@@ -39,7 +39,7 @@ pub fn autoderef(
39
39
) -> impl Iterator < Item = Ty > {
40
40
let mut table = InferenceTable :: new ( db, env) ;
41
41
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 ) ;
43
43
let mut v = Vec :: new ( ) ;
44
44
while let Some ( ( ty, _steps) ) = autoderef. next ( ) {
45
45
// `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)>> {
89
89
at_start : bool ,
90
90
steps : T ,
91
91
explicit : bool ,
92
+ use_receiver_trait : bool ,
92
93
}
93
94
94
95
impl < ' 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 {
96
102
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 }
98
104
}
99
105
100
106
pub ( crate ) fn steps ( & self ) -> & [ ( AutoderefKind , Ty ) ] {
@@ -107,9 +113,10 @@ impl<'table, 'db> Autoderef<'table, 'db, usize> {
107
113
table : & ' table mut InferenceTable < ' db > ,
108
114
ty : Ty ,
109
115
explicit : bool ,
116
+ use_receiver_trait : bool ,
110
117
) -> Self {
111
118
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 }
113
120
}
114
121
}
115
122
@@ -137,7 +144,8 @@ impl<T: TrackAutoderefSteps> Iterator for Autoderef<'_, '_, T> {
137
144
return None ;
138
145
}
139
146
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 ) ?;
141
149
142
150
self . steps . push ( kind, & self . ty ) ;
143
151
self . ty = new_ty;
@@ -150,11 +158,12 @@ pub(crate) fn autoderef_step(
150
158
table : & mut InferenceTable < ' _ > ,
151
159
ty : Ty ,
152
160
explicit : bool ,
161
+ use_receiver_trait : bool ,
153
162
) -> Option < ( AutoderefKind , Ty ) > {
154
163
if let Some ( derefed) = builtin_deref ( table. db , & ty, explicit) {
155
164
Some ( ( AutoderefKind :: Builtin , table. resolve_ty_shallow ( derefed) ) )
156
165
} else {
157
- Some ( ( AutoderefKind :: Overloaded , deref_by_trait ( table, ty) ?) )
166
+ Some ( ( AutoderefKind :: Overloaded , deref_by_trait ( table, ty, use_receiver_trait ) ?) )
158
167
}
159
168
}
160
169
@@ -176,21 +185,33 @@ pub(crate) fn builtin_deref<'ty>(
176
185
pub ( crate ) fn deref_by_trait (
177
186
table @ & mut InferenceTable { db, .. } : & mut InferenceTable < ' _ > ,
178
187
ty : Ty ,
188
+ use_receiver_trait : bool ,
179
189
) -> Option < Ty > {
180
190
let _p = tracing:: info_span!( "deref_by_trait" ) . entered ( ) ;
181
191
if table. resolve_ty_shallow ( & ty) . inference_var ( Interner ) . is_some ( ) {
182
192
// don't try to deref unknown variables
183
193
return None ;
184
194
}
185
195
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 ( ) ?;
188
209
let target = db
189
- . trait_data ( deref_trait )
210
+ . trait_data ( trait_id )
190
211
. associated_type_by_name ( & Name :: new_symbol_root ( sym:: Target . clone ( ) ) ) ?;
191
212
192
213
let projection = {
193
- let b = TyBuilder :: subst_for_def ( db, deref_trait , None ) ;
214
+ let b = TyBuilder :: subst_for_def ( db, trait_id , None ) ;
194
215
if b. remaining ( ) != 1 {
195
216
// the Target type + Deref trait should only have one generic parameter,
196
217
// namely Deref's Self type
0 commit comments