@@ -15,7 +15,7 @@ struct FindLocalByTypeVisitor<'a, 'gcx: 'a + 'tcx, 'tcx: 'a> {
1515 hir_map : & ' a hir:: map:: Map < ' gcx > ,
1616 found_local_pattern : Option < & ' gcx Pat > ,
1717 found_arg_pattern : Option < & ' gcx Pat > ,
18- found_ty : Option < String > ,
18+ found_ty : Option < Ty < ' tcx > > ,
1919}
2020
2121impl < ' a , ' gcx , ' tcx > FindLocalByTypeVisitor < ' a , ' gcx , ' tcx > {
@@ -55,7 +55,7 @@ impl<'a, 'gcx, 'tcx> Visitor<'gcx> for FindLocalByTypeVisitor<'a, 'gcx, 'tcx> {
5555 fn visit_local ( & mut self , local : & ' gcx Local ) {
5656 if let ( None , Some ( ty) ) = ( self . found_local_pattern , self . node_matches_type ( local. hir_id ) ) {
5757 self . found_local_pattern = Some ( & * local. pat ) ;
58- self . found_ty = Some ( ty. to_string ( ) ) ;
58+ self . found_ty = Some ( ty) ;
5959 }
6060 intravisit:: walk_local ( self , local) ;
6161 }
@@ -67,7 +67,7 @@ impl<'a, 'gcx, 'tcx> Visitor<'gcx> for FindLocalByTypeVisitor<'a, 'gcx, 'tcx> {
6767 self . node_matches_type ( argument. hir_id ) ,
6868 ) {
6969 self . found_arg_pattern = Some ( & * argument. pat ) ;
70- self . found_ty = Some ( ty. to_string ( ) ) ;
70+ self . found_ty = Some ( ty) ;
7171 }
7272 }
7373 intravisit:: walk_body ( self , body) ;
@@ -117,14 +117,43 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
117117 found_arg_pattern : None ,
118118 found_ty : None ,
119119 } ;
120+ let ty_to_string = |ty : Ty < ' tcx > | -> String {
121+ let mut s = String :: new ( ) ;
122+ let mut printer = ty:: print:: FmtPrinter :: new ( self . tcx , & mut s, Namespace :: TypeNS ) ;
123+ let ty_vars = self . type_variables . borrow ( ) ;
124+ let getter = move |ty_vid| {
125+ if let TypeVariableOrigin :: TypeParameterDefinition ( _, name) =
126+ * ty_vars. var_origin ( ty_vid) {
127+ return Some ( name. to_string ( ) ) ;
128+ }
129+ None
130+ } ;
131+ printer. name_resolver = Some ( Box :: new ( & getter) ) ;
132+ let _ = ty. print ( printer) ;
133+ s
134+ } ;
120135
121136 if let Some ( body_id) = body_id {
122137 let expr = self . tcx . hir ( ) . expect_expr_by_hir_id ( body_id. hir_id ) ;
123138 local_visitor. visit_expr ( expr) ;
124139 }
125140
141+ // When `name` corresponds to a type argument, show the path of the full type we're
142+ // trying to infer. In the following example, `ty_msg` contains
143+ // " in `std::result::Result<i32, E>`":
144+ // ```
145+ // error[E0282]: type annotations needed in `std::result::Result<i32, E>`
146+ // --> file.rs:L:CC
147+ // |
148+ // L | let b = Ok(4);
149+ // | - ^^ cannot infer type for `E` in `std::result::Result<i32, E>`
150+ // | |
151+ // | consider giving `b` a type
152+ // ```
126153 let ty_msg = match & local_visitor. found_ty {
127- Some ( ty) if & ty[ ..] != "_" && ty != & name => format ! ( " in `{}`" , ty) ,
154+ Some ( ty) if & ty. to_string ( ) != "_" && ty. to_string ( ) != name => {
155+ format ! ( " in `{}`" , ty_to_string( ty) )
156+ }
128157 _ => String :: new ( ) ,
129158 } ;
130159 let mut labels = vec ! [ ( span, InferCtxt :: missing_type_msg( & name, & ty_msg) ) ] ;
@@ -144,17 +173,20 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
144173 // After clearing, it looks something like this:
145174 // ```
146175 // let x = |_| { };
147- // ^ consider giving this closure parameter a type
176+ // ^ consider giving this closure parameter the type `[_; 0]`
177+ // with the type parameter `_` specified
148178 // ```
149179 labels. clear ( ) ;
150180 labels. push ( ( pattern. span , format ! (
151181 "consider giving this closure parameter {}" ,
152182 match & local_visitor. found_ty {
153- Some ( ty) if & ty[ ..] != "_" && ty != & name => format!(
154- "the type `{}` with the type parameter `{}` specified" ,
155- ty,
156- name,
157- ) ,
183+ Some ( ty) if & ty. to_string( ) != "_" && ty. to_string( ) != name => {
184+ format!(
185+ "the type `{}` with the type parameter `{}` specified" ,
186+ ty_to_string( ty) ,
187+ name,
188+ )
189+ }
158190 _ => "a type" . to_owned( ) ,
159191 } ,
160192 ) ) ) ;
0 commit comments