diff --git a/src/librustc/middle/typeck/check/_match.rs b/src/librustc/middle/typeck/check/_match.rs index e198653165a61..fd89423f304ca 100644 --- a/src/librustc/middle/typeck/check/_match.rs +++ b/src/librustc/middle/typeck/check/_match.rs @@ -726,22 +726,38 @@ pub fn check_pat(pcx: &pat_ctxt, pat: &ast::Pat, expected: ty::t) { } // 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", 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); } _ => { diff --git a/src/test/compile-fail/destructure-trait-ref.rs b/src/test/compile-fail/destructure-trait-ref.rs new file mode 100644 index 0000000000000..671bf45c9338f --- /dev/null +++ b/src/test/compile-fail/destructure-trait-ref.rs @@ -0,0 +1,41 @@ +// 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 or the MIT license +// , 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; //~ 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; //~ ERROR found a box pattern +} diff --git a/src/test/compile-fail/issue-4972.rs b/src/test/compile-fail/issue-4972.rs index ffac6b499f4c1..edd6932aec6f0 100644 --- a/src/test/compile-fail/issue-4972.rs +++ b/src/test/compile-fail/issue-4972.rs @@ -17,7 +17,7 @@ pub enum TraitWrapper { fn get_tw_map<'lt>(tw: &'lt TraitWrapper) -> &'lt MyTrait { match *tw { - A(box ref map) => map, //~ ERROR found a box pattern + A(box ref map) => map, //~ ERROR cannot be dereferenced } }