}
// Helper function to check gc, box and & patterns
-pub fn check_pointer_pat(pcx: &pat_ctxt,
- pointer_kind: PointerKind,
- inner: &ast::Pat,
- pat_id: ast::NodeId,
- span: Span,
- expected: ty::t) {
+fn check_pointer_pat(pcx: &pat_ctxt,
+ pointer_kind: PointerKind,
+ inner: &ast::Pat,
+ pat_id: ast::NodeId,
+ span: Span,
+ expected: ty::t) {
let fcx = pcx.fcx;
+ let tcx = fcx.ccx.tcx;
let check_inner: |ty::t| = |e_inner| {
- check_pat(pcx, inner, e_inner);
- fcx.write_ty(pat_id, expected);
+ match ty::get(e_inner).sty {
+ ty::ty_trait(_) if pat_is_binding(&tcx.def_map, inner) => {
+ // This is "x = SomeTrait" being reduced from
+ // "let &x = &SomeTrait" or "let box x = Box<SomeTrait>", an error.
+ check_pat(pcx, inner, ty::mk_err());
+ tcx.sess.span_err(
+ span,
+ format!("type `{}` cannot be dereferenced",
+ fcx.infcx().ty_to_str(expected)).as_slice());
+ fcx.write_error(pat_id);
+ }
+ _ => {
+ check_pat(pcx, inner, e_inner);
+ fcx.write_ty(pat_id, expected);
+ }
+ }
};
+
match *structure_of(fcx, span, expected) {
- ty::ty_uniq(e_inner) if pointer_kind == Send && !ty::type_is_trait(e_inner) => {
+ ty::ty_uniq(e_inner) if pointer_kind == Send => {
check_inner(e_inner);
}
- ty::ty_rptr(_, e_inner) if pointer_kind == Borrowed && !ty::type_is_trait(e_inner.ty) => {
+ ty::ty_rptr(_, e_inner) if pointer_kind == Borrowed => {
check_inner(e_inner.ty);
}
_ => {
--- /dev/null
+// Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// The regression test for #15031 to make sure destructuring trait
+// reference work properly.
+
+trait T {}
+impl T for int {}
+
+fn main() {
+ // For an expression of the form:
+ //
+ // let &...&x = &..&SomeTrait;
+ //
+ // Say we have n `&` at the left hand and m `&` right hand, then:
+ // if n < m, we are golden;
+ // if n == m, it's a derefing non-derefable type error;
+ // if n > m, it's a type mismatch error.
+
+ // n < m
+ let &x = &(&1 as &T);
+ let &x = &&(&1 as &T);
+ let &&x = &&(&1 as &T);
+
+ // n == m
+ let &x = &1 as &T; //~ ERROR cannot be dereferenced
+ let &&x = &(&1 as &T); //~ ERROR cannot be dereferenced
+ let box x = box 1 as Box<T>; //~ ERROR cannot be dereferenced
+
+ // n > m
+ let &&x = &1 as &T; //~ ERROR found an `&`-pointer pattern
+ let &&&x = &(&1 as &T); //~ ERROR found an `&`-pointer pattern
+ let box box x = box 1 as Box<T>; //~ ERROR found a box pattern
+}