Skip to content

Commit 33aa2f8

Browse files
committed
Fix assoc type selection
1 parent 4a8279a commit 33aa2f8

File tree

2 files changed

+43
-32
lines changed

2 files changed

+43
-32
lines changed

crates/ra_hir_ty/src/lower.rs

Lines changed: 40 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ use std::sync::Arc;
1010

1111
use hir_def::{
1212
builtin_type::BuiltinType,
13-
generics::{WherePredicateTarget, WherePredicate},
13+
generics::{WherePredicate, WherePredicateTarget},
1414
path::{GenericArg, Path, PathSegment, PathSegments},
1515
resolver::{HasResolver, Resolver, TypeNs},
1616
type_ref::{TypeBound, TypeRef},
@@ -27,8 +27,8 @@ use crate::{
2727
all_super_traits, associated_type_by_name_including_super_traits, generics, make_mut_slice,
2828
variant_data,
2929
},
30-
FnSig, GenericPredicate, ProjectionPredicate, ProjectionTy, Substs, TraitEnvironment, TraitRef,
31-
Ty, TypeCtor, PolyFnSig, Binders,
30+
Binders, FnSig, GenericPredicate, PolyFnSig, ProjectionPredicate, ProjectionTy, Substs,
31+
TraitEnvironment, TraitRef, Ty, TypeCtor,
3232
};
3333

3434
#[derive(Debug)]
@@ -62,7 +62,7 @@ impl<'a, DB: HirDatabase> TyLoweringContext<'a, DB> {
6262
}
6363
}
6464

65-
#[derive(Copy, Clone, Debug)]
65+
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
6666
pub enum ImplTraitLoweringMode {
6767
/// `impl Trait` gets lowered into an opaque type that doesn't unify with
6868
/// anything except itself. This is used in places where values flow 'out',
@@ -78,7 +78,7 @@ pub enum ImplTraitLoweringMode {
7878
Disallowed,
7979
}
8080

81-
#[derive(Copy, Clone, Debug)]
81+
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
8282
pub enum TypeParamLoweringMode {
8383
Placeholder,
8484
Variable,
@@ -140,12 +140,13 @@ impl Ty {
140140
ImplTraitLoweringMode::Variable => {
141141
let idx = ctx.impl_trait_counter.get();
142142
ctx.impl_trait_counter.set(idx + 1);
143-
let (self_params, list_params, _impl_trait_params) = if let Some(def) = ctx.resolver.generic_def() {
144-
let generics = generics(ctx.db, def);
145-
generics.provenance_split()
146-
} else {
147-
(0, 0, 0)
148-
};
143+
let (self_params, list_params, _impl_trait_params) =
144+
if let Some(def) = ctx.resolver.generic_def() {
145+
let generics = generics(ctx.db, def);
146+
generics.provenance_split()
147+
} else {
148+
(0, 0, 0)
149+
};
149150
// assert!((idx as usize) < impl_trait_params); // TODO return position impl trait
150151
Ty::Bound(idx as u32 + self_params as u32 + list_params as u32)
151152
}
@@ -251,7 +252,7 @@ impl Ty {
251252
// FIXME: maybe return name in resolution?
252253
let name = generics.param_name(param_id);
253254
Ty::Param { idx, name }
254-
},
255+
}
255256
TypeParamLoweringMode::Variable => Ty::Bound(idx),
256257
}
257258
}
@@ -262,15 +263,15 @@ impl Ty {
262263
TypeParamLoweringMode::Variable => Substs::bound_vars(&generics),
263264
};
264265
ctx.db.impl_self_ty(impl_id).subst(&substs)
265-
},
266+
}
266267
TypeNs::AdtSelfType(adt) => {
267268
let generics = generics(ctx.db, adt.into());
268269
let substs = match ctx.type_param_mode {
269270
TypeParamLoweringMode::Placeholder => Substs::identity(&generics),
270271
TypeParamLoweringMode::Variable => Substs::bound_vars(&generics),
271272
};
272273
ctx.db.ty(adt.into()).subst(&substs)
273-
},
274+
}
274275

