about summary refs log tree commit diff
diff options
context:
space:
mode:
authorEsteban Küber <esteban@kuber.com.ar>2019-05-30 15:33:13 -0700
committerEsteban Küber <esteban@kuber.com.ar>2019-05-31 18:33:59 -0700
commit74fb3bbee45d54e1680832ba064fa1af8d344bc0 (patch)
tree01ab612bf99564ee00c8815ec1ec07d84c41deb9
parent65c2a7b18bb34547de7c716ace2e8878c2676794 (diff)
downloadrust-74fb3bbee45d54e1680832ba064fa1af8d344bc0.tar.gz
rust-74fb3bbee45d54e1680832ba064fa1af8d344bc0.zip
On type inference errors use the type argument name when possible
```
error[E0282]: type annotations needed in `std::result::Result<i32, E>`
 --> file7.rs:3:13
  |
3 |     let b = Ok(4);
  |         -   ^^ cannot infer type for `E` in `std::result::Result<i32, E>`
  |         |
  |         consider giving `b` a type`
```
-rw-r--r--src/librustc/infer/error_reporting/need_type_info.rs52
-rw-r--r--src/librustc/ty/print/pretty.rs23
-rw-r--r--src/test/ui/issues/issue-12187-1.stderr2
-rw-r--r--src/test/ui/issues/issue-12187-2.stderr2
-rw-r--r--src/test/ui/issues/issue-17551.stderr4
-rw-r--r--src/test/ui/issues/issue-23046.stderr4
-rw-r--r--src/test/ui/issues/issue-25368.stderr4
-rw-r--r--src/test/ui/methods/method-ambig-one-trait-unknown-int-type.stderr4
-rw-r--r--src/test/ui/type/type-check/cannot_infer_local_or_vec.stderr4
-rw-r--r--src/test/ui/type/type-check/cannot_infer_local_or_vec_in_tuples.stderr4
-rw-r--r--src/test/ui/unboxed-closures/unboxed-closures-failed-recursive-fn-2.stderr2
-rw-r--r--src/test/ui/vector-no-ann.stderr4
12 files changed, 81 insertions, 28 deletions
diff --git a/src/librustc/infer/error_reporting/need_type_info.rs b/src/librustc/infer/error_reporting/need_type_info.rs
index aae7b5e1202..85ff1cbc9e4 100644
--- a/src/librustc/infer/error_reporting/need_type_info.rs
+++ b/src/librustc/infer/error_reporting/need_type_info.rs
@@ -15,7 +15,7 @@ struct FindLocalByTypeVisitor<'a, 'gcx: 'a + 'tcx, 'tcx: 'a> {
     hir_map: &'a hir::map::Map<'gcx>,
     found_local_pattern: Option<&'gcx Pat>,
     found_arg_pattern: Option<&'gcx Pat>,
-    found_ty: Option<String>,
+    found_ty: Option<Ty<'tcx>>,
 }
 
 impl<'a, 'gcx, 'tcx> FindLocalByTypeVisitor<'a, 'gcx, 'tcx> {
@@ -55,7 +55,7 @@ impl<'a, 'gcx, 'tcx> Visitor<'gcx> for FindLocalByTypeVisitor<'a, 'gcx, 'tcx> {
     fn visit_local(&mut self, local: &'gcx Local) {
         if let (None, Some(ty)) = (self.found_local_pattern, self.node_matches_type(local.hir_id)) {
             self.found_local_pattern = Some(&*local.pat);
-            self.found_ty = Some(ty.to_string());
+            self.found_ty = Some(ty);
         }
         intravisit::walk_local(self, local);
     }
@@ -67,7 +67,7 @@ impl<'a, 'gcx, 'tcx> Visitor<'gcx> for FindLocalByTypeVisitor<'a, 'gcx, 'tcx> {
                 self.node_matches_type(argument.hir_id),
             ) {
                 self.found_arg_pattern = Some(&*argument.pat);
-                self.found_ty = Some(ty.to_string());
+                self.found_ty = Some(ty);
             }
         }
         intravisit::walk_body(self, body);
@@ -117,14 +117,43 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
             found_arg_pattern: None,
             found_ty: None,
         };
+        let ty_to_string = |ty: Ty<'tcx>| -> String {
+            let mut s = String::new();
+            let mut printer = ty::print::FmtPrinter::new(self.tcx, &mut s, Namespace::TypeNS);
+            let ty_vars = self.type_variables.borrow();
+            let getter = move |ty_vid| {
+                if let TypeVariableOrigin::TypeParameterDefinition(_, name) =
+                    *ty_vars.var_origin(ty_vid) {
+                    return Some(name.to_string());
+                }
+                None
+            };
+            printer.name_resolver = Some(Box::new(&getter));
+            let _ = ty.print(printer);
+            s
+        };
 
         if let Some(body_id) = body_id {
             let expr = self.tcx.hir().expect_expr_by_hir_id(body_id.hir_id);
             local_visitor.visit_expr(expr);
         }
 
+        // When `name` corresponds to a type argument, show the path of the full type we're
+        // trying to infer. In the following example, `ty_msg` contains
+        // " in `std::result::Result<i32, E>`":
+        // ```
+        // error[E0282]: type annotations needed in `std::result::Result<i32, E>`
+        //  --> file.rs:L:CC
+        //   |
+        // L |     let b = Ok(4);
+        //   |         -   ^^ cannot infer type for `E` in `std::result::Result<i32, E>`
+        //   |         |
+        //   |         consider giving `b` a type
+        // ```
         let ty_msg = match &local_visitor.found_ty {
-            Some(ty) if &ty[..] != "_" && ty != &name => format!(" in `{}`", ty),
+            Some(ty) if &ty.to_string() != "_" && ty.to_string() != name => {
+                format!(" in `{}`", ty_to_string(ty))
+            }
             _ => String::new(),
         };
         let mut labels = vec![(span, InferCtxt::missing_type_msg(&name, &ty_msg))];
