@@ -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,38 @@ 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 ) ,
387
+ if let Some ( res) = res {
388
+ let ty =
389
+ associated_type_shorthand_candidates ( ctx. db , res, move |name, t, associated_ty| {
390
+ if name == segment. name {
391
+ let substs = match ctx. type_param_mode {
392
+ TypeParamLoweringMode :: Placeholder => {
393
+ // if we're lowering to placeholders, we have to put
394
+ // them in now
395
+ let s = Substs :: type_params (
396
+ ctx. db ,
397
+ ctx. resolver . generic_def ( ) . expect (
398
+ "there should be generics if there's a generic param" ,
399
+ ) ,
400
+ ) ;
401
+ t. substs . clone ( ) . subst_bound_vars ( & s)
402
+ }
403
+ TypeParamLoweringMode :: Variable => t. substs . clone ( ) ,
409
404
} ;
410
- traits_. push ( trait_ref) ;
405
+ // FIXME handle type parameters on the segment
406
+ return Some ( Ty :: Projection ( ProjectionTy {
407
+ associated_ty,
408
+ parameters : substs,
409
+ } ) ) ;
411
410
}
412
- }
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
- }
411
+
412
+ None
413
+ } ) ;
414
+
415
+ ty. unwrap_or ( Ty :: Unknown )
416
+ } else {
417
+ Ty :: Unknown
439
418
}
440
- Ty :: Unknown
441
419
}
442
420
443
421
fn from_hir_path_inner (
@@ -694,6 +672,61 @@ pub fn callable_item_sig(db: &dyn HirDatabase, def: CallableDef) -> PolyFnSig {
694
672
}
695
673
}
696
674
675
+ pub fn associated_type_shorthand_candidates < R > (
676
+ db : & dyn HirDatabase ,
677
+ res : TypeNs ,
678
+ mut cb : impl FnMut ( & Name , & TraitRef , TypeAliasId ) -> Option < R > ,
679
+ ) -> Option < R > {
680
+ let traits_from_env: Vec < _ > = match res {
681
+ TypeNs :: SelfType ( impl_id) => match db. impl_trait ( impl_id) {
682
+ None => vec ! [ ] ,
683
+ Some ( trait_ref) => vec ! [ trait_ref. value] ,
684
+ } ,
685
+ TypeNs :: GenericParam ( param_id) => {
686
+ let predicates = db. generic_predicates_for_param ( param_id) ;
687
+ let mut traits_: Vec < _ > = predicates
688
+ . iter ( )
689
+ . filter_map ( |pred| match & pred. value {
690
+ GenericPredicate :: Implemented ( tr) => Some ( tr. clone ( ) ) ,
691
+ _ => None ,
692
+ } )
693
+ . collect ( ) ;
694
+ // Handle `Self::Type` referring to own associated type in trait definitions
695
+ if let GenericDefId :: TraitId ( trait_id) = param_id. parent {
696
+ let generics = generics ( db. upcast ( ) , trait_id. into ( ) ) ;
697
+ if generics. params . types [ param_id. local_id ] . provenance
698
+ == TypeParamProvenance :: TraitSelf
699
+ {
700
+ let trait_ref = TraitRef {
701
+ trait_ : trait_id,
702
+ substs : Substs :: bound_vars ( & generics, DebruijnIndex :: INNERMOST ) ,
703
+ } ;
704
+ traits_. push ( trait_ref) ;
705
+ }
706
+ }
707
+ traits_
708
+ }
709
+ _ => vec ! [ ] ,
710
+ } ;
711
+
712
+ for t in traits_from_env. into_iter ( ) . flat_map ( move |t| all_super_trait_refs ( db, t) ) {
713
+ let data = db. trait_data ( t. trait_ ) ;
714
+
715
+ for ( name, assoc_id) in & data. items {
716
+ match assoc_id {
717
+ AssocItemId :: TypeAliasId ( alias) => {
718
+ if let Some ( result) = cb ( name, & t, * alias) {
719
+ return Some ( result) ;
720
+ }
721
+ }
722
+ AssocItemId :: FunctionId ( _) | AssocItemId :: ConstId ( _) => { }
723
+ }
724
+ }
725
+ }
726
+
727
+ None
728
+ }
729
+
697
730
/// Build the type of all specific fields of a struct or enum variant.
698
731
pub ( crate ) fn field_types_query (
699
732
db : & dyn HirDatabase ,
0 commit comments