@@ -68,12 +68,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
6868 }
6969 }
7070
71- pub fn report_method_error < ' b > (
71+ pub fn report_method_error (
7272 & self ,
7373 span : Span ,
7474 rcvr_ty : Ty < ' tcx > ,
7575 item_name : Ident ,
76- source : SelfSource < ' b > ,
76+ source : SelfSource < ' tcx > ,
7777 error : MethodError < ' tcx > ,
7878 args : Option < & ' tcx [ hir:: Expr < ' tcx > ] > ,
7979 ) -> Option < DiagnosticBuilder < ' _ > > {
@@ -323,8 +323,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
323323 err. span_suggestion (
324324 lit. span ,
325325 & format ! (
326- "you must specify a concrete type for \
327- this numeric value, like `{}`",
326+ "you must specify a concrete type for this numeric value, \
327+ like `{}`",
328328 concrete_type
329329 ) ,
330330 format ! ( "{}_{}" , snippet, concrete_type) ,
@@ -975,17 +975,78 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
975975 }
976976 }
977977
978- fn suggest_traits_to_import < ' b > (
978+ fn suggest_traits_to_import (
979979 & self ,
980980 err : & mut DiagnosticBuilder < ' _ > ,
981981 span : Span ,
982982 rcvr_ty : Ty < ' tcx > ,
983983 item_name : Ident ,
984- source : SelfSource < ' b > ,
984+ source : SelfSource < ' tcx > ,
985985 valid_out_of_scope_traits : Vec < DefId > ,
986986 unsatisfied_predicates : & [ ( ty:: Predicate < ' tcx > , Option < ty:: Predicate < ' tcx > > ) ] ,
987987 ) {
988- if self . suggest_valid_traits ( err, valid_out_of_scope_traits) {
988+ let mut alt_rcvr_sugg = false ;
989+ if let SelfSource :: MethodCall ( rcvr) = source {
990+ info ! ( ?span, ?item_name, ?rcvr_ty, ?rcvr) ;
991+ if let ty:: Adt ( ..) = rcvr_ty. kind ( ) {
992+ // Try alternative arbitrary self types that could fulfill this call.
993+ // FIXME: probe for all types that *could* be arbitrary self-types, not
994+ // just this list.
995+ for ( rcvr_ty, post) in & [
996+ ( rcvr_ty, "" ) ,
997+ ( self . tcx . mk_mut_ref ( & ty:: ReErased , rcvr_ty) , "&mut " ) ,
998+ ( self . tcx . mk_imm_ref ( & ty:: ReErased , rcvr_ty) , "&" ) ,
999+ ] {
1000+ for ( rcvr_ty, pre) in & [
1001+ ( self . tcx . mk_lang_item ( rcvr_ty, LangItem :: OwnedBox ) , "Box::new" ) ,
1002+ ( self . tcx . mk_lang_item ( rcvr_ty, LangItem :: Pin ) , "Pin::new" ) ,
1003+ ( self . tcx . mk_diagnostic_item ( rcvr_ty, sym:: Arc ) , "Arc::new" ) ,
1004+ ( self . tcx . mk_diagnostic_item ( rcvr_ty, sym:: Rc ) , "Rc::new" ) ,
1005+ ] {
1006+ if let Some ( new_rcvr_t) = * rcvr_ty {
1007+ if let Ok ( pick) = self . lookup_probe (
1008+ span,
1009+ item_name,
1010+ new_rcvr_t,
1011+ rcvr,
1012+ crate :: check:: method:: probe:: ProbeScope :: AllTraits ,
1013+ ) {
1014+ debug ! ( "try_alt_rcvr: pick candidate {:?}" , pick) ;
1015+ // Make sure the method is defined for the *actual* receiver:
1016+ // we don't want to treat `Box<Self>` as a receiver if
1017+ // it only works because of an autoderef to `&self`
1018+ if pick. autoderefs == 0
1019+ // We don't want to suggest a container type when the missing method is
1020+ // `.clone()`, otherwise we'd suggest `Arc::new(foo).clone()`, which is
1021+ // far from what the user really wants.
1022+ && Some ( pick. item . container . id ( ) ) != self . tcx . lang_items ( ) . clone_trait ( )
1023+ {
1024+ err. span_label (
1025+ pick. item . ident . span ,
1026+ & format ! (
1027+ "the method is available for `{}` here" ,
1028+ new_rcvr_t
1029+ ) ,
1030+ ) ;
1031+ err. multipart_suggestion (
1032+ "consider wrapping the receiver expression with the \
1033+ appropriate type",
1034+ vec ! [
1035+ ( rcvr. span. shrink_to_lo( ) , format!( "{}({}" , pre, post) ) ,
1036+ ( rcvr. span. shrink_to_hi( ) , ")" . to_string( ) ) ,
1037+ ] ,
1038+ Applicability :: MaybeIncorrect ,
1039+ ) ;
1040+ // We don't care about the other suggestions.
1041+ alt_rcvr_sugg = true ;
1042+ }
1043+ }
1044+ }
1045+ }
1046+ }
1047+ }
1048+ }
1049+ if !alt_rcvr_sugg && self . suggest_valid_traits ( err, valid_out_of_scope_traits) {
9891050 return ;
9901051 }
9911052
@@ -1075,6 +1136,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
10751136 "the method might not be found because of this arbitrary self type" ,
10761137 ) ;
10771138 }
1139+ if alt_rcvr_sugg {
1140+ return ;
1141+ }
10781142
10791143 if !candidates. is_empty ( ) {
10801144 // Sort from most relevant to least relevant.
@@ -1284,7 +1348,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
12841348
12851349 /// Checks whether there is a local type somewhere in the chain of
12861350 /// autoderefs of `rcvr_ty`.
1287- fn type_derefs_to_local ( & self , span : Span , rcvr_ty : Ty < ' tcx > , source : SelfSource < ' _ > ) -> bool {
1351+ fn type_derefs_to_local (
1352+ & self ,
1353+ span : Span ,
1354+ rcvr_ty : Ty < ' tcx > ,
1355+ source : SelfSource < ' tcx > ,
1356+ ) -> bool {
12881357 fn is_local ( ty : Ty < ' _ > ) -> bool {
12891358 match ty. kind ( ) {
12901359 ty:: Adt ( def, _) => def. did . is_local ( ) ,
@@ -1310,7 +1379,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
13101379 }
13111380}
13121381
1313- #[ derive( Copy , Clone ) ]
1382+ #[ derive( Copy , Clone , Debug ) ]
13141383pub enum SelfSource < ' a > {
13151384 QPath ( & ' a hir:: Ty < ' a > ) ,
13161385 MethodCall ( & ' a hir:: Expr < ' a > /* rcvr */ ) ,
0 commit comments