]> git.lizzy.rs Git - rust.git/commitdiff
Improve error message for uninferrable types #38812
authorCengiz Can <cengizc@gmail.com>
Tue, 24 Jan 2017 15:19:36 +0000 (15:19 +0000)
committerCengiz Can <cengizc@gmail.com>
Sat, 4 Feb 2017 21:25:56 +0000 (16:25 -0500)
20 files changed:
src/librustc/traits/error_reporting.rs
src/test/compile-fail/issue-12187-1.rs
src/test/compile-fail/issue-12187-2.rs
src/test/compile-fail/issue-17551.rs
src/test/compile-fail/issue-18159.rs
src/test/compile-fail/issue-23041.rs
src/test/compile-fail/issue-23046.rs
src/test/compile-fail/issue-24013.rs
src/test/compile-fail/issue-5062.rs
src/test/compile-fail/issue-6458-2.rs
src/test/compile-fail/issue-6458-3.rs
src/test/compile-fail/issue-6458.rs
src/test/compile-fail/issue-7813.rs
src/test/compile-fail/method-ambig-one-trait-unknown-int-type.rs
src/test/compile-fail/traits-multidispatch-convert-ambig-dest.rs
src/test/compile-fail/unconstrained-none.rs
src/test/compile-fail/unconstrained-ref.rs
src/test/compile-fail/vector-no-ann.rs
src/test/ui/codemap_tests/repair_span_std_macros.stderr
src/test/ui/missing-items/missing-type-parameter.stderr

index 661d47199df13991861ca3023eeb302a4a9d6931..4d45f82a15863ec7b54bbc30c27d8cabf276d5f3 100644 (file)
@@ -39,6 +39,8 @@
 use std::cmp;
 use std::fmt;
 use syntax::ast;
+use hir::{intravisit, Local, Pat};
+use hir::intravisit::{Visitor, NestedVisitorMap};
 use syntax_pos::{DUMMY_SP, Span};
 use errors::DiagnosticBuilder;
 
@@ -60,6 +62,30 @@ fn from_error(infcx: &InferCtxt<'a, 'gcx, 'tcx>,
     }
 }
 
