@@ -17,9 +17,9 @@ use hir_def::{
1717 path:: { GenericArg , Path , PathSegment , PathSegments } ,
1818 resolver:: { HasResolver , Resolver , TypeNs } ,
1919 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 ,
2323} ;
2424use ra_arena:: map:: ArenaMap ;
2525use ra_db:: CrateId ;
@@ -34,6 +34,7 @@ use crate::{
3434 Binders , BoundVar , DebruijnIndex , FnSig , GenericPredicate , PolyFnSig , ProjectionPredicate ,
3535 ProjectionTy , Substs , TraitEnvironment , TraitRef , Ty , TypeCtor , TypeWalk ,
3636} ;
37+ use hir_expand:: name:: Name ;
3738
3839#[ derive( Debug ) ]
3940pub struct TyLoweringContext < ' a > {
@@ -383,61 +384,38 @@ impl Ty {
383384 res : Option < TypeNs > ,
384385 segment : PathSegment < ' _ > ,
385386 ) -> 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 ( ) ,
409404 } ;
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+ } ) ) ;
411410 }
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
439418 }
440- Ty :: Unknown
441419 }
442420
443421 fn from_hir_path_inner (
@@ -694,6 +672,61 @@ pub fn callable_item_sig(db: &dyn HirDatabase, def: CallableDef) -> PolyFnSig {
694672 }
695673}
696674
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+
697730/// Build the type of all specific fields of a struct or enum variant.
698731pub ( crate ) fn field_types_query (
699732 db : & dyn HirDatabase ,
0 commit comments