@@ -68,12 +68,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
68
68
}
69
69
}
70
70
71
- pub fn report_method_error < ' b > (
71
+ pub fn report_method_error (
72
72
& self ,
73
73
span : Span ,
74
74
rcvr_ty : Ty < ' tcx > ,
75
75
item_name : Ident ,
76
- source : SelfSource < ' b > ,
76
+ source : SelfSource < ' tcx > ,
77
77
error : MethodError < ' tcx > ,
78
78
args : Option < & ' tcx [ hir:: Expr < ' tcx > ] > ,
79
79
) -> Option < DiagnosticBuilder < ' _ > > {
@@ -323,8 +323,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
323
323
err. span_suggestion (
324
324
lit. span ,
325
325
& 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 `{}`",
328
328
concrete_type
329
329
) ,
330
330
format ! ( "{}_{}" , snippet, concrete_type) ,
@@ -975,17 +975,78 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
975
975
}
976
976
}
977
977
978
- fn suggest_traits_to_import < ' b > (
978
+ fn suggest_traits_to_import (
979
979
& self ,
980
980
err : & mut DiagnosticBuilder < ' _ > ,
981
981
span : Span ,
982
982
rcvr_ty : Ty < ' tcx > ,
983
983
item_name : Ident ,
984
- source : SelfSource < ' b > ,
984
+ source : SelfSource < ' tcx > ,
985
985
valid_out_of_scope_traits : Vec < DefId > ,
986
986
unsatisfied_predicates : & [ ( ty:: Predicate < ' tcx > , Option < ty:: Predicate < ' tcx > > ) ] ,
987
987
) {
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) {
989
1050
return ;
990
1051
}
991
1052
@@ -1075,6 +1136,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
1075
1136
"the method might not be found because of this arbitrary self type" ,
1076
1137
) ;
1077
1138
}
1139
+ if alt_rcvr_sugg {
1140
+ return ;
1141
+ }
1078
1142
1079
1143
if !candidates. is_empty ( ) {
1080
1144
// Sort from most relevant to least relevant.
@@ -1284,7 +1348,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
1284
1348
1285
1349
/// Checks whether there is a local type somewhere in the chain of
1286
1350
/// 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 {
1288
1357
fn is_local ( ty : Ty < ' _ > ) -> bool {
1289
1358
match ty. kind ( ) {
1290
1359
ty:: Adt ( def, _) => def. did . is_local ( ) ,
@@ -1310,7 +1379,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
1310
1379
}
1311
1380
}
1312
1381
1313
- #[ derive( Copy , Clone ) ]
1382
+ #[ derive( Copy , Clone , Debug ) ]
1314
1383
pub enum SelfSource < ' a > {
1315
1384
QPath ( & ' a hir:: Ty < ' a > ) ,
1316
1385
MethodCall ( & ' a hir:: Expr < ' a > /* rcvr */ ) ,
0 commit comments