@@ -973,7 +973,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
973973 error : MethodError < ' tcx > ,
974974 ) {
975975 let rcvr = & args[ 0 ] ;
976- let try_alt_rcvr = |err : & mut DiagnosticBuilder < ' _ > , new_rcvr_t| {
976+ let try_alt_rcvr = |err : & mut DiagnosticBuilder < ' _ > , new_rcvr_t, pre : & str , post : & str | {
977977 if let Some ( new_rcvr_t) = new_rcvr_t {
978978 if let Ok ( pick) = self . lookup_probe (
979979 span,
@@ -986,11 +986,24 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
986986 // Make sure the method is defined for the *actual* receiver:
987987 // we don't want to treat `Box<Self>` as a receiver if
988988 // it only works because of an autoderef to `&self`
989- if pick. autoderefs == 0 {
989+ if pick. autoderefs == 0
990+ // We don't want to suggest a container type when the missing method is
991+ // `.clone()`, otherwise we'd suggest `Arc::new(foo).clone()`, which is
992+ // far from what the user really wants.
993+ && Some ( pick. item . container . id ( ) ) != self . tcx . lang_items ( ) . clone_trait ( )
994+ {
990995 err. span_label (
991996 pick. item . ident . span ,
992997 & format ! ( "the method is available for `{}` here" , new_rcvr_t) ,
993998 ) ;
999+ err. multipart_suggestion (
1000+ "consider wrapping the receiver expression with the appropriate type" ,
1001+ vec ! [
1002+ ( rcvr. span. shrink_to_lo( ) , format!( "{}({}" , pre, post) ) ,
1003+ ( rcvr. span. shrink_to_hi( ) , ")" . to_string( ) ) ,
1004+ ] ,
1005+ Applicability :: MaybeIncorrect ,
1006+ ) ;
9941007 }
9951008 }
9961009 }
@@ -1008,10 +1021,20 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
10081021 // Try alternative arbitrary self types that could fulfill this call.
10091022 // FIXME: probe for all types that *could* be arbitrary self-types, not
10101023 // just this list.
1011- try_alt_rcvr ( & mut err, self . tcx . mk_lang_item ( rcvr_t, LangItem :: OwnedBox ) ) ;
1012- try_alt_rcvr ( & mut err, self . tcx . mk_lang_item ( rcvr_t, LangItem :: Pin ) ) ;
1013- try_alt_rcvr ( & mut err, self . tcx . mk_diagnostic_item ( rcvr_t, sym:: Arc ) ) ;
1014- try_alt_rcvr ( & mut err, self . tcx . mk_diagnostic_item ( rcvr_t, sym:: Rc ) ) ;
1024+ for ( rcvr_t, post) in & [
1025+ ( rcvr_t, "" ) ,
1026+ ( self . tcx . mk_mut_ref ( & ty:: ReErased , rcvr_t) , "&mut " ) ,
1027+ ( self . tcx . mk_imm_ref ( & ty:: ReErased , rcvr_t) , "&" ) ,
1028+ ] {
1029+ for ( rcvr_t, pre) in & [
1030+ ( self . tcx . mk_lang_item ( rcvr_t, LangItem :: OwnedBox ) , "Box::new" ) ,
1031+ ( self . tcx . mk_lang_item ( rcvr_t, LangItem :: Pin ) , "Pin::new" ) ,
1032+ ( self . tcx . mk_diagnostic_item ( rcvr_t, sym:: Arc ) , "Arc::new" ) ,
1033+ ( self . tcx . mk_diagnostic_item ( rcvr_t, sym:: Rc ) , "Rc::new" ) ,
1034+ ] {
1035+ try_alt_rcvr ( & mut err, * rcvr_t, pre, post) ;
1036+ }
1037+ }
10151038 }
10161039 err. emit ( ) ;
10171040 }
0 commit comments