@@ -294,143 +294,151 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
294294 let id = map. get_parent_item ( hir_id) ;
295295 let hir_id: hir:: HirId = id. into ( ) ;
296296
297- if let Some ( node) = map. find ( hir_id) && let Some ( body_id) = node. body_id ( ) {
298- let body = map. body ( body_id) ;
299- expr_finder. visit_expr ( body. value ) ;
300- let mut eraser = TypeEraser { tcx } ;
301- let mut prev = eraser. fold_ty ( ty) ;
302- let mut prev_span = None ;
303-
304- for binding in expr_finder. uses {
305- // In every expression where the binding is referenced, we will look at that
306- // expression's type and see if it is where the incorrect found type was fully
307- // "materialized" and point at it. We will also try to provide a suggestion there.
308- let parent = map. get_parent_node ( binding. hir_id ) ;
309- if let Some ( hir:: Node :: Expr ( expr) )
310- | Some ( hir:: Node :: Stmt ( hir:: Stmt {
311- kind : hir:: StmtKind :: Expr ( expr) | hir:: StmtKind :: Semi ( expr) ,
312- ..
313- } ) ) = & map. find ( parent)
314- && let hir:: ExprKind :: MethodCall ( s, rcvr, args, _span) = expr. kind
315- && rcvr. hir_id == binding. hir_id
316- && let Some ( def_id) = self . typeck_results . borrow ( ) . type_dependent_def_id ( expr. hir_id )
317- {
318- // We special case methods, because they can influence inference through the
319- // call's arguments and we can provide a more explicit span.
320- let sig = self . tcx . fn_sig ( def_id) ;
321- let def_self_ty = sig. input ( 0 ) . skip_binder ( ) ;
322- let rcvr_ty = self . node_ty ( rcvr. hir_id ) ;
323- // Get the evaluated type *after* calling the method call, so that the influence
324- // of the arguments can be reflected in the receiver type. The receiver
325- // expression has the type *before* theis analysis is done.
326- let ty = match self . lookup_probe ( s. ident , rcvr_ty, expr, probe:: ProbeScope :: TraitsInScope ) {
327- Ok ( pick) => pick. self_ty ,
328- Err ( _) => rcvr_ty,
329- } ;
330- // Remove one layer of references to account for `&mut self` and
331- // `&self`, so that we can compare it against the binding.
332- let ( ty, def_self_ty) = match ( ty. kind ( ) , def_self_ty. kind ( ) ) {
333- ( ty:: Ref ( _, ty, a) , ty:: Ref ( _, self_ty, b) ) if a == b => ( * ty, * self_ty) ,
334- _ => ( ty, def_self_ty) ,
335- } ;
336- let mut param_args = FxHashMap :: default ( ) ;
337- let mut param_expected = FxHashMap :: default ( ) ;
338- let mut param_found = FxHashMap :: default ( ) ;
339- if self . can_eq ( self . param_env , ty, found) . is_ok ( ) {
340- // We only point at the first place where the found type was inferred.
341- for ( i, param_ty) in sig. inputs ( ) . skip_binder ( ) . iter ( ) . skip ( 1 ) . enumerate ( ) {
342- if def_self_ty. contains ( * param_ty) && let ty:: Param ( _) = param_ty. kind ( ) {
343- // We found an argument that references a type parameter in `Self`,
344- // so we assume that this is the argument that caused the found
345- // type, which we know already because of `can_eq` above was first
346- // inferred in this method call.
347- let arg = & args[ i] ;
348- let arg_ty = self . node_ty ( arg. hir_id ) ;
349- err. span_label (
350- arg. span ,
351- & format ! (
352- "this is of type `{arg_ty}`, which makes `{ident}` to be \
353- inferred as `{ty}`",
354- ) ,
355- ) ;
356- param_args. insert ( param_ty, ( arg, arg_ty) ) ;
357- }
297+ let Some ( node) = map. find ( hir_id) else { return false ; } ;
298+ let Some ( body_id) = node. body_id ( ) else { return false ; } ;
299+ let body = map. body ( body_id) ;
300+ expr_finder. visit_expr ( body. value ) ;
301+ let mut eraser = TypeEraser { tcx } ;
302+ let mut prev = eraser. fold_ty ( ty) ;
303+ let mut prev_span = None ;
304+
305+ for binding in expr_finder. uses {
306+ // In every expression where the binding is referenced, we will look at that
307+ // expression's type and see if it is where the incorrect found type was fully
308+ // "materialized" and point at it. We will also try to provide a suggestion there.
309+ let parent = map. get_parent_node ( binding. hir_id ) ;
310+ if let Some ( hir:: Node :: Expr ( expr) )
311+ | Some ( hir:: Node :: Stmt ( hir:: Stmt {
312+ kind : hir:: StmtKind :: Expr ( expr) | hir:: StmtKind :: Semi ( expr) ,
313+ ..
314+ } ) ) = & map. find ( parent)
315+ && let hir:: ExprKind :: MethodCall ( segment, rcvr, args, _span) = expr. kind
316+ && rcvr. hir_id == binding. hir_id
317+ && let Some ( def_id) = self . typeck_results . borrow ( ) . type_dependent_def_id ( expr. hir_id )
318+ {
319+ // We special case methods, because they can influence inference through the
320+ // call's arguments and we can provide a more explicit span.
321+ let sig = self . tcx . fn_sig ( def_id) ;
322+ let def_self_ty = sig. input ( 0 ) . skip_binder ( ) ;
323+ let rcvr_ty = self . node_ty ( rcvr. hir_id ) ;
324+ // Get the evaluated type *after* calling the method call, so that the influence
325+ // of the arguments can be reflected in the receiver type. The receiver
326+ // expression has the type *before* theis analysis is done.
327+ let ty = match self . lookup_probe (
328+ segment. ident ,
329+ rcvr_ty,
330+ expr,
331+ probe:: ProbeScope :: TraitsInScope ,
332+ ) {
333+ Ok ( pick) => pick. self_ty ,
334+ Err ( _) => rcvr_ty,
335+ } ;
336+ // Remove one layer of references to account for `&mut self` and
337+ // `&self`, so that we can compare it against the binding.
338+ let ( ty, def_self_ty) = match ( ty. kind ( ) , def_self_ty. kind ( ) ) {
339+ ( ty:: Ref ( _, ty, a) , ty:: Ref ( _, self_ty, b) ) if a == b => ( * ty, * self_ty) ,
340+ _ => ( ty, def_self_ty) ,
341+ } ;
342+ let mut param_args = FxHashMap :: default ( ) ;
343+ let mut param_expected = FxHashMap :: default ( ) ;
344+ let mut param_found = FxHashMap :: default ( ) ;
345+ if self . can_eq ( self . param_env , ty, found) . is_ok ( ) {
346+ // We only point at the first place where the found type was inferred.
347+ for ( i, param_ty) in sig. inputs ( ) . skip_binder ( ) . iter ( ) . skip ( 1 ) . enumerate ( ) {
348+ if def_self_ty. contains ( * param_ty) && let ty:: Param ( _) = param_ty. kind ( ) {
349+ // We found an argument that references a type parameter in `Self`,
350+ // so we assume that this is the argument that caused the found
351+ // type, which we know already because of `can_eq` above was first
352+ // inferred in this method call.
353+ let arg = & args[ i] ;
354+ let arg_ty = self . node_ty ( arg. hir_id ) ;
355+ err. span_label (
356+ arg. span ,
357+ & format ! (
358+ "this is of type `{arg_ty}`, which makes `{ident}` to be \
359+ inferred as `{ty}`",
360+ ) ,
361+ ) ;
362+ param_args. insert ( param_ty, ( arg, arg_ty) ) ;
358363 }
359364 }
365+ }
360366
361- // Here we find, for a type param `T`, the type that `T` is in the current
362- // method call *and* in the original expected type. That way, we can see if we
363- // can give any structured suggestion for the function argument.
364- let mut c = CollectAllMismatches {
365- infcx : & self . infcx ,
366- param_env : self . param_env ,
367- errors : vec ! [ ] ,
368- } ;
369- let _ = c. relate ( def_self_ty, ty) ;
370- for error in c. errors {
371- if let TypeError :: Sorts ( error) = error {
372- param_found. insert ( error. expected , error. found ) ;
373- }
374- }
375- c. errors = vec ! [ ] ;
376- let _ = c. relate ( def_self_ty, expected) ;
377- for error in c. errors {
378- if let TypeError :: Sorts ( error) = error {
379- param_expected. insert ( error. expected , error. found ) ;
380- }
367+ // Here we find, for a type param `T`, the type that `T` is in the current
368+ // method call *and* in the original expected type. That way, we can see if we
369+ // can give any structured suggestion for the function argument.
370+ let mut c = CollectAllMismatches {
371+ infcx : & self . infcx ,
372+ param_env : self . param_env ,
373+ errors : vec ! [ ] ,
374+ } ;
375+ let _ = c. relate ( def_self_ty, ty) ;
376+ for error in c. errors {
377+ if let TypeError :: Sorts ( error) = error {
378+ param_found. insert ( error. expected , error. found ) ;
381379 }
382- for ( param, ( arg, arg_ty) ) in param_args. iter ( ) {
383- let Some ( expected) = param_expected. get ( param) else { continue ; } ;
384- let Some ( found) = param_found. get ( param) else { continue ; } ;
385- if self . can_eq ( self . param_env , * arg_ty, * found) . is_err ( ) { continue ; }
386- self . suggest_deref_ref_or_into ( err, arg, * expected, * found, None ) ;
380+ }
381+ c. errors = vec ! [ ] ;
382+ let _ = c. relate ( def_self_ty, expected) ;
383+ for error in c. errors {
384+ if let TypeError :: Sorts ( error) = error {
385+ param_expected. insert ( error. expected , error. found ) ;
387386 }
387+ }
388+ for ( param, ( arg, arg_ty) ) in param_args. iter ( ) {
389+ let Some ( expected) = param_expected. get ( param) else { continue ; } ;
390+ let Some ( found) = param_found. get ( param) else { continue ; } ;
391+ if self . can_eq ( self . param_env , * arg_ty, * found) . is_err ( ) { continue ; }
392+ self . suggest_deref_ref_or_into ( err, arg, * expected, * found, None ) ;
393+ }
388394
389- let ty = eraser. fold_ty ( ty) ;
390- if ty. references_error ( ) {
391- break ;
392- }
393- if ty != prev
394- && param_args. is_empty ( )
395- && self . can_eq ( self . param_env , ty, found) . is_ok ( )
396- {
397- // We only point at the first place where the found type was inferred.
398- err. span_label (
399- s. ident . span ,
400- with_forced_trimmed_paths ! ( format!(
401- "here the type of `{ident}` is inferred to be `{ty}`" ,
402- ) ) ,
403- ) ;
404- break ;
405- }
406- prev = ty;
407- } else {
408- let ty = eraser. fold_ty ( self . node_ty ( binding. hir_id ) ) ;
409- if ty. references_error ( ) {
410- break ;
411- }
412- if ty != prev && let Some ( span) = prev_span && self . can_eq ( self . param_env , ty, found) . is_ok ( ) {
413- // We only point at the first place where the found type was inferred.
414- // We use the *previous* span because if the type is known *here* it means
415- // it was *evaluated earlier*. We don't do this for method calls because we
416- // evaluate the method's self type eagerly, but not in any other case.
417- err. span_label (
418- span,
419- with_forced_trimmed_paths ! ( format!(
420- "here the type of `{ident}` is inferred to be `{ty}`" ,
421- ) ) ,
422- ) ;
423- break ;
424- }
425- prev = ty;
395+ let ty = eraser. fold_ty ( ty) ;
396+ if ty. references_error ( ) {
397+ break ;
426398 }
427- if binding. hir_id == expr. hir_id {
428- // Do not look at expressions that come after the expression we were originally
429- // evaluating and had a type error.
399+ if ty != prev
400+ && param_args. is_empty ( )
401+ && self . can_eq ( self . param_env , ty, found) . is_ok ( )
402+ {
403+ // We only point at the first place where the found type was inferred.
404+ err. span_label (
405+ segment. ident . span ,
406+ with_forced_trimmed_paths ! ( format!(
407+ "here the type of `{ident}` is inferred to be `{ty}`" ,
408+ ) ) ,
409+ ) ;
430410 break ;
431411 }
432- prev_span = Some ( binding. span ) ;
412+ prev = ty;
413+ } else {
414+ let ty = eraser. fold_ty ( self . node_ty ( binding. hir_id ) ) ;
415+ if ty. references_error ( ) {
416+ break ;
417+ }
418+ if ty != prev
419+ && let Some ( span) = prev_span
420+ && self . can_eq ( self . param_env , ty, found) . is_ok ( )
421+ {
422+ // We only point at the first place where the found type was inferred.
423+ // We use the *previous* span because if the type is known *here* it means
424+ // it was *evaluated earlier*. We don't do this for method calls because we
425+ // evaluate the method's self type eagerly, but not in any other case.
426+ err. span_label (
427+ span,
428+ with_forced_trimmed_paths ! ( format!(
429+ "here the type of `{ident}` is inferred to be `{ty}`" ,
430+ ) ) ,
431+ ) ;
432+ break ;
433+ }
434+ prev = ty;
435+ }
436+ if binding. hir_id == expr. hir_id {
437+ // Do not look at expressions that come after the expression we were originally
438+ // evaluating and had a type error.
439+ break ;
433440 }
441+ prev_span = Some ( binding. span ) ;
434442 }
435443 true
436444 }
0 commit comments