@@ -144,17 +173,20 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
             // After clearing, it looks something like this:
             // ```
             // let x = |_| {  };
-            //          ^ consider giving this closure parameter a type
+            //          ^ consider giving this closure parameter the type `[_; 0]`
+            //            with the type parameter `_` specified
             // ```
             labels.clear();
             labels.push((pattern.span, format!(
                 "consider giving this closure parameter {}",
                 match &local_visitor.found_ty {
-                    Some(ty) if &ty[..] != "_" && ty != &name => format!(
-                        "the type `{}` with the type parameter `{}` specified",
-                        ty,
-                        name,
-                    ),
+                    Some(ty) if &ty.to_string() != "_" && ty.to_string() != name => {
+                        format!(
+                            "the type `{}` with the type parameter `{}` specified",
+                            ty_to_string(ty),
+                            name,
+                        )
+                    }
                     _ => "a type".to_owned(),
                 },
             )));
diff --git a/src/librustc/ty/print/pretty.rs b/src/librustc/ty/print/pretty.rs
index a246d9652f2..cd617a9368d 100644
--- a/src/librustc/ty/print/pretty.rs
+++ b/src/librustc/ty/print/pretty.rs
@@ -483,7 +483,17 @@ pub trait PrettyPrinter<'gcx: 'tcx, 'tcx>:
             ty::FnPtr(ref bare_fn) => {
                 p!(print(bare_fn))
             }
-            ty::Infer(infer_ty) => p!(write("{}", infer_ty)),
+            ty::Infer(infer_ty) => {
+                if let ty::TyVar(ty_vid) = infer_ty {
+                    if let Some(name) = self.infer_ty_name(ty_vid) {
+                        p!(write("{}", name))
+                    } else {
+                        p!(write("{}", infer_ty))
+                    }
+                } else {
+                    p!(write("{}", infer_ty))
+                }
+            },
             ty::Error => p!(write("[type error]")),
             ty::Param(ref param_ty) => p!(write("{}", param_ty)),
             ty::Bound(debruijn, bound_ty) => {
@@ -681,6 +691,10 @@ pub trait PrettyPrinter<'gcx: 'tcx, 'tcx>:
         Ok(self)
     }
 
+    fn infer_ty_name(&self, _: ty::TyVid) -> Option<String> {
+        None
+    }
+
     fn pretty_print_dyn_existential(
         mut self,
         predicates: &'tcx ty::List<ty::ExistentialPredicate<'tcx>>,
@@ -931,6 +945,8 @@ pub struct FmtPrinterData<'a, 'gcx, 'tcx, F> {
     binder_depth: usize,
 
     pub region_highlight_mode: RegionHighlightMode,
+
+    pub name_resolver: Option<Box<&'a dyn Fn(ty::sty::TyVid) -> Option<String>>>,
 }
 
 impl<F> Deref for FmtPrinter<'a, 'gcx, 'tcx, F> {
@@ -957,6 +973,7 @@ impl<F> FmtPrinter<'a, 'gcx, 'tcx, F> {
             region_index: 0,
             binder_depth: 0,
             region_highlight_mode: RegionHighlightMode::default(),
+            name_resolver: None,
         }))
     }
 }
