@@ -1260,6 +1260,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
1260
1260
// Dynamic limit to avoid hiding just one candidate, which is silly.
1261
1261
let limit = if sources. len ( ) == 5 { 5 } else { 4 } ;
1262
1262
1263
+ let mut suggs = vec ! [ ] ;
1263
1264
for ( idx, source) in sources. iter ( ) . take ( limit) . enumerate ( ) {
1264
1265
match * source {
1265
1266
CandidateSource :: Impl ( impl_did) => {
@@ -1322,7 +1323,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
1322
1323
let path = self . tcx . def_path_str ( trait_ref. skip_binder ( ) . def_id ) ;
1323
1324
1324
1325
let ty = match item. kind {
1325
- ty:: AssocKind :: Const | ty:: AssocKind :: Type => rcvr_ty ,
1326
+ ty:: AssocKind :: Const | ty:: AssocKind :: Type => impl_ty ,
1326
1327
ty:: AssocKind :: Fn => self
1327
1328
. tcx
1328
1329
. fn_sig ( item. def_id )
@@ -1334,19 +1335,22 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
1334
1335
. copied ( )
1335
1336
. unwrap_or ( rcvr_ty) ,
1336
1337
} ;
1337
- print_disambiguation_help (
1338
+ if let Some ( sugg ) = print_disambiguation_help (
1338
1339
item_name,
1339
1340
args,
1340
1341
err,
1341
1342
path,
1342
1343
ty,
1344
+ Some ( impl_ty) ,
1343
1345
item. kind ,
1344
1346
self . tcx . def_kind_descr ( item. kind . as_def_kind ( ) , item. def_id ) ,
1345
1347
sugg_span,
1346
1348
idx,
1347
1349
self . tcx . sess . source_map ( ) ,
1348
1350
item. fn_has_self_parameter ,
1349
- ) ;
1351
+ ) {
1352
+ suggs. push ( sugg) ;
1353
+ }
1350
1354
}
1351
1355
}
1352
1356
CandidateSource :: Trait ( trait_did) => {
@@ -1370,23 +1374,34 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
1370
1374
} ;
1371
1375
if let Some ( sugg_span) = sugg_span {
1372
1376
let path = self . tcx . def_path_str ( trait_did) ;
1373
- print_disambiguation_help (
1377
+ if let Some ( sugg ) = print_disambiguation_help (
1374
1378
item_name,
1375
1379
args,
1376
1380
err,
1377
1381
path,
1378
1382
rcvr_ty,
1383
+ None ,
1379
1384
item. kind ,
1380
1385
self . tcx . def_kind_descr ( item. kind . as_def_kind ( ) , item. def_id ) ,
1381
1386
sugg_span,
1382
1387
idx,
1383
1388
self . tcx . sess . source_map ( ) ,
1384
1389
item. fn_has_self_parameter ,
1385
- ) ;
1390
+ ) {
1391
+ suggs. push ( sugg) ;
1392
+ }
1386
1393
}
1387
1394
}
1388
1395
}
1389
1396
}
1397
+ if !suggs. is_empty ( ) && let Some ( span) = sugg_span {
1398
+ err. span_suggestions (
1399
+ span. with_hi ( item_name. span . lo ( ) ) ,
1400
+ "use fully-qualified syntax to disambiguate" ,
1401
+ suggs,
1402
+ Applicability :: MachineApplicable ,
1403
+ ) ;
1404
+ }
1390
1405
if sources. len ( ) > limit {
1391
1406
err. note ( format ! ( "and {} others" , sources. len( ) - limit) ) ;
1392
1407
}
@@ -3146,52 +3161,51 @@ fn print_disambiguation_help<'tcx>(
3146
3161
err : & mut Diagnostic ,
3147
3162
trait_name : String ,
3148
3163
rcvr_ty : Ty < ' _ > ,
3164
+ impl_self_ty : Option < Ty < ' _ > > ,
3149
3165
kind : ty:: AssocKind ,
3150
3166
def_kind_descr : & ' static str ,
3151
3167
span : Span ,
3152
3168
candidate : Option < usize > ,
3153
3169
source_map : & source_map:: SourceMap ,
3154
3170
fn_has_self_parameter : bool ,
3155
- ) {
3156
- let mut applicability = Applicability :: MachineApplicable ;
3157
- let ( span, sugg) = if let (
3158
- ty:: AssocKind :: Fn ,
3159
- Some ( MethodCallComponents { receiver, args, .. } ) ,
3160
- ) = ( kind, args)
3161
- {
3162
- let args = format ! (
3163
- "({}{})" ,
3164
- rcvr_ty. ref_mutability( ) . map_or( "" , |mutbl| mutbl. ref_prefix_str( ) ) ,
3165
- std:: iter:: once( receiver)
3166
- . chain( args. iter( ) )
3167
- . map( |arg| source_map. span_to_snippet( arg. span) . unwrap_or_else( |_| {
3168
- applicability = Applicability :: HasPlaceholders ;
3169
- "_" . to_owned( )
3170
- } ) )
3171
- . collect:: <Vec <_>>( )
3172
- . join( ", " ) ,
3173
- ) ;
3174
- let trait_name = if !fn_has_self_parameter {
3175
- format ! ( "<{rcvr_ty} as {trait_name}>" )
3171
+ ) -> Option < String > {
3172
+ Some (
3173
+ if let ( ty:: AssocKind :: Fn , Some ( MethodCallComponents { receiver, args, .. } ) ) = ( kind, args)
3174
+ {
3175
+ let args = format ! (
3176
+ "({}{})" ,
3177
+ rcvr_ty. ref_mutability( ) . map_or( "" , |mutbl| mutbl. ref_prefix_str( ) ) ,
3178
+ std:: iter:: once( receiver)
3179
+ . chain( args. iter( ) )
3180
+ . map( |arg| source_map
3181
+ . span_to_snippet( arg. span)
3182
+ . unwrap_or_else( |_| { "_" . to_owned( ) } ) )
3183
+ . collect:: <Vec <_>>( )
3184
+ . join( ", " ) ,
3185
+ ) ;
3186
+ let trait_name = if !fn_has_self_parameter && let Some ( impl_self_ty) = impl_self_ty {
3187
+ format ! ( "<{impl_self_ty} as {trait_name}>" )
3176
3188
} else {
3177
3189
trait_name
3178
3190
} ;
3179
- ( span, format ! ( "{trait_name}::{item_name}{args}" ) )
3180
- } else {
3181
- ( span. with_hi ( item_name. span . lo ( ) ) , format ! ( "<{rcvr_ty} as {trait_name}>::" ) )
3182
- } ;
3183
- err. span_suggestion_verbose (
3184
- span,
3185
- format ! (
3186
- "disambiguate the {} for {}" ,
3187
- def_kind_descr,
3188
- if let Some ( candidate) = candidate {
3189
- format!( "candidate #{candidate}" )
3190
- } else {
3191
- "the candidate" . to_string( )
3192
- } ,
3193
- ) ,
3194
- sugg,
3195
- applicability,
3196
- ) ;
3191
+ err. span_suggestion_verbose (
3192
+ span,
3193
+ format ! (
3194
+ "disambiguate the {def_kind_descr} for {}" ,
3195
+ if let Some ( candidate) = candidate {
3196
+ format!( "candidate #{candidate}" )
3197
+ } else {
3198
+ "the candidate" . to_string( )
3199
+ } ,
3200
+ ) ,
3201
+ format ! ( "{trait_name}::{item_name}{args}" ) ,
3202
+ Applicability :: HasPlaceholders ,
3203
+ ) ;
3204
+ return None ;
3205
+ } else if let Some ( impl_self_ty) = impl_self_ty {
3206
+ format ! ( "<{impl_self_ty} as {trait_name}>::" )
3207
+ } else {
3208
+ format ! ( "{trait_name}::" )
3209
+ } ,
3210
+ )
3197
3211
}
0 commit comments