+struct FindLocalByTypeVisitor<'a, 'gcx: 'a + 'tcx, 'tcx: 'a> {
+    infcx: &'a InferCtxt<'a, 'gcx, 'tcx>,
+    target_ty: &'a Ty<'tcx>,
+    found_pattern: Option<&'a Pat>,
+}
+
+impl<'a, 'gcx, 'tcx> Visitor<'a> for FindLocalByTypeVisitor<'a, 'gcx, 'tcx> {
+    fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'a> {
+        NestedVisitorMap::None
+    }
+
+    fn visit_local(&mut self, local: &'a Local) {
+        if let Some(&ty) = self.infcx.tables.borrow().node_types.get(&local.id) {
+            let ty = self.infcx.resolve_type_vars_if_possible(&ty);
+            let is_match = ty.walk().any(|t| t == *self.target_ty);
+
+            if is_match && self.found_pattern.is_none() {
+                self.found_pattern = Some(&*local.pat);
+            }
+        }
+        intravisit::walk_local(self, local);
+    }
+}
+
 impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
     pub fn report_fulfillment_errors(&self, errors: &Vec<FulfillmentError<'tcx>>) {
         for error in errors {
@@ -775,7 +801,7 @@ fn maybe_report_ambiguity(&self, obligation: &PredicateObligation<'tcx>) {
                             self.tcx.lang_items.sized_trait()
                             .map_or(false, |sized_id| sized_id == trait_ref.def_id())
                         {
-                            self.need_type_info(obligation.cause.span, self_ty);
+                            self.need_type_info(obligation, self_ty);
                         } else {
                             let mut err = struct_span_err!(self.tcx.sess,
                                                            obligation.cause.span, E0283,
@@ -793,7 +819,7 @@ fn maybe_report_ambiguity(&self, obligation: &PredicateObligation<'tcx>) {
                 // Same hacky approach as above to avoid deluging user
                 // with error messages.
                 if !ty.references_error() && !self.tcx.sess.has_errors() {
-                    self.need_type_info(obligation.cause.span, ty);
+                    self.need_type_info(obligation, ty);
                 }
             }
 
@@ -858,26 +884,42 @@ fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
     }
 
 
-    fn need_type_info(&self, span: Span, ty: Ty<'tcx>) {
+    fn need_type_info(&self,
+                      obligation: &PredicateObligation<'tcx>,
+                      ty: Ty<'tcx>) {
+
         let ty = self.resolve_type_vars_if_possible(&ty);
-        let name = if let ty::TyInfer(ty::TyVar(ty_vid)) = ty.sty {
-            let ty_vars = self.type_variables.borrow();
-            if let TypeVariableOrigin::TypeParameterDefinition(_, name) =
-                    *ty_vars.var_origin(ty_vid)
-            {
-                name.to_string()
+        let ref cause = obligation.cause;
+
+        let mut err = struct_span_err!(self.tcx.sess,
+                                       cause.span,
+                                       E0282,
+                                       "unable to fully infer type(s)");
+
+        err.note("type annotations or generic parameter binding required");
+        err.span_label(cause.span, &format!("cannot infer type"));
+
+        let expr = self.tcx.hir.expect_expr(cause.body_id);
+
+        let mut local_visitor = FindLocalByTypeVisitor {
+            infcx: &self,
+            target_ty: &ty,
+            found_pattern: None
+        };
+
+        local_visitor.visit_expr(expr);
+
+        if let Some(pattern) = local_visitor.found_pattern {
+            let pattern_span = pattern.span;
+            if let Some(n) = pattern.simple_name() {
+                err.span_label(pattern_span,
+                    &format!("annotating the type for the variable `{}` would help", n));
             } else {
-                ty.to_string()
+                err.span_label(pattern_span,
+                    &format!("annotating the type of pattern would help"));
             }
-        } else {
-            ty.to_string()
-        };
+        }
 
-        let mut err = struct_span_err!(self.tcx.sess, span, E0282,
-                                       "unable to infer enough type information about `{}`",
-                                       name);
-        err.note("type annotations or generic parameter binding required");
-        err.span_label(span, &format!("cannot infer type for `{}`", name));
         err.emit();
     }
 
index 001e4b51bebc4f619beaa84665fb38a7d6ecf525..8f9b897eae22452dbb4905b974d2c1f31c535b3f 100644 (file)
@@ -14,7 +14,7 @@ fn new<T>() -> &'static T {
 
 fn main() {
     let &v = new();
-    //~^ ERROR unable to infer enough type information about `_` [E0282]
-    //~| NOTE cannot infer type for `_`
+    //~^ ERROR unable to fully infer type(s) [E0282]
+    //~| NOTE cannot infer type
     //~| NOTE type annotations or generic parameter binding
 }
index 7cbee402b368253cb59845e912ed357307f77f33..29ae04a3aaca679840bde14b9d00eb2a993fa887 100644 (file)
@@ -14,7 +14,7 @@ fn new<'r, T>() -> &'r T {
 
 fn main() {
     let &v = new();
-    //~^ ERROR unable to infer enough type information about `_` [E0282]
-    //~| NOTE cannot infer type for `_`
+    //~^ ERROR unable to fully infer type(s) [E0282]
+    //~| NOTE cannot infer type
     //~| NOTE type annotations or generic parameter binding
 }
index 5e69553d3a48532e1a78b6a50a60f4e9441cf98e..332d3fb3e2bedeb86db73c40b2ee29070abf5b18 100644 (file)
@@ -13,6 +13,6 @@
 struct B<T>(marker::PhantomData<T>);
 
 fn main() {
-    let foo = B(marker::PhantomData); //~ ERROR unable to infer enough type information
+    let foo = B(marker::PhantomData); //~ ERROR unable to fully infer type(s)
     let closure = || foo;
 }
index e46bcf46cc3983dca3e36ab72d65278b3db1bb23..7338d2cb41864d0b1f1a69b723856936076d2ee0 100644 (file)
@@ -9,5 +9,5 @@
 // except according to those terms.
 
 fn main() {
-    let x; //~ ERROR unable to infer enough type information
+    let x; //~ ERROR unable to fully infer type(s)
 }
index 1be082ba9bbbad454982a42a82d8ce3e7c4b6361..f67d8affd30e7e30cb0c6556b938a0f150a762b5 100644 (file)
@@ -14,6 +14,6 @@ fn main()
     fn bar(x:i32) ->i32 { 3*x };
     let b:Box<Any> = Box::new(bar as fn(_)->_);
     b.downcast_ref::<fn(_)->_>(); //~ ERROR E0282
-                                  //~| NOTE cannot infer type for `_`
+                                  //~| NOTE cannot infer type
                                   //~| NOTE type annotations or generic parameter binding required
 }
index c274665530fdb67f28b8108f4353b6adfe1265be..c80923298bca91e4b4877a5f2b106bebb1378d4b 100644 (file)
@@ -25,6 +25,6 @@ pub fn let_<'var, VAR, F: for<'v: 'var> Fn(Expr<'v, VAR>) -> Expr<'v, VAR>>
 
 fn main() {
     let ex = |x| {
-        let_(add(x,x), |y| { //~ ERROR unable to infer enough type information about `VAR`
+        let_(add(x,x), |y| { //~ ERROR unable to fully infer type(s)
             let_(add(x, x), |x|x)})};
 }
index df857a2e6eb1f9766a2cefabd0234aedf1b275dc..edd876ed6639c253564c12ba7b8defb6574cf745 100644 (file)
@@ -13,5 +13,5 @@ fn main() {
     let a = 1;
     let b = 2;
     unsafe {swap::<&mut _>(transmute(&a), transmute(&b))};
-    //~^ ERROR unable to infer enough type information about `_`
+    //~^ ERROR unable to fully infer type(s)
 }
index cf78d6d8c0ad4715686519707a9b3e8050962318..e61ca92c78a10cd42dec2cc065d9873ee3224c27 100644 (file)
@@ -9,4 +9,4 @@
 // except according to those terms.
 
 fn main() { format!("{:?}", None); }
-    //~^ ERROR unable to infer enough type information about `T` [E0282]
+    //~^ ERROR unable to fully infer type(s) [E0282]
index 3816896d43d1f47533d3bad1366161d95f3b1472..77eb8b3e7a95da381e22b0acd4de5aeb305e0a11 100644 (file)
@@ -11,5 +11,5 @@
 fn main() {
     // Unconstrained type:
     format!("{:?}", None);
-    //~^ ERROR unable to infer enough type information about `T` [E0282]
+    //~^ ERROR unable to fully infer type(s) [E0282]
 }
index 8029522f5d3cc9cdb3bb696c769c50032dc4e6ce..a8ad8951c648130418f72b0ef8a73b6a7dc9f761 100644 (file)
@@ -12,7 +12,7 @@
 
 fn main() {
     mem::transmute(0);
-    //~^ ERROR unable to infer enough type information about `U` [E0282]
-    //~| NOTE cannot infer type for `U`
+    //~^ ERROR unable to fully infer type(s) [E0282]
+    //~| NOTE cannot infer type
     //~| NOTE type annotations or generic parameter binding
 }
index f8354ddbf12a58df5563eb80639a3dfb1cfab696..7d1b5cfffe4bfa08d0bc4c31bde9bd33bce14bb5 100644 (file)
@@ -17,8 +17,8 @@ pub fn foo<State>(_: TypeWithState<State>) {}
 
 pub fn bar() {
    foo(TypeWithState(marker::PhantomData));
-   //~^ ERROR unable to infer enough type information about `State` [E0282]
-   //~| NOTE cannot infer type for `State`
+   //~^ ERROR unable to fully infer type(s) [E0282]
+   //~| NOTE cannot infer type
    //~| NOTE type annotations or generic parameter binding
 }
 
index e37a881642393fd9400a7f2fe0d2ea24c6521171..c7510f215bed09a6abd7a22a732938400b4bde20 100644 (file)
@@ -10,7 +10,8 @@
 
 fn main() {
     let v = &[];
-    let it = v.iter(); //~ ERROR unable to infer enough type information about `T` [E0282]
-                       //~| NOTE cannot infer type for `T`
+    let it = v.iter(); //~ ERROR unable to fully infer type(s) [E0282]
+                       //~| NOTE cannot infer type
+                       //~| NOTE annotating the type for the variable `it` would help
                        //~| NOTE type annotations or generic parameter binding
 }
index 1cf41f95a2d6d8bc977ad375defe266ed85c20cb..eeecefd91aef7a08c8c1f93432141192d17ea261 100644 (file)
@@ -32,7 +32,7 @@ fn foo(&self) -> isize {2}
 fn m1() {
     // we couldn't infer the type of the vector just based on calling foo()...
     let mut x = Vec::new();
-    //~^ ERROR unable to infer enough type information about `T` [E0282]
+    //~^ ERROR unable to fully infer type(s) [E0282]
     x.foo();
 }
 
index ed2ffa995e521ce188e83b8c5de832f6868a196c..6ccd8f66a492c155ecfddd218d64a4e0444c6d85 100644 (file)
@@ -34,8 +34,8 @@ fn test<T,U>(_: T, _: U)
 
 fn a() {
     test(22, std::default::Default::default());
-    //~^ ERROR unable to infer enough type information about `U` [E0282]
-    //~| NOTE cannot infer type for `U`
+    //~^ ERROR unable to fully infer type(s) [E0282]
+    //~| NOTE cannot infer type
     //~| NOTE type annotations or generic parameter binding
 }
 
index 88080bc70cab4e404a65c97108b7889ba42ff7b1..49818791d2fc51449ac03d624a88f71dfe8c1415 100644 (file)
@@ -11,7 +11,7 @@
 // Issue #5062
 
 fn main() {
-    None; //~ ERROR unable to infer enough type information about `T` [E0282]
-          //~| NOTE cannot infer type for `T`
+    None; //~ ERROR unable to fully infer type(s) [E0282]
+          //~| NOTE cannot infer type
           //~| NOTE type annotations or generic parameter binding
 }
index 12278549215ed132deca9b9cb4584dc78d74fbbc..53995af5b86700f8ca274801dd3fa2792ccb3528 100644 (file)
@@ -13,7 +13,7 @@ struct S<'a, T:'a> {
 }
 
 fn main() {
-    S { o: &None }; //~ ERROR unable to infer enough type information about `T` [E0282]
-                    //~| NOTE cannot infer type for `T`
+    S { o: &None }; //~ ERROR unable to fully infer type(s) [E0282]
+                    //~| NOTE cannot infer type
                     //~| NOTE type annotations or generic parameter binding
 }
index d559caf77a1a37944dedf9d43f7bb6cdf1acd583..d470f937190bbef1b4a3d6d0a69bd6e8e2b0f6c8 100644 (file)
@@ -11,7 +11,8 @@
 
 fn main() {
     let _foo = Vec::new();
-    //~^ ERROR unable to infer enough type information about `T` [E0282]
-    //~| NOTE cannot infer type for `T`
+    //~^ ERROR unable to fully infer type(s) [E0282]
+    //~| NOTE cannot infer type
+    //~| NOTE annotating the type for the variable `_foo` would help
     //~| NOTE type annotations or generic parameter binding
 }
index 7e0d778a3b205e431bd5ee8b58d7f692292e4867..f0be8d07f49bd4b1dcacd7a9db0a0c55db9960fe 100644 (file)
@@ -1,11 +1,14 @@
-error[E0282]: unable to infer enough type information about `T`
+error[E0282]: unable to fully infer type(s)
   --> $DIR/repair_span_std_macros.rs:12:13
    |
 12 |     let x = vec![];
-   |             ^^^^^^ cannot infer type for `T`
+   |         -   ^^^^^^ cannot infer type
+   |         |
+   |         annotating the type for the variable `x` would help
    |
    = note: type annotations or generic parameter binding required
    = note: this error originates in a macro outside of the current crate
 
 error: aborting due to previous error
 
+
index 2d007af4980b208aad23781e8478e5d385ae2bdf..df5571787d7bc5110b91ab08027bbf887e142e69 100644 (file)
@@ -1,10 +1,11 @@
-error[E0282]: unable to infer enough type information about `X`
+error[E0282]: unable to fully infer type(s)
   --> $DIR/missing-type-parameter.rs:14:5
    |
 14 |     foo();
-   |     ^^^ cannot infer type for `X`
+   |     ^^^ cannot infer type
    |
    = note: type annotations or generic parameter binding required
 
 error: aborting due to previous error
 
+