@@ -91,7 +91,14 @@ pub enum TypeParamLoweringMode {
91
91
92
92
impl Ty {
93
93
pub fn from_hir ( ctx : & TyLoweringContext < ' _ , impl HirDatabase > , type_ref : & TypeRef ) -> Self {
94
- match type_ref {
94
+ Ty :: from_hir_ext ( ctx, type_ref) . 0
95
+ }
96
+ pub fn from_hir_ext (
97
+ ctx : & TyLoweringContext < ' _ , impl HirDatabase > ,
98
+ type_ref : & TypeRef ,
99
+ ) -> ( Self , Option < TypeNs > ) {
100
+ let mut res = None ;
101
+ let ty = match type_ref {
95
102
TypeRef :: Never => Ty :: simple ( TypeCtor :: Never ) ,
96
103
TypeRef :: Tuple ( inner) => {
97
104
let inner_tys: Arc < [ Ty ] > = inner. iter ( ) . map ( |tr| Ty :: from_hir ( ctx, tr) ) . collect ( ) ;
@@ -100,7 +107,11 @@ impl Ty {
100
107
Substs ( inner_tys) ,
101
108
)
102
109
}
103
- TypeRef :: Path ( path) => Ty :: from_hir_path ( ctx, path) ,
110
+ TypeRef :: Path ( path) => {
111
+ let ( ty, res_) = Ty :: from_hir_path ( ctx, path) ;
112
+ res = res_;
113
+ ty
114
+ }
104
115
TypeRef :: RawPtr ( inner, mutability) => {
105
116
let inner_ty = Ty :: from_hir ( ctx, inner) ;
106
117
Ty :: apply_one ( TypeCtor :: RawPtr ( * mutability) , inner_ty)
@@ -183,7 +194,8 @@ impl Ty {
183
194
}
184
195
}
185
196
TypeRef :: Error => Ty :: Unknown ,
186
- }
197
+ } ;
198
+ ( ty, res)
187
199
}
188
200
189
201
/// This is only for `generic_predicates_for_param`, where we can't just
@@ -217,17 +229,19 @@ impl Ty {
217
229
pub ( crate ) fn from_type_relative_path (
218
230
ctx : & TyLoweringContext < ' _ , impl HirDatabase > ,
219
231
ty : Ty ,
232
+ // We need the original resolution to lower `Self::AssocTy` correctly
233
+ res : Option < TypeNs > ,
220
234
remaining_segments : PathSegments < ' _ > ,
221
- ) -> Ty {
235
+ ) -> ( Ty , Option < TypeNs > ) {
222
236
if remaining_segments. len ( ) == 1 {
223
237
// resolve unselected assoc types
224
238
let segment = remaining_segments. first ( ) . unwrap ( ) ;
225
- Ty :: select_associated_type ( ctx, ty, segment)
239
+ ( Ty :: select_associated_type ( ctx, ty, res , segment) , None )
226
240
} else if remaining_segments. len ( ) > 1 {
227
241
// FIXME report error (ambiguous associated type)
228
- Ty :: Unknown
242
+ ( Ty :: Unknown , None )
229
243
} else {
230
- ty
244
+ ( ty , res )
231
245
}
232
246
}
233
247
@@ -236,14 +250,14 @@ impl Ty {
236
250
resolution : TypeNs ,
237
251
resolved_segment : PathSegment < ' _ > ,
238
252
remaining_segments : PathSegments < ' _ > ,
239
- ) -> Ty {
253
+ ) -> ( Ty , Option < TypeNs > ) {
240
254
let ty = match resolution {
241
255
TypeNs :: TraitId ( trait_) => {
242
256
// if this is a bare dyn Trait, we'll directly put the required ^0 for the self type in there
243
257
let self_ty = if remaining_segments. len ( ) == 0 { Some ( Ty :: Bound ( 0 ) ) } else { None } ;
244
258
let trait_ref =
245
259
TraitRef :: from_resolved_path ( ctx, trait_, resolved_segment, self_ty) ;
246
- return if remaining_segments. len ( ) == 1 {
260
+ let ty = if remaining_segments. len ( ) == 1 {
247
261
let segment = remaining_segments. first ( ) . unwrap ( ) ;
248
262
let associated_ty = associated_type_by_name_including_super_traits (
249
263
ctx. db ,
@@ -269,6 +283,7 @@ impl Ty {
269
283
} else {
270
284
Ty :: Dyn ( Arc :: new ( [ GenericPredicate :: Implemented ( trait_ref) ] ) )
271
285
} ;
286
+ return ( ty, None ) ;
272
287
}
273
288
TypeNs :: GenericParam ( param_id) => {
274
289
let generics =
@@ -306,22 +321,25 @@ impl Ty {
306
321
TypeNs :: BuiltinType ( it) => Ty :: from_hir_path_inner ( ctx, resolved_segment, it. into ( ) ) ,
307
322
TypeNs :: TypeAliasId ( it) => Ty :: from_hir_path_inner ( ctx, resolved_segment, it. into ( ) ) ,
308
323
// FIXME: report error
309
- TypeNs :: EnumVariantId ( _) => return Ty :: Unknown ,
324
+ TypeNs :: EnumVariantId ( _) => return ( Ty :: Unknown , None ) ,
310
325
} ;
311
326
312
- Ty :: from_type_relative_path ( ctx, ty, remaining_segments)
327
+ Ty :: from_type_relative_path ( ctx, ty, Some ( resolution ) , remaining_segments)
313
328
}
314
329
315
- pub ( crate ) fn from_hir_path ( ctx : & TyLoweringContext < ' _ , impl HirDatabase > , path : & Path ) -> Ty {
330
+ pub ( crate ) fn from_hir_path (
331
+ ctx : & TyLoweringContext < ' _ , impl HirDatabase > ,
332
+ path : & Path ,
333
+ ) -> ( Ty , Option < TypeNs > ) {
316
334
// Resolve the path (in type namespace)
317
335
if let Some ( type_ref) = path. type_anchor ( ) {
318
- let ty = Ty :: from_hir ( ctx, & type_ref) ;
319
- return Ty :: from_type_relative_path ( ctx, ty, path. segments ( ) ) ;
336
+ let ( ty , res ) = Ty :: from_hir_ext ( ctx, & type_ref) ;
337
+ return Ty :: from_type_relative_path ( ctx, ty, res , path. segments ( ) ) ;
320
338
}
321
339
let ( resolution, remaining_index) =
322
340
match ctx. resolver . resolve_path_in_type_ns ( ctx. db , path. mod_path ( ) ) {
323
341
Some ( it) => it,
324
- None => return Ty :: Unknown ,
342
+ None => return ( Ty :: Unknown , None ) ,
325
343
} ;
326
344
let ( resolved_segment, remaining_segments) = match remaining_index {
327
345
None => (
@@ -336,31 +354,27 @@ impl Ty {
336
354
fn select_associated_type (
337
355
ctx : & TyLoweringContext < ' _ , impl HirDatabase > ,
338
356
self_ty : Ty ,
357
+ res : Option < TypeNs > ,
339
358
segment : PathSegment < ' _ > ,
340
359
) -> Ty {
341
- let def = match ctx . resolver . generic_def ( ) {
342
- Some ( def ) => def ,
343
- None => return Ty :: Unknown , // this can't actually happen
344
- } ;
345
- let param_id = match self_ty {
346
- Ty :: Placeholder ( id ) if ctx . type_param_mode == TypeParamLoweringMode :: Placeholder => id ,
347
- Ty :: Bound ( idx ) if ctx . type_param_mode == TypeParamLoweringMode :: Variable => {
348
- let generics = generics ( ctx . db , def ) ;
349
- let param_id = if let Some ( ( id , _ ) ) = generics . iter ( ) . nth ( idx as usize ) {
350
- id
351
- } else {
352
- return Ty :: Unknown ;
353
- } ;
354
- param_id
360
+ let traits_from_env : Vec < _ > = match res {
361
+ Some ( TypeNs :: SelfType ( impl_id ) ) => match ctx . db . impl_trait ( impl_id ) {
362
+ None => return Ty :: Unknown ,
363
+ Some ( trait_ref ) => vec ! [ trait_ref . value . trait_ ] ,
364
+ } ,
365
+ Some ( TypeNs :: GenericParam ( param_id ) ) => {
366
+ let predicates = ctx . db . generic_predicates_for_param ( param_id ) ;
367
+ predicates
368
+ . iter ( )
369
+ . filter_map ( |pred| match & pred . value {
370
+ GenericPredicate :: Implemented ( tr ) => Some ( tr . trait_ ) ,
371
+ _ => None ,
372
+ } )
373
+ . collect ( )
355
374
}
356
- _ => return Ty :: Unknown , // Error: Ambiguous associated type
375
+ _ => return Ty :: Unknown ,
357
376
} ;
358
- let predicates = ctx. db . generic_predicates_for_param ( param_id) ;
359
- let traits_from_env = predicates. iter ( ) . filter_map ( |pred| match & pred. value {
360
- GenericPredicate :: Implemented ( tr) => Some ( tr. trait_ ) ,
361
- _ => None ,
362
- } ) ;
363
- let traits = traits_from_env. flat_map ( |t| all_super_traits ( ctx. db , t) ) ;
377
+ let traits = traits_from_env. into_iter ( ) . flat_map ( |t| all_super_traits ( ctx. db , t) ) ;
364
378
for t in traits {
365
379
if let Some ( associated_ty) = ctx. db . trait_data ( t) . associated_type_by_name ( & segment. name )
366
380
{
0 commit comments