@@ -39,7 +39,7 @@ pub fn autoderef(
3939) -> impl Iterator < Item = Ty > {
4040 let mut table = InferenceTable :: new ( db, env) ;
4141 let ty = table. instantiate_canonical ( ty) ;
42- let mut autoderef = Autoderef :: new_no_tracking ( & mut table, ty, false ) ;
42+ let mut autoderef = Autoderef :: new_no_tracking ( & mut table, ty, false , false ) ;
4343 let mut v = Vec :: new ( ) ;
4444 while let Some ( ( ty, _steps) ) = autoderef. next ( ) {
4545 // `ty` may contain unresolved inference variables. Since there's no chance they would be
@@ -89,12 +89,18 @@ pub(crate) struct Autoderef<'table, 'db, T = Vec<(AutoderefKind, Ty)>> {
8989 at_start : bool ,
9090 steps : T ,
9191 explicit : bool ,
92+ use_receiver_trait : bool ,
9293}
9394
9495impl < ' table , ' db > Autoderef < ' table , ' db > {
95- pub ( crate ) fn new ( table : & ' table mut InferenceTable < ' db > , ty : Ty , explicit : bool ) -> Self {
96+ pub ( crate ) fn new (
97+ table : & ' table mut InferenceTable < ' db > ,
98+ ty : Ty ,
99+ explicit : bool ,
100+ use_receiver_trait : bool ,
101+ ) -> Self {
96102 let ty = table. resolve_ty_shallow ( & ty) ;
97- Autoderef { table, ty, at_start : true , steps : Vec :: new ( ) , explicit }
103+ Autoderef { table, ty, at_start : true , steps : Vec :: new ( ) , explicit, use_receiver_trait }
98104 }
99105
100106 pub ( crate ) fn steps ( & self ) -> & [ ( AutoderefKind , Ty ) ] {
@@ -107,9 +113,10 @@ impl<'table, 'db> Autoderef<'table, 'db, usize> {
107113 table : & ' table mut InferenceTable < ' db > ,
108114 ty : Ty ,
109115 explicit : bool ,
116+ use_receiver_trait : bool ,
110117 ) -> Self {
111118 let ty = table. resolve_ty_shallow ( & ty) ;
112- Autoderef { table, ty, at_start : true , steps : 0 , explicit }
119+ Autoderef { table, ty, at_start : true , steps : 0 , explicit, use_receiver_trait }
113120 }
114121}
115122
@@ -137,7 +144,8 @@ impl<T: TrackAutoderefSteps> Iterator for Autoderef<'_, '_, T> {
137144 return None ;
138145 }
139146
140- let ( kind, new_ty) = autoderef_step ( self . table , self . ty . clone ( ) , self . explicit ) ?;
147+ let ( kind, new_ty) =
148+ autoderef_step ( self . table , self . ty . clone ( ) , self . explicit , self . use_receiver_trait ) ?;
141149
142150 self . steps . push ( kind, & self . ty ) ;
143151 self . ty = new_ty;
@@ -150,11 +158,12 @@ pub(crate) fn autoderef_step(
150158 table : & mut InferenceTable < ' _ > ,
151159 ty : Ty ,
152160 explicit : bool ,
161+ use_receiver_trait : bool ,
153162) -> Option < ( AutoderefKind , Ty ) > {
154163 if let Some ( derefed) = builtin_deref ( table. db , & ty, explicit) {
155164 Some ( ( AutoderefKind :: Builtin , table. resolve_ty_shallow ( derefed) ) )
156165 } else {
157- Some ( ( AutoderefKind :: Overloaded , deref_by_trait ( table, ty) ?) )
166+ Some ( ( AutoderefKind :: Overloaded , deref_by_trait ( table, ty, use_receiver_trait ) ?) )
158167 }
159168}
160169
@@ -176,21 +185,33 @@ pub(crate) fn builtin_deref<'ty>(
176185pub ( crate ) fn deref_by_trait (
177186 table @ & mut InferenceTable { db, .. } : & mut InferenceTable < ' _ > ,
178187 ty : Ty ,
188+ use_receiver_trait : bool ,
179189) -> Option < Ty > {
180190 let _p = tracing:: info_span!( "deref_by_trait" ) . entered ( ) ;
181191 if table. resolve_ty_shallow ( & ty) . inference_var ( Interner ) . is_some ( ) {
182192 // don't try to deref unknown variables
183193 return None ;
184194 }
185195
186- let deref_trait =
187- db. lang_item ( table. trait_env . krate , LangItem :: Deref ) . and_then ( |l| l. as_trait ( ) ) ?;
196+ let trait_id = || {
197+ if use_receiver_trait {
198+ if let Some ( receiver) =
199+ db. lang_item ( table. trait_env . krate , LangItem :: Receiver ) . and_then ( |l| l. as_trait ( ) )
200+ {
201+ return Some ( receiver) ;
202+ }
203+ }
204+ // Old rustc versions might not have `Receiver` trait.
205+ // Fallback to `Deref` if they don't
206+ db. lang_item ( table. trait_env . krate , LangItem :: Deref ) . and_then ( |l| l. as_trait ( ) )
207+ } ;
208+ let trait_id = trait_id ( ) ?;
188209 let target = db
189- . trait_data ( deref_trait )
210+ . trait_data ( trait_id )
190211 . associated_type_by_name ( & Name :: new_symbol_root ( sym:: Target . clone ( ) ) ) ?;
191212
192213 let projection = {
193- let b = TyBuilder :: subst_for_def ( db, deref_trait , None ) ;
214+ let b = TyBuilder :: subst_for_def ( db, trait_id , None ) ;
194215 if b. remaining ( ) != 1 {
195216 // the Target type + Deref trait should only have one generic parameter,
196217 // namely Deref's Self type
0 commit comments