@@ -481,7 +481,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
481481 ) ;
482482 probe. is_ok ( )
483483 } ) ;
484-
485484 self . note_internal_mutation_in_method (
486485 & mut err,
487486 rcvr_expr,
@@ -1240,7 +1239,40 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
12401239 }
12411240 }
12421241 }
1243-
1242+ // If an appropriate error source is not found, check method chain for possible candiates
1243+ if unsatisfied_predicates. is_empty ( ) && let Mode :: MethodCall = mode && let SelfSource :: MethodCall ( mut source_expr) = source {
1244+ let mut stack_methods = vec ! [ ] ;
1245+ while let hir:: ExprKind :: MethodCall ( _path_segment, rcvr_expr, _args, method_span) =
1246+ source_expr. kind
1247+ {
1248+ // Pop the matching receiver, to align on it's notional span
1249+ if let Some ( prev_match) = stack_methods. pop ( ) {
1250+ err. span_label ( method_span, format ! ( "{item_kind} `{item_name}` is available on `{prev_match}`" ) ) ;
1251+ }
1252+ let rcvr_ty = self . resolve_vars_if_possible (
1253+ self . typeck_results
1254+ . borrow ( )
1255+ . expr_ty_adjusted_opt ( rcvr_expr)
1256+ . unwrap_or ( Ty :: new_misc_error ( self . tcx ) ) , ) ;
1257+
1258+ for _matched_method in self . probe_for_name_many (
1259+ Mode :: MethodCall ,
1260+ item_name,
1261+ None ,
1262+ IsSuggestion ( true ) ,
1263+ rcvr_ty,
1264+ source_expr. hir_id ,
1265+ ProbeScope :: TraitsInScope , ) {
1266+ // found a match, push to stack
1267+ stack_methods. push ( rcvr_ty) ;
1268+ }
1269+ source_expr = rcvr_expr;
1270+ }
1271+ // If there is a match at the start of the chain, add a label for it too!
1272+ if let Some ( prev_match) = stack_methods. pop ( ) {
1273+ err. span_label ( source_expr. span , format ! ( "{item_kind} `{item_name}` is available on `{prev_match}`" ) ) ;
1274+ }
1275+ }
12441276 self . note_derefed_ty_has_method ( & mut err, source, rcvr_ty, item_name, expected) ;
12451277 return Some ( err) ;
12461278 }
0 commit comments