@@ -6,6 +6,7 @@ use crate::infer::type_variable::TypeVariableOriginKind;
66use crate :: ty:: { self , Ty , Infer , TyVar } ;
77use crate :: ty:: print:: Print ;
88use syntax:: source_map:: DesugaringKind ;
9+ use syntax:: symbol:: kw;
910use syntax_pos:: Span ;
1011use errors:: { Applicability , DiagnosticBuilder } ;
1112
@@ -19,6 +20,7 @@ struct FindLocalByTypeVisitor<'a, 'tcx> {
1920 found_arg_pattern : Option < & ' tcx Pat > ,
2021 found_ty : Option < Ty < ' tcx > > ,
2122 found_closure : Option < & ' tcx ExprKind > ,
23+ found_method_call : Option < & ' tcx ExprKind > ,
2224}
2325
2426impl < ' a , ' tcx > FindLocalByTypeVisitor < ' a , ' tcx > {
@@ -35,6 +37,7 @@ impl<'a, 'tcx> FindLocalByTypeVisitor<'a, 'tcx> {
3537 found_arg_pattern : None ,
3638 found_ty : None ,
3739 found_closure : None ,
40+ found_method_call : None ,
3841 }
3942 }
4043
@@ -93,11 +96,12 @@ impl<'a, 'tcx> Visitor<'tcx> for FindLocalByTypeVisitor<'a, 'tcx> {
9396 }
9497
9598 fn visit_expr ( & mut self , expr : & ' tcx Expr ) {
96- if let ( ExprKind :: Closure ( _, _fn_decl, _id, _sp, _) , Some ( _) ) = (
97- & expr. kind ,
98- self . node_matches_type ( expr. hir_id ) ,
99- ) {
100- self . found_closure = Some ( & expr. kind ) ;
99+ if self . node_matches_type ( expr. hir_id ) . is_some ( ) {
100+ match expr. kind {
101+ ExprKind :: Closure ( ..) => self . found_closure = Some ( & expr. kind ) ,
102+ ExprKind :: MethodCall ( ..) => self . found_method_call = Some ( & expr. kind ) ,
103+ _ => { }
104+ }
101105 }
102106 intravisit:: walk_expr ( self , expr) ;
103107 }
@@ -157,7 +161,9 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
157161 let ty_vars = self . type_variables . borrow ( ) ;
158162 let var_origin = ty_vars. var_origin ( ty_vid) ;
159163 if let TypeVariableOriginKind :: TypeParameterDefinition ( name) = var_origin. kind {
160- return ( name. to_string ( ) , Some ( var_origin. span ) ) ;
164+ if name != kw:: SelfUpper {
165+ return ( name. to_string ( ) , Some ( var_origin. span ) ) ;
166+ }
161167 }
162168 }
163169
@@ -175,6 +181,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
175181 body_id : Option < hir:: BodyId > ,
176182 span : Span ,
177183 ty : Ty < ' tcx > ,
184+ is_projection : bool ,
178185 ) -> DiagnosticBuilder < ' tcx > {
179186 let ty = self . resolve_vars_if_possible ( & ty) ;
180187 let ( name, name_sp) = self . extract_type_name ( & ty, None ) ;
@@ -210,6 +217,20 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
210217 // 3 | let _ = x.sum() as f64;
211218 // | ^^^ cannot infer type for `S`
212219 span
220+ } else if let Some ( ExprKind :: MethodCall ( _, call_span, _) ) = local_visitor. found_method_call {
221+ // Point at the call instead of the whole expression:
222+ // error[E0284]: type annotations needed
223+ // --> file.rs:2:5
224+ // |
225+ // 2 | vec![Ok(2)].into_iter().collect()?;
226+ // | ^^^^^^^ cannot infer type
227+ // |
228+ // = note: cannot resolve `<_ as std::ops::Try>::Ok == _`
229+ if span. contains ( * call_span) {
230+ * call_span
231+ } else {
232+ span
233+ }
213234 } else {
214235 span
215236 } ;
@@ -247,13 +268,11 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
247268 // | consider giving `b` the explicit type `std::result::Result<i32, E>`, where
248269 // | the type parameter `E` is specified
249270 // ```
250- let mut err = struct_span_err ! (
251- self . tcx. sess,
252- err_span,
253- E0282 ,
254- "type annotations needed{}" ,
255- ty_msg,
256- ) ;
271+ let mut err = if is_projection {
272+ struct_span_err ! ( self . tcx. sess, err_span, E0284 , "type annotations needed{}" , ty_msg)
273+ } else {
274+ struct_span_err ! ( self . tcx. sess, err_span, E0282 , "type annotations needed{}" , ty_msg)
275+ } ;
257276
258277 let suffix = match local_visitor. found_ty {
259278 Some ( ty:: TyS { kind : ty:: Closure ( def_id, substs) , .. } ) => {
@@ -334,6 +353,18 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
334353 format ! ( "consider giving this pattern {}" , suffix)
335354 } ;
336355 err. span_label ( pattern. span , msg) ;
356+ } else if let Some ( ExprKind :: MethodCall ( segment, ..) ) = local_visitor. found_method_call {
357+ if let Ok ( snippet) = self . tcx . sess . source_map ( ) . span_to_snippet ( segment. ident . span ) {
358+ if segment. args . is_none ( ) {
359+ err. span_suggestion (
360+ segment. ident . span ,
361+ "consider specifying the type argument in the method call" ,
362+ // FIXME: we don't know how many type arguments should be set here.
363+ format ! ( "{}::<_>" , snippet) ,
364+ Applicability :: HasPlaceholders ,
365+ ) ;
366+ }
367+ }
337368 }
338369 // Instead of the following:
339370 // error[E0282]: type annotations needed
@@ -351,7 +382,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
351382 // | ^^^ cannot infer type for `S`
352383 // |
353384 // = note: type must be known at this point
354- let span = name_sp. unwrap_or ( span ) ;
385+ let span = name_sp. unwrap_or ( err_span ) ;
355386 if !err. span . span_labels ( ) . iter ( ) . any ( |span_label| {
356387 span_label. label . is_some ( ) && span_label. span == span
357388 } ) && local_visitor. found_arg_pattern . is_none ( )
0 commit comments