@@ -33,7 +33,7 @@ use rustc_middle::ty::fast_reject::{simplify_type, TreatParams};
3333use rustc_middle:: ty:: print:: { with_crate_prefix, with_forced_trimmed_paths} ;
3434use rustc_middle:: ty:: IsSuggestable ;
3535use rustc_middle:: ty:: { self , GenericArgKind , Ty , TyCtxt , TypeVisitableExt } ;
36- use rustc_span:: def_id:: DefIdSet ;
36+ use rustc_span:: def_id:: { self , DefIdSet } ;
3737use rustc_span:: symbol:: { kw, sym, Ident } ;
3838use rustc_span:: Symbol ;
3939use rustc_span:: { edit_distance, ExpnKind , FileName , MacroKind , Span } ;
@@ -3312,7 +3312,7 @@ fn print_disambiguation_help<'tcx>(
33123312 span : Span ,
33133313 item : ty:: AssocItem ,
33143314) -> Option < String > {
3315- let trait_impl_type = trait_ref. self_ty ( ) ;
3315+ let trait_impl_type = trait_ref. self_ty ( ) . peel_refs ( ) ;
33163316 let trait_ref = if item. fn_has_self_parameter {
33173317 trait_ref. print_only_trait_name ( ) . to_string ( )
33183318 } else {
@@ -3340,9 +3340,43 @@ fn print_disambiguation_help<'tcx>(
33403340 . get ( 0 )
33413341 . and_then ( |ty| ty. ref_mutability ( ) )
33423342 . map_or ( "" , |mutbl| mutbl. ref_prefix_str ( ) ) ;
3343- // 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.
3344- let args = if let Some ( t) = first_arg_type
3345- && ( t. to_string ( ) == "Self" || t == trait_impl_type)
3343+
3344+ // this is for `arbitrary_self_types`(egde case), see `tests/ui/methods/method-deref-to-same-trait-object-with-separate-params.rs`
3345+ // for the following example:
3346+ //
3347+ // impl<T: ?Sized> NuisanceFoo for T {
3348+ // fn foo(self) {}
3349+ // }
3350+ //
3351+ // 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.
3352+ let arbitrary_self_types_check = |local_def_id : Option < def_id:: LocalDefId > | -> bool {
3353+ local_def_id. and_then ( |id| tcx. opt_hir_node_by_def_id ( id) ) . map_or ( false , |node| {
3354+ match node {
3355+ Node :: ImplItem ( it) => match it. kind {
3356+ hir:: ImplItemKind :: Fn ( _, body_id) => {
3357+ let body = tcx. hir ( ) . body ( body_id) ;
3358+ body. params . get ( 0 ) . map_or ( false , |first_param| {
3359+ match & first_param. pat . kind {
3360+ // check the name of first arg
3361+ rustc_hir:: PatKind :: Binding ( _, _, ident, _) => {
3362+ ident. name . as_str ( ) == "self"
3363+ }
3364+ _ => false ,
3365+ }
3366+ } )
3367+ }
3368+ _ => false ,
3369+ } ,
3370+ _ => false ,
3371+ }
3372+ } )
3373+ } ;
3374+
3375+ // 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.
3376+ let args = if let Some ( first_arg_type) = first_arg_type
3377+ && ( first_arg_type == tcx. types . self_param
3378+ || first_arg_type == trait_impl_type
3379+ || arbitrary_self_types_check ( item. def_id . as_local ( ) ) )
33463380 {
33473381 std:: iter:: once ( receiver) . chain ( args. iter ( ) ) . collect :: < Vec < _ > > ( )
33483382 } else {
0 commit comments