about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorNiko Matsakis <niko@alum.mit.edu>2017-01-10 14:45:30 -0500
committerNiko Matsakis <niko@alum.mit.edu>2017-01-10 14:47:58 -0500
commit59d7d4c80ef94ec5b001ffe1a8bac40694c50c3f (patch)
tree7063a25edd98023f4f9a6f3d2f6bd8c2e13a22a4 /src
parent563ecc1b1fe8f8daea20910a23b7090411cf2de8 (diff)
only emit suggestion to move `&` if the inner pattern is a binding
Diffstat (limited to 'src')
-rw-r--r--src/librustc_typeck/check/_match.rs25
1 files changed, 18 insertions, 7 deletions
diff --git a/src/librustc_typeck/check/_match.rs b/src/librustc_typeck/check/_match.rs
index f05c9a00be2..f7fd78097b8 100644
--- a/src/librustc_typeck/check/_match.rs
+++ b/src/librustc_typeck/check/_match.rs
@@ -30,10 +30,14 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
         self.check_pat_arg(pat, expected, false);
     }
 
+    /// The `is_arg` argument indicates whether this pattern is the
+    /// *outermost* pattern in an argument (e.g., in `fn foo(&x:
+    /// &u32)`, it is true for the `&x` pattern but not `x`). This is
+    /// used to tailor error reporting.
     pub fn check_pat_arg(&self, pat: &'gcx hir::Pat, expected: Ty<'tcx>, is_arg: bool) {
         let tcx = self.tcx;
 
-        debug!("check_pat(pat={:?},expected={:?})", pat, expected);
+        debug!("check_pat(pat={:?},expected={:?},is_arg={})", pat, expected, is_arg);
 
         let ty = match pat.node {
             PatKind::Wild => {
@@ -206,6 +210,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
                     // can, to avoid creating needless variables.  This
                     // also helps with the bad interactions of the given
                     // hack detailed in (*) below.
+                    debug!("check_pat_arg: expected={:?}", expected);
                     let (rptr_ty, inner_ty) = match expected.sty {
                         ty::TyRef(_, mt) if mt.mutbl == mutbl => {
                             (expected, mt.ty)
@@ -216,15 +221,21 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
                             let mt = ty::TypeAndMut { ty: inner_ty, mutbl: mutbl };
                             let region = self.next_region_var(infer::PatternRegion(pat.span));
                             let rptr_ty = tcx.mk_ref(region, mt);
+                            debug!("check_pat_arg: demanding {:?} = {:?}", expected, rptr_ty);
                             let err = self.demand_eqtype_diag(pat.span, expected, rptr_ty);
+
+                            // Look for a case like `fn foo(&foo: u32)` and suggest
+                            // `fn foo(foo: &u32)`
                             if let Some(mut err) = err {
                                 if is_arg {
-                                    if let Ok(snippet) = self.sess().codemap()
-                                        .span_to_snippet(pat.span)
-                                    {
-                                        err.help(&format!("did you mean `{}: &{}`?",
-                                                          &snippet[1..],
-                                                          expected));
+                                    if let PatKind::Binding(..) = inner.node {
+                                        if let Ok(snippet) = self.sess().codemap()
+                                                                        .span_to_snippet(pat.span)
+                                        {
+                                            err.help(&format!("did you mean `{}: &{}`?",
+                                                              &snippet[1..],
+                                                              expected));
+                                        }
                                     }
                                 }
                                 err.emit();