@@ -30,6 +30,7 @@ use smallvec::SmallVec;
30
30
use stdx:: impl_from;
31
31
use syntax:: ast;
32
32
33
+ use crate :: all_super_traits;
33
34
use crate :: {
34
35
consteval,
35
36
db:: HirDatabase ,
@@ -531,9 +532,10 @@ impl<'a> TyLoweringContext<'a> {
531
532
532
533
fn select_associated_type ( & self , res : Option < TypeNs > , segment : PathSegment < ' _ > ) -> Ty {
533
534
if let Some ( res) = res {
534
- let ty = associated_type_shorthand_candidates (
535
+ let ty = named_associated_type_shorthand_candidates (
535
536
self . db ,
536
537
res,
538
+ Some ( segment. name . clone ( ) ) ,
537
539
move |name, t, associated_ty| {
538
540
if name == segment. name {
539
541
let substs = match self . type_param_mode {
@@ -555,16 +557,16 @@ impl<'a> TyLoweringContext<'a> {
555
557
// associated_type_shorthand_candidates does not do that
556
558
let substs = substs. shifted_in_from ( & Interner , self . in_binders ) ;
557
559
// FIXME handle type parameters on the segment
558
- return Some (
560
+ Some (
559
561
TyKind :: Alias ( AliasTy :: Projection ( ProjectionTy {
560
562
associated_ty_id : to_assoc_type_id ( associated_ty) ,
561
563
substitution : substs,
562
564
} ) )
563
565
. intern ( & Interner ) ,
564
- ) ;
566
+ )
567
+ } else {
568
+ None
565
569
}
566
-
567
- None
568
570
} ,
569
571
) ;
570
572
@@ -935,6 +937,15 @@ pub fn callable_item_sig(db: &dyn HirDatabase, def: CallableDefId) -> PolyFnSig
935
937
pub fn associated_type_shorthand_candidates < R > (
936
938
db : & dyn HirDatabase ,
937
939
res : TypeNs ,
940
+ cb : impl FnMut ( & Name , & TraitRef , TypeAliasId ) -> Option < R > ,
941
+ ) -> Option < R > {
942
+ named_associated_type_shorthand_candidates ( db, res, None , cb)
943
+ }
944
+
945
+ fn named_associated_type_shorthand_candidates < R > (
946
+ db : & dyn HirDatabase ,
947
+ res : TypeNs ,
948
+ assoc_name : Option < Name > ,
938
949
mut cb : impl FnMut ( & Name , & TraitRef , TypeAliasId ) -> Option < R > ,
939
950
) -> Option < R > {
940
951
let mut search = |t| {
@@ -959,7 +970,7 @@ pub fn associated_type_shorthand_candidates<R>(
959
970
db. impl_trait ( impl_id) ?. into_value_and_skipped_binders ( ) . 0 ,
960
971
) ,
961
972
TypeNs :: GenericParam ( param_id) => {
962
- let predicates = db. generic_predicates_for_param ( param_id) ;
973
+ let predicates = db. generic_predicates_for_param ( param_id, assoc_name ) ;
963
974
let res = predicates. iter ( ) . find_map ( |pred| match pred. skip_binders ( ) . skip_binders ( ) {
964
975
// FIXME: how to correctly handle higher-ranked bounds here?
965
976
WhereClause :: Implemented ( tr) => search (
@@ -1022,6 +1033,7 @@ pub(crate) fn field_types_query(
1022
1033
pub ( crate ) fn generic_predicates_for_param_query (
1023
1034
db : & dyn HirDatabase ,
1024
1035
param_id : TypeParamId ,
1036
+ assoc_name : Option < Name > ,
1025
1037
) -> Arc < [ Binders < QuantifiedWhereClause > ] > {
1026
1038
let resolver = param_id. parent . resolver ( db. upcast ( ) ) ;
1027
1039
let ctx =
@@ -1031,13 +1043,46 @@ pub(crate) fn generic_predicates_for_param_query(
1031
1043
. where_predicates_in_scope ( )
1032
1044
// we have to filter out all other predicates *first*, before attempting to lower them
1033
1045
. filter ( |pred| match pred {
1034
- WherePredicate :: ForLifetime { target, .. }
1035
- | WherePredicate :: TypeBound { target, .. } => match target {
1036
- WherePredicateTypeTarget :: TypeRef ( type_ref) => {
1037
- ctx. lower_ty_only_param ( type_ref) == Some ( param_id)
1046
+ WherePredicate :: ForLifetime { target, bound, .. }
1047
+ | WherePredicate :: TypeBound { target, bound, .. } => {
1048
+ match target {
1049
+ WherePredicateTypeTarget :: TypeRef ( type_ref) => {
1050
+ if ctx. lower_ty_only_param ( type_ref) != Some ( param_id) {
1051
+ return false ;
1052
+ }
1053
+ }
1054
+ WherePredicateTypeTarget :: TypeParam ( local_id) => {
1055
+ if * local_id != param_id. local_id {
1056
+ return false ;
1057
+ }
1058
+ }
1059
+ } ;
1060
+
1061
+ match & * * bound {
1062
+ TypeBound :: ForLifetime ( _, path) | TypeBound :: Path ( path, _) => {
1063
+ // Only lower the bound if the trait could possibly define the associated
1064
+ // type we're looking for.
1065
+
1066
+ let assoc_name = match & assoc_name {
1067
+ Some ( it) => it,
1068
+ None => return true ,
1069
+ } ;
1070
+ let tr = match resolver
1071
+ . resolve_path_in_type_ns_fully ( db. upcast ( ) , path. mod_path ( ) )
1072
+ {
1073
+ Some ( TypeNs :: TraitId ( tr) ) => tr,
1074
+ _ => return false ,
1075
+ } ;
1076
+
1077
+ all_super_traits ( db. upcast ( ) , tr) . iter ( ) . any ( |tr| {
1078
+ db. trait_data ( * tr) . items . iter ( ) . any ( |( name, item) | {
1079
+ matches ! ( item, AssocItemId :: TypeAliasId ( _) ) && name == assoc_name
1080
+ } )
1081
+ } )
1082
+ }
1083
+ TypeBound :: Lifetime ( _) | TypeBound :: Error => false ,
1038
1084
}
1039
- WherePredicateTypeTarget :: TypeParam ( local_id) => * local_id == param_id. local_id ,
1040
- } ,
1085
+ }
1041
1086
WherePredicate :: Lifetime { .. } => false ,
1042
1087
} )
1043
1088
. flat_map ( |pred| ctx. lower_where_predicate ( pred, true ) . map ( |p| make_binders ( & generics, p) ) )
@@ -1056,6 +1101,7 @@ pub(crate) fn generic_predicates_for_param_recover(
1056
1101
_db : & dyn HirDatabase ,
1057
1102
_cycle : & [ String ] ,
1058
1103
_param_id : & TypeParamId ,
1104
+ _assoc_name : & Option < Name > ,
1059
1105
) -> Arc < [ Binders < QuantifiedWhereClause > ] > {
1060
1106
Arc :: new ( [ ] )
1061
1107
}
0 commit comments