@@ -1206,6 +1223,10 @@ impl<F: fmt::Write> Printer<'gcx, 'tcx> for FmtPrinter<'_, 'gcx, 'tcx, F> {
 }
 
 impl<F: fmt::Write> PrettyPrinter<'gcx, 'tcx> for FmtPrinter<'_, 'gcx, 'tcx, F> {
+    fn infer_ty_name(&self, id: ty::TyVid) -> Option<String> {
+        self.0.name_resolver.as_ref().and_then(|func| func(id))
+    }
+
     fn print_value_path(
         mut self,
         def_id: DefId,
diff --git a/src/test/ui/issues/issue-12187-1.stderr b/src/test/ui/issues/issue-12187-1.stderr
index 510eeb4b9bb..5f07dbc6673 100644
--- a/src/test/ui/issues/issue-12187-1.stderr
+++ b/src/test/ui/issues/issue-12187-1.stderr
@@ -1,4 +1,4 @@
-error[E0282]: type annotations needed in `&_`
+error[E0282]: type annotations needed in `&T`
   --> $DIR/issue-12187-1.rs:6:10
    |
 LL |     let &v = new();
diff --git a/src/test/ui/issues/issue-12187-2.stderr b/src/test/ui/issues/issue-12187-2.stderr
index 8b12ff5f9d8..5b44278359c 100644
--- a/src/test/ui/issues/issue-12187-2.stderr
+++ b/src/test/ui/issues/issue-12187-2.stderr
@@ -1,4 +1,4 @@
-error[E0282]: type annotations needed in `&_`
+error[E0282]: type annotations needed in `&T`
   --> $DIR/issue-12187-2.rs:6:10
    |
 LL |     let &v = new();
diff --git a/src/test/ui/issues/issue-17551.stderr b/src/test/ui/issues/issue-17551.stderr
index 0d7a31fc60d..95af1e41b58 100644
--- a/src/test/ui/issues/issue-17551.stderr
+++ b/src/test/ui/issues/issue-17551.stderr
@@ -1,8 +1,8 @@
-error[E0282]: type annotations needed in `B<_>`
+error[E0282]: type annotations needed in `B<T>`
   --> $DIR/issue-17551.rs:6:15
    |
 LL |     let foo = B(marker::PhantomData);
-   |         ---   ^ cannot infer type for `T` in `B<_>`
+   |         ---   ^ cannot infer type for `T` in `B<T>`
    |         |
    |         consider giving `foo` a type
 
diff --git a/src/test/ui/issues/issue-23046.stderr b/src/test/ui/issues/issue-23046.stderr
index 1363a6f963f..102cfe0085f 100644
--- a/src/test/ui/issues/issue-23046.stderr
+++ b/src/test/ui/issues/issue-23046.stderr
@@ -1,8 +1,8 @@
-error[E0282]: type annotations needed in `Expr<'_, _>`
+error[E0282]: type annotations needed in `Expr<'_, VAR>`
   --> $DIR/issue-23046.rs:17:15
    |
 LL |     let ex = |x| {
-   |               ^ consider giving this closure parameter the type `Expr<'_, _>` with the type parameter `VAR` specified
+   |               ^ consider giving this closure parameter the type `Expr<'_, VAR>` with the type parameter `VAR` specified
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/issues/issue-25368.stderr b/src/test/ui/issues/issue-25368.stderr
index 5fc9ab26969..a386fc94628 100644
--- a/src/test/ui/issues/issue-25368.stderr
+++ b/src/test/ui/issues/issue-25368.stderr
@@ -1,11 +1,11 @@
-error[E0282]: type annotations needed in `(std::sync::mpsc::Sender<Foo<_>>, std::sync::mpsc::Receiver<Foo<_>>)`
+error[E0282]: type annotations needed in `(std::sync::mpsc::Sender<Foo<T>>, std::sync::mpsc::Receiver<Foo<T>>)`
   --> $DIR/issue-25368.rs:11:17
    |
 LL |     let (tx, rx) = channel();
    |         -------- consider giving the pattern a type
 ...
 LL |         tx.send(Foo{ foo: PhantomData });
-   |                 ^^^ cannot infer type for `T` in `(std::sync::mpsc::Sender<Foo<_>>, std::sync::mpsc::Receiver<Foo<_>>)`
+   |                 ^^^ cannot infer type for `T` in `(std::sync::mpsc::Sender<Foo<T>>, std::sync::mpsc::Receiver<Foo<T>>)`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/methods/method-ambig-one-trait-unknown-int-type.stderr b/src/test/ui/methods/method-ambig-one-trait-unknown-int-type.stderr
index e8871efc5b2..b9fa36041b1 100644
--- a/src/test/ui/methods/method-ambig-one-trait-unknown-int-type.stderr
+++ b/src/test/ui/methods/method-ambig-one-trait-unknown-int-type.stderr
@@ -1,8 +1,8 @@
-error[E0282]: type annotations needed in `std::vec::Vec<_>`
+error[E0282]: type annotations needed in `std::vec::Vec<T>`
   --> $DIR/method-ambig-one-trait-unknown-int-type.rs:24:17
    |
 LL |     let mut x = Vec::new();
-   |         -----   ^^^^^^^^ cannot infer type for `T` in `std::vec::Vec<_>`
+   |         -----   ^^^^^^^^ cannot infer type for `T` in `std::vec::Vec<T>`
    |         |
    |         consider giving `x` a type
 
diff --git a/src/test/ui/type/type-check/cannot_infer_local_or_vec.stderr b/src/test/ui/type/type-check/cannot_infer_local_or_vec.stderr
index 59a8b52a66d..a491d4516cc 100644
--- a/src/test/ui/type/type-check/cannot_infer_local_or_vec.stderr
+++ b/src/test/ui/type/type-check/cannot_infer_local_or_vec.stderr
@@ -1,8 +1,8 @@
-error[E0282]: type annotations needed in `std::vec::Vec<_>`
+error[E0282]: type annotations needed in `std::vec::Vec<T>`
   --> $DIR/cannot_infer_local_or_vec.rs:2:13
    |
 LL |     let x = vec![];
-   |         -   ^^^^^^ cannot infer type for `T` in `std::vec::Vec<_>`
+   |         -   ^^^^^^ cannot infer type for `T` in `std::vec::Vec<T>`
    |         |
    |         consider giving `x` a type
    |
diff --git a/src/test/ui/type/type-check/cannot_infer_local_or_vec_in_tuples.stderr b/src/test/ui/type/type-check/cannot_infer_local_or_vec_in_tuples.stderr
index 294b6d93211..1c5b750b9b4 100644
--- a/src/test/ui/type/type-check/cannot_infer_local_or_vec_in_tuples.stderr
+++ b/src/test/ui/type/type-check/cannot_infer_local_or_vec_in_tuples.stderr
@@ -1,8 +1,8 @@
-error[E0282]: type annotations needed in `(std::vec::Vec<_>,)`
+error[E0282]: type annotations needed in `(std::vec::Vec<T>,)`
   --> $DIR/cannot_infer_local_or_vec_in_tuples.rs:2:18
    |
 LL |     let (x, ) = (vec![], );
-   |         -----    ^^^^^^ cannot infer type for `T` in `(std::vec::Vec<_>,)`
+   |         -----    ^^^^^^ cannot infer type for `T` in `(std::vec::Vec<T>,)`
    |         |
    |         consider giving the pattern a type
    |
diff --git a/src/test/ui/unboxed-closures/unboxed-closures-failed-recursive-fn-2.stderr b/src/test/ui/unboxed-closures/unboxed-closures-failed-recursive-fn-2.stderr
index 142975144d4..dda453870dc 100644
--- a/src/test/ui/unboxed-closures/unboxed-closures-failed-recursive-fn-2.stderr
+++ b/src/test/ui/unboxed-closures/unboxed-closures-failed-recursive-fn-2.stderr
@@ -1,4 +1,4 @@
-error[E0282]: type annotations needed in `std::option::Option<_>`
+error[E0282]: type annotations needed in `std::option::Option<T>`
   --> $DIR/unboxed-closures-failed-recursive-fn-2.rs:16:32
    |
 LL |     let mut closure0 = None;
diff --git a/src/test/ui/vector-no-ann.stderr b/src/test/ui/vector-no-ann.stderr
index 2431927f2ac..a6c805c0c26 100644
--- a/src/test/ui/vector-no-ann.stderr
+++ b/src/test/ui/vector-no-ann.stderr
@@ -1,8 +1,8 @@
-error[E0282]: type annotations needed in `std::vec::Vec<_>`
+error[E0282]: type annotations needed in `std::vec::Vec<T>`
   --> $DIR/vector-no-ann.rs:2:16
    |
 LL |     let _foo = Vec::new();
-   |         ----   ^^^^^^^^ cannot infer type for `T` in `std::vec::Vec<_>`
+   |         ----   ^^^^^^^^ cannot infer type for `T` in `std::vec::Vec<T>`
    |         |
    |         consider giving `_foo` a type