275276
TypeNs::AdtId(it) => Ty::from_hir_path_inner(ctx, resolved_segment, it.into()),
276277
TypeNs::BuiltinType(it) => Ty::from_hir_path_inner(ctx, resolved_segment, it.into()),
@@ -309,7 +310,8 @@ impl Ty {
309310
segment: PathSegment<'_>,
310311
) -> Ty {
311312
let param_idx = match self_ty {
312-
Ty::Param { idx, .. } => idx,
313+
Ty::Param { idx, .. } if ctx.type_param_mode == TypeParamLoweringMode::Placeholder => idx,
314+
Ty::Bound(idx) if ctx.type_param_mode == TypeParamLoweringMode::Variable => idx,
313315
_ => return Ty::Unknown, // Error: Ambiguous associated type
314316
};
315317
let def = match ctx.resolver.generic_def() {
@@ -318,7 +320,14 @@ impl Ty {
318320
};
319321
let predicates = ctx.db.generic_predicates_for_param(def.into(), param_idx);
320322
let traits_from_env = predicates.iter().filter_map(|pred| match pred {
321-
GenericPredicate::Implemented(tr) if tr.self_ty() == &self_ty => Some(tr.trait_),
323+
GenericPredicate::Implemented(tr) => {
324+
if let Ty::Param { idx, .. } = tr.self_ty() {
325+
if *idx == param_idx {
326+
return Some(tr.trait_);
327+
}
328+
}
329+
None
330+
}
322331
_ => None,
323332
});
324333
let traits = traits_from_env.flat_map(|t| all_super_traits(ctx.db, t));
@@ -516,10 +525,10 @@ impl GenericPredicate {
516525
TypeParamLoweringMode::Placeholder => {
517526
let name = generics.param_name(param_id);
518527
Ty::Param { idx, name }
519-
},
528+
}
520529
TypeParamLoweringMode::Variable => Ty::Bound(idx),
521530
}
522-
},
531+
}
523532
};
524533
GenericPredicate::from_type_bound(ctx, &where_predicate.bound, self_ty)
525534
}
@@ -615,7 +624,9 @@ pub(crate) fn generic_predicates_for_param_query(
615624
.where_predicates_in_scope()
616625
// we have to filter out all other predicates *first*, before attempting to lower them
617626
.filter(|pred| match &pred.target {
618-
WherePredicateTarget::TypeRef(type_ref) => Ty::from_hir_only_param(&ctx, type_ref) == Some(param_idx),
627+
WherePredicateTarget::TypeRef(type_ref) => {
628+
Ty::from_hir_only_param(&ctx, type_ref) == Some(param_idx)
629+
}
619630
WherePredicateTarget::TypeParam(local_id) => {
620631
let param_id = hir_def::TypeParamId { parent: def, local_id: *local_id };
621632
let idx = generics.param_idx(param_id);
@@ -701,8 +712,8 @@ fn type_for_const(db: &impl HirDatabase, def: ConstId) -> Binders<Ty> {
701712
let data = db.const_data(def);
702713
let generics = generics(db, def.into());
703714
let resolver = def.resolver(db);
704-
let ctx = TyLoweringContext::new(db, &resolver)
705-
.with_type_param_mode(TypeParamLoweringMode::Variable);
715+
let ctx =
716+
TyLoweringContext::new(db, &resolver).with_type_param_mode(TypeParamLoweringMode::Variable);
706717

707718
Binders::new(generics.len(), Ty::from_hir(&ctx, &data.type_ref))
708719
}
@@ -731,8 +742,8 @@ fn fn_sig_for_struct_constructor(db: &impl HirDatabase, def: StructId) -> PolyFn
731742
let struct_data = db.struct_data(def.into());
732743
let fields = struct_data.variant_data.fields();
733744
let resolver = def.resolver(db);
734-
let ctx = TyLoweringContext::new(db, &resolver)
735-
.with_type_param_mode(TypeParamLoweringMode::Variable);
745+
let ctx =
746+
TyLoweringContext::new(db, &resolver).with_type_param_mode(TypeParamLoweringMode::Variable);
736747
let params =
737748
fields.iter().map(|(_, field)| Ty::from_hir(&ctx, &field.type_ref)).collect::<Vec<_>>();
738749
let ret = type_for_adt(db, def.into());
@@ -755,8 +766,8 @@ fn fn_sig_for_enum_variant_constructor(db: &impl HirDatabase, def: EnumVariantId
755766
let var_data = &enum_data.variants[def.local_id];
756767
let fields = var_data.variant_data.fields();
757768
let resolver = def.parent.resolver(db);
758-
let ctx = TyLoweringContext::new(db, &resolver)
759-
.with_type_param_mode(TypeParamLoweringMode::Variable);
769+
let ctx =
770+
TyLoweringContext::new(db, &resolver).with_type_param_mode(TypeParamLoweringMode::Variable);
760771
let params =
761772
fields.iter().map(|(_, field)| Ty::from_hir(&ctx, &field.type_ref)).collect::<Vec<_>>();
762773
let ret = type_for_adt(db, def.parent.into());
@@ -784,8 +795,8 @@ fn type_for_adt(db: &impl HirDatabase, adt: AdtId) -> Binders<Ty> {
784795
fn type_for_type_alias(db: &impl HirDatabase, t: TypeAliasId) -> Binders<Ty> {
785796
let generics = generics(db, t.into());
786797
let resolver = t.resolver(db);
787-
let ctx = TyLoweringContext::new(db, &resolver)
788-
.with_type_param_mode(TypeParamLoweringMode::Variable);
798+
let ctx =
799+
TyLoweringContext::new(db, &resolver).with_type_param_mode(TypeParamLoweringMode::Variable);
789800
let type_ref = &db.type_alias_data(t).type_ref;
790801
let substs = Substs::bound_vars(&generics);
791802
let inner = Ty::from_hir(&ctx, type_ref.as_ref().unwrap_or(&TypeRef::Error));
@@ -870,8 +881,8 @@ pub(crate) fn impl_self_ty_query(db: &impl HirDatabase, impl_id: ImplId) -> Bind
870881
let impl_data = db.impl_data(impl_id);
871882
let resolver = impl_id.resolver(db);
872883
let generics = generics(db, impl_id.into());
873-
let ctx = TyLoweringContext::new(db, &resolver)
874-
.with_type_param_mode(TypeParamLoweringMode::Variable);
884+
let ctx =
885+
TyLoweringContext::new(db, &resolver).with_type_param_mode(TypeParamLoweringMode::Variable);
875886
Binders::new(generics.len(), Ty::from_hir(&ctx, &impl_data.target_type))
876887
}
877888

crates/ra_hir_ty/src/tests/traits.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -358,15 +358,15 @@ fn test() {
358358
[221; 223) '{}': ()
359359
[234; 300) '{ ...(S); }': ()
360360
[244; 245) 'x': u32
361-
[248; 252) 'foo1': fn foo1<S>(T) -> <T as Iterable>::Item
361+
[248; 252) 'foo1': fn foo1<S>(S) -> <S as Iterable>::Item
362362
[248; 255) 'foo1(S)': u32
363363
[253; 254) 'S': S
364364
[265; 266) 'y': u32
365-
[269; 273) 'foo2': fn foo2<S>(T) -> <T as Iterable>::Item
365+
[269; 273) 'foo2': fn foo2<S>(S) -> <S as Iterable>::Item
366366
[269; 276) 'foo2(S)': u32
367367
[274; 275) 'S': S
368368
[286; 287) 'z': u32
369-
[290; 294) 'foo3': fn foo3<S>(T) -> <T as Iterable>::Item
369+
[290; 294) 'foo3': fn foo3<S>(S) -> <S as Iterable>::Item
370370
[290; 297) 'foo3(S)': u32
371371
[295; 296) 'S': S
372372
"###

0 commit comments

Comments
 (0)