@@ -17,9 +17,9 @@ use hir_def::{
17
17
path:: { GenericArg , Path , PathSegment , PathSegments } ,
18
18
resolver:: { HasResolver , Resolver , TypeNs } ,
19
19
type_ref:: { TypeBound , TypeRef } ,
20
- AdtId , AssocContainerId , ConstId , EnumId , EnumVariantId , FunctionId , GenericDefId , HasModule ,
21
- ImplId , LocalFieldId , Lookup , StaticId , StructId , TraitId , TypeAliasId , TypeParamId , UnionId ,
22
- VariantId ,
20
+ AdtId , AssocContainerId , AssocItemId , ConstId , EnumId , EnumVariantId , FunctionId , GenericDefId ,
21
+ HasModule , ImplId , LocalFieldId , Lookup , StaticId , StructId , TraitId , TypeAliasId , TypeParamId ,
22
+ UnionId , VariantId ,
23
23
} ;
24
24
use ra_arena:: map:: ArenaMap ;
25
25
use ra_db:: CrateId ;
@@ -34,6 +34,7 @@ use crate::{
34
34
Binders , BoundVar , DebruijnIndex , FnSig , GenericPredicate , PolyFnSig , ProjectionPredicate ,
35
35
ProjectionTy , Substs , TraitEnvironment , TraitRef , Ty , TypeCtor , TypeWalk ,
36
36
} ;
37
+ use hir_expand:: name:: Name ;
37
38
38
39
#[ derive( Debug ) ]
39
40
pub struct TyLoweringContext < ' a > {
@@ -383,61 +384,37 @@ impl Ty {
383
384
res : Option < TypeNs > ,
384
385
segment : PathSegment < ' _ > ,
385
386
) -> Ty {
386
- let traits_from_env: Vec < _ > = match res {
387
- Some ( TypeNs :: SelfType ( impl_id) ) => match ctx. db . impl_trait ( impl_id) {
388
- None => return Ty :: Unknown ,
389
- Some ( trait_ref) => vec ! [ trait_ref. value] ,
390
- } ,
391
- Some ( TypeNs :: GenericParam ( param_id) ) => {
392
- let predicates = ctx. db . generic_predicates_for_param ( param_id) ;
393
- let mut traits_: Vec < _ > = predicates
394
- . iter ( )
395
- . filter_map ( |pred| match & pred. value {
396
- GenericPredicate :: Implemented ( tr) => Some ( tr. clone ( ) ) ,
397
- _ => None ,
398
- } )
399
- . collect ( ) ;
400
- // Handle `Self::Type` referring to own associated type in trait definitions
401
- if let GenericDefId :: TraitId ( trait_id) = param_id. parent {
402
- let generics = generics ( ctx. db . upcast ( ) , trait_id. into ( ) ) ;
403
- if generics. params . types [ param_id. local_id ] . provenance
404
- == TypeParamProvenance :: TraitSelf
405
- {
406
- let trait_ref = TraitRef {
407
- trait_ : trait_id,
408
- substs : Substs :: bound_vars ( & generics, DebruijnIndex :: INNERMOST ) ,
409
- } ;
410
- traits_. push ( trait_ref) ;
411
- }
387
+ if let Some ( res) = res {
388
+ let ty = associated_types ( ctx. db , res, move |name, t, associated_ty| {
389
+ if name == segment. name {
390
+ let substs = match ctx. type_param_mode {
391
+ TypeParamLoweringMode :: Placeholder => {
392
+ // if we're lowering to placeholders, we have to put
393
+ // them in now
394
+ let s = Substs :: type_params (
395
+ ctx. db ,
396
+ ctx. resolver
397
+ . generic_def ( )
398
+ . expect ( "there should be generics if there's a generic param" ) ,
399
+ ) ;
400
+ t. substs . clone ( ) . subst_bound_vars ( & s)
401
+ }
402
+ TypeParamLoweringMode :: Variable => t. substs . clone ( ) ,
403
+ } ;
404
+ // FIXME handle type parameters on the segment
405
+ return Some ( Ty :: Projection ( ProjectionTy {
406
+ associated_ty,
407
+ parameters : substs,
408
+ } ) ) ;
412
409
}
413
- traits_
414
- }
415
- _ => return Ty :: Unknown ,
416
- } ;
417
- let traits = traits_from_env. into_iter ( ) . flat_map ( |t| all_super_trait_refs ( ctx. db , t) ) ;
418
- for t in traits {
419
- if let Some ( associated_ty) =
420
- ctx. db . trait_data ( t. trait_ ) . associated_type_by_name ( & segment. name )
421
- {
422
- let substs = match ctx. type_param_mode {
423
- TypeParamLoweringMode :: Placeholder => {
424
- // if we're lowering to placeholders, we have to put
425
- // them in now
426
- let s = Substs :: type_params (
427
- ctx. db ,
428
- ctx. resolver
429
- . generic_def ( )
430
- . expect ( "there should be generics if there's a generic param" ) ,
431
- ) ;
432
- t. substs . subst_bound_vars ( & s)
433
- }
434
- TypeParamLoweringMode :: Variable => t. substs ,
435
- } ;
436
- // FIXME handle (forbid) type parameters on the segment
437
- return Ty :: Projection ( ProjectionTy { associated_ty, parameters : substs } ) ;
438
- }
410
+
411
+ None
412
+ } ) ;
413
+
414
+ ty. unwrap_or ( Ty :: Unknown )
415
+ } else {
416
+ Ty :: Unknown
439
417
}
440
- Ty :: Unknown
441
418
}
442
419
443
420
fn from_hir_path_inner (
@@ -694,6 +671,61 @@ pub fn callable_item_sig(db: &dyn HirDatabase, def: CallableDef) -> PolyFnSig {
694
671
}
695
672
}
696
673
674
+ pub fn associated_types < R > (
675
+ db : & dyn HirDatabase ,
676
+ res : TypeNs ,
677
+ mut cb : impl FnMut ( & Name , & TraitRef , TypeAliasId ) -> Option < R > ,
678
+ ) -> Option < R > {
679
+ let traits_from_env: Vec < _ > = match res {
680
+ TypeNs :: SelfType ( impl_id) => match db. impl_trait ( impl_id) {
681
+ None => vec ! [ ] ,
682
+ Some ( trait_ref) => vec ! [ trait_ref. value] ,
683
+ } ,
684
+ TypeNs :: GenericParam ( param_id) => {
685
+ let predicates = db. generic_predicates_for_param ( param_id) ;
686
+ let mut traits_: Vec < _ > = predicates
687
+ . iter ( )
688
+ . filter_map ( |pred| match & pred. value {
689
+ GenericPredicate :: Implemented ( tr) => Some ( tr. clone ( ) ) ,
690
+ _ => None ,
691
+ } )
692
+ . collect ( ) ;
693
+ // Handle `Self::Type` referring to own associated type in trait definitions
694
+ if let GenericDefId :: TraitId ( trait_id) = param_id. parent {
695
+ let generics = generics ( db. upcast ( ) , trait_id. into ( ) ) ;
696
+ if generics. params . types [ param_id. local_id ] . provenance
697
+ == TypeParamProvenance :: TraitSelf
698
+ {
699
+ let trait_ref = TraitRef {
700
+ trait_ : trait_id,
701
+ substs : Substs :: bound_vars ( & generics, DebruijnIndex :: INNERMOST ) ,
702
+ } ;
703
+ traits_. push ( trait_ref) ;
704
+ }
705
+ }
706
+ traits_
707
+ }
708
+ _ => vec ! [ ] ,
709
+ } ;
710
+
711
+ for t in traits_from_env. into_iter ( ) . flat_map ( move |t| all_super_trait_refs ( db, t) ) {
712
+ let data = db. trait_data ( t. trait_ ) ;
713
+
714
+ for ( name, assoc_id) in & data. items {
715
+ match assoc_id {
716
+ AssocItemId :: TypeAliasId ( alias) => {
717
+ if let Some ( result) = cb ( name, & t, * alias) {
718
+ return Some ( result) ;
719
+ }
720
+ }
721
+ AssocItemId :: FunctionId ( _) | AssocItemId :: ConstId ( _) => { }
722
+ }
723
+ }
724
+ }
725
+
726
+ None
727
+ }
728
+
697
729
/// Build the type of all specific fields of a struct or enum variant.
698
730
pub ( crate ) fn field_types_query (
699
731
db : & dyn HirDatabase ,
0 commit comments