]> git.lizzy.rs Git - rust.git/commitdiff
Suggest solutions for `fn foo(&foo: Foo)`
authorEsteban Küber <esteban@kuber.com.ar>
Sun, 25 Dec 2016 01:44:41 +0000 (17:44 -0800)
committerEsteban Küber <esteban@kuber.com.ar>
Wed, 28 Dec 2016 23:25:09 +0000 (15:25 -0800)
src/librustc_typeck/check/_match.rs
src/librustc_typeck/check/demand.rs
src/librustc_typeck/check/mod.rs
src/librustc_typeck/check/wfcheck.rs
src/test/ui/mismatched_types/issue-38371.rs [new file with mode: 0644]
src/test/ui/mismatched_types/issue-38371.stderr [new file with mode: 0644]

index 9b86196b3ece234b91eb760575bd23989362d14d..fcd61b3c7c8c952e68cbf9c244b363d3c06f2842 100644 (file)
 
 impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
     pub fn check_pat(&self, pat: &'gcx hir::Pat, expected: Ty<'tcx>) {
+        self.check_pat_arg(pat, expected, false);
+    }
+
+    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);
@@ -212,7 +216,22 @@ pub fn check_pat(&self, pat: &'gcx hir::Pat, expected: Ty<'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);
-                            self.demand_eqtype(pat.span, expected, rptr_ty);
+                            let err = self.demand_eqtype_diag(pat.span, expected, rptr_ty);
+                            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,
+                                                          expected));
+                                        err.help(&format!("did you mean `{}: {}`?",
+                                                          &snippet[1..],
+                                                          expected));
+                                    }
+                                }
+                                err.emit();
+                            }
                             (rptr_ty, inner_ty)
                         }
                     };
index 393d9341a08432151876eb73941c90d3e5d50964..8838eb9b1b3ff78b8f5eca14740a1852a5776d4b 100644 (file)
@@ -19,6 +19,7 @@
 use rustc::hir;
 use rustc::hir::def::Def;
 use rustc::ty::{self, AssociatedItem};
+use errors::DiagnosticBuilder;
 
 use super::method::probe;
 
@@ -38,20 +39,29 @@ pub fn demand_suptype(&self, sp: Span, expected: Ty<'tcx>, actual: Ty<'tcx>) {
     }
 
     pub fn demand_eqtype(&self, sp: Span, expected: Ty<'tcx>, actual: Ty<'tcx>) {
-        self.demand_eqtype_with_origin(&self.misc(sp), expected, actual);
+        if let Some(mut err) = self.demand_eqtype_diag(sp, expected, actual) {
+            err.emit();
+        }
+    }
+
+    pub fn demand_eqtype_diag(&self,
+                             sp: Span,
+                             expected: Ty<'tcx>,
+                             actual: Ty<'tcx>) -> Option<DiagnosticBuilder<'tcx>> {
+        self.demand_eqtype_with_origin(&self.misc(sp), expected, actual)
     }
 
     pub fn demand_eqtype_with_origin(&self,
                                      cause: &ObligationCause<'tcx>,
                                      expected: Ty<'tcx>,
-                                     actual: Ty<'tcx>)
-    {
+                                     actual: Ty<'tcx>) -> Option<DiagnosticBuilder<'tcx>> {
         match self.eq_types(false, cause, actual, expected) {
             Ok(InferOk { obligations, value: () }) => {
                 self.register_predicates(obligations);
+                None
             },
             Err(e) => {
-                self.report_mismatched_types(cause, expected, actual, e).emit();
+                Some(self.report_mismatched_types(cause, expected, actual, e))
             }
         }
     }
index 7275fbd12036b308768b7fc53259bf3c8e28384b..b89654138dd135624418aacf7ae79972c4c49a3d 100644 (file)
@@ -798,7 +798,7 @@ fn check_fn<'a, 'gcx, 'tcx>(inherited: &'a Inherited<'a, 'gcx, 'tcx>,
         fcx.register_old_wf_obligation(arg_ty, arg.pat.span, traits::MiscObligation);
 
         // Check the pattern.
-        fcx.check_pat(&arg.pat, arg_ty);
+        fcx.check_pat_arg(&arg.pat, arg_ty, true);
         fcx.write_ty(arg.id, arg_ty);
     }
 
index c80db7fa4d0e02b47c5ab4b2b800f63f8065b886..4c124cdd60c0fbc34bdf3c2db05cd29425b6f036 100644 (file)
@@ -505,7 +505,9 @@ fn check_method_receiver<'fcx, 'tcx>(&mut self,
         debug!("check_method_receiver: receiver ty = {:?}", rcvr_ty);
 
         let cause = fcx.cause(span, ObligationCauseCode::MethodReceiver);
-        fcx.demand_eqtype_with_origin(&cause, rcvr_ty, self_arg_ty);
+        if let Some(mut err) = fcx.demand_eqtype_with_origin(&cause, rcvr_ty, self_arg_ty) {
+            err.emit();
+        }
     }
 
     fn check_variances_for_type_defn(&self,
diff --git a/src/test/ui/mismatched_types/issue-38371.rs b/src/test/ui/mismatched_types/issue-38371.rs
new file mode 100644 (file)
index 0000000..2099844
--- /dev/null
@@ -0,0 +1,26 @@
+// Copyright 2016 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.
+
+struct Foo {
+}
+
+fn foo(&foo: Foo) {  // illegal syntax
+}
+
+fn bar(foo: Foo) {  // legal
+}
+
+fn qux(foo: &Foo) {  // legal
+}
+
+fn zar(&foo: &Foo) {  // legal
+}
+
+fn main() {}
diff --git a/src/test/ui/mismatched_types/issue-38371.stderr b/src/test/ui/mismatched_types/issue-38371.stderr
new file mode 100644 (file)
index 0000000..8b27218
--- /dev/null
@@ -0,0 +1,13 @@
+error[E0308]: mismatched types
+  --> $DIR/issue-38371.rs:14:8
+   |
+14 | fn foo(&foo: Foo) {  // illegal syntax
+   |        ^^^^ expected struct `Foo`, found reference
+   |
+   = note: expected type `Foo`
+   = note:    found type `&_`
+   = help: did you mean `&foo: &Foo`?
+   = help: did you mean `foo: Foo`?
+
+error: aborting due to previous error
+