@@ -3304,7 +3304,7 @@ fn print_disambiguation_help<'tcx>(
3304
3304
span : Span ,
3305
3305
item : ty:: AssocItem ,
3306
3306
) -> Option < String > {
3307
- let trait_impl_type = trait_ref. self_ty ( ) ;
3307
+ let trait_impl_type = trait_ref. self_ty ( ) . peel_refs ( ) ;
3308
3308
let trait_ref = if item. fn_has_self_parameter {
3309
3309
trait_ref. print_only_trait_name ( ) . to_string ( )
3310
3310
} else {
@@ -3332,9 +3332,53 @@ fn print_disambiguation_help<'tcx>(
3332
3332
. get ( 0 )
3333
3333
. and_then ( |ty| ty. ref_mutability ( ) )
3334
3334
. map_or ( "" , |mutbl| mutbl. ref_prefix_str ( ) ) ;
3335
- // If the type of first arg of this assoc function is `Self` or current trait impl type, we need to take the receiver as args. Otherwise, we don't.
3336
- let args = if let Some ( t) = first_arg_type
3337
- && ( t. to_string ( ) == "Self" || t == trait_impl_type)
3335
+
3336
+ // this is for `arbitrary_self_types`(egde case), see `tests/ui/methods/method-deref-to-same-trait-object-with-separate-params.rs`
3337
+ // for the following example:
3338
+ //
3339
+ // impl<T: ?Sized> NuisanceFoo for T {
3340
+ // fn foo(self) {}
3341
+ // }
3342
+ //
3343
+ // type of `self` is T(unspecified), which is not `Self` or current trait impl type, but the receiver still shouble be take as the first arg.
3344
+ let arbitrary_self_types_check =
3345
+ |hir_map : rustc_middle:: hir:: map:: Map < ' _ > ,
3346
+ local_def_id : Option < rustc_span:: def_id:: LocalDefId > |
3347
+ -> bool {
3348
+ match local_def_id {
3349
+ Some ( local_def_id) => match hir_map. find_by_def_id ( local_def_id) {
3350
+ Some ( node) => match node {
3351
+ Node :: ImplItem ( it) => match it. kind {
3352
+ hir:: ImplItemKind :: Fn ( _, body_id) => {
3353
+ let body = hir_map. body ( body_id) ;
3354
+ match body. params . get ( 0 ) {
3355
+ Some ( first_param) => {
3356
+ if let rustc_hir:: PatKind :: Binding ( _, _, ident, _) =
3357
+ & first_param. pat . kind
3358
+ {
3359
+ ident. name . as_str ( ) == "self"
3360
+ } else {
3361
+ false
3362
+ }
3363
+ }
3364
+ None => false ,
3365
+ }
3366
+ }
3367
+ _ => false ,
3368
+ } ,
3369
+ _ => false ,
3370
+ } ,
3371
+ None => false ,
3372
+ } ,
3373
+ None => false ,
3374
+ }
3375
+ } ;
3376
+
3377
+ // If the type of first arg of this assoc function is `Self` or current trait impl type or `arbitrary_self_types`, we need to take the receiver as args. Otherwise, we don't.
3378
+ let args = if let Some ( first_arg_type) = first_arg_type
3379
+ && ( first_arg_type == tcx. types . self_param
3380
+ || first_arg_type == trait_impl_type
3381
+ || arbitrary_self_types_check ( tcx. hir ( ) , item. def_id . as_local ( ) ) )
3338
3382
{
3339
3383
std:: iter:: once ( receiver) . chain ( args. iter ( ) ) . collect :: < Vec < _ > > ( )
3340
3384
} else {
0 commit comments