@@ -27,13 +27,14 @@ use rustc_infer::infer::{
2727 type_variable:: { TypeVariableOrigin , TypeVariableOriginKind } ,
2828 RegionVariableOrigin ,
2929} ;
30+ use rustc_middle:: hir:: map;
3031use rustc_middle:: infer:: unify_key:: { ConstVariableOrigin , ConstVariableOriginKind } ;
3132use rustc_middle:: ty:: fast_reject:: DeepRejectCtxt ;
3233use rustc_middle:: ty:: fast_reject:: { simplify_type, TreatParams } ;
3334use rustc_middle:: ty:: print:: { with_crate_prefix, with_forced_trimmed_paths} ;
3435use rustc_middle:: ty:: IsSuggestable ;
3536use rustc_middle:: ty:: { self , GenericArgKind , Ty , TyCtxt , TypeVisitableExt } ;
36- use rustc_span:: def_id:: DefIdSet ;
37+ use rustc_span:: def_id:: { self , DefIdSet } ;
3738use rustc_span:: symbol:: { kw, sym, Ident } ;
3839use rustc_span:: Symbol ;
3940use rustc_span:: { edit_distance, ExpnKind , FileName , MacroKind , Span } ;
@@ -3304,7 +3305,7 @@ fn print_disambiguation_help<'tcx>(
33043305 span : Span ,
33053306 item : ty:: AssocItem ,
33063307) -> Option < String > {
3307- let trait_impl_type = trait_ref. self_ty ( ) ;
3308+ let trait_impl_type = trait_ref. self_ty ( ) . peel_refs ( ) ;
33083309 let trait_ref = if item. fn_has_self_parameter {
33093310 trait_ref. print_only_trait_name ( ) . to_string ( )
33103311 } else {
@@ -3332,9 +3333,51 @@ fn print_disambiguation_help<'tcx>(
33323333 . get ( 0 )
33333334 . and_then ( |ty| ty. ref_mutability ( ) )
33343335 . 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)
3336+
3337+ // this is for `arbitrary_self_types`(egde case), see `tests/ui/methods/method-deref-to-same-trait-object-with-separate-params.rs`
3338+ // for the following example:
3339+ //
3340+ // impl<T: ?Sized> NuisanceFoo for T {
3341+ // fn foo(self) {}
3342+ // }
3343+ //
3344+ // 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.
3345+ let arbitrary_self_types_check =
3346+ |hir_map : map:: Map < ' _ > , local_def_id : Option < def_id:: LocalDefId > | -> bool {
3347+ match local_def_id {
3348+ Some ( local_def_id) => match hir_map. find_by_def_id ( local_def_id) {
3349+ Some ( node) => match node {
3350+ Node :: ImplItem ( it) => match it. kind {
3351+ hir:: ImplItemKind :: Fn ( _, body_id) => {
3352+ let body = hir_map. body ( body_id) ;
3353+ match body. params . get ( 0 ) {
3354+ Some ( first_param) => {
3355+ if let rustc_hir:: PatKind :: Binding ( _, _, ident, _) =
3356+ & first_param. pat . kind
3357+ {
3358+ ident. name . as_str ( ) == "self"
3359+ } else {
3360+ false
3361+ }
3362+ }
3363+ None => false ,
3364+ }
3365+ }
3366+ _ => false ,
3367+ } ,
3368+ _ => false ,
3369+ } ,
3370+ None => false ,
3371+ } ,
3372+ None => false ,
3373+ }
3374+ } ;
3375+
3376+ // 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.
3377+ let args = if let Some ( first_arg_type) = first_arg_type
3378+ && ( first_arg_type == tcx. types . self_param
3379+ || first_arg_type == trait_impl_type
3380+ || arbitrary_self_types_check ( tcx. hir ( ) , item. def_id . as_local ( ) ) )
33383381 {
33393382 std:: iter:: once ( receiver) . chain ( args. iter ( ) ) . collect :: < Vec < _ > > ( )
33403383 } else {
0 commit comments