Skip to content

Commit e1962d2

Browse files
Fix a bug with predicate lowering of associated items
The essence of the bug is that bounds on `impl Trait` got lowered with incorrect bound vars, as if we were lowering the parent.
1 parent ea27351 commit e1962d2

File tree

2 files changed

+32
-5
lines changed

2 files changed

+32
-5
lines changed

crates/hir-ty/src/lower.rs

+13-5
Original file line numberDiff line numberDiff line change
@@ -464,10 +464,14 @@ impl<'a> TyLoweringContext<'a> {
464464
self.lower_trait_ref_from_path(trait_ref.path, explicit_self_ty).map(|it| it.0)
465465
}
466466

467+
/// When lowering predicates from parents (impl, traits) for children defs (fns, consts, types), `generics` should
468+
/// contain the `Generics` for the **child**, while `predicate_owner` should contain the `GenericDefId` of the
469+
/// **parent**. This is important so we generate the correct bound var/placeholder.
467470
pub(crate) fn lower_where_predicate<'b>(
468471
&'b mut self,
469472
where_predicate: &'b WherePredicate,
470473
generics: &'b Generics,
474+
predicate_owner: GenericDefId,
471475
ignore_bindings: bool,
472476
) -> impl Iterator<Item = QuantifiedWhereClause> + use<'a, 'b> {
473477
match where_predicate {
@@ -477,7 +481,7 @@ impl<'a> TyLoweringContext<'a> {
477481
WherePredicateTypeTarget::TypeRef(type_ref) => self.lower_ty(*type_ref),
478482
&WherePredicateTypeTarget::TypeOrConstParam(local_id) => {
479483
let param_id =
480-
hir_def::TypeOrConstParamId { parent: generics.def(), local_id };
484+
hir_def::TypeOrConstParamId { parent: predicate_owner, local_id };
481485
match self.type_param_mode {
482486
ParamLoweringMode::Placeholder => {
483487
TyKind::Placeholder(to_placeholder_idx(self.db, param_id))
@@ -887,7 +891,7 @@ pub(crate) fn generic_predicates_for_param_query(
887891
if invalid_target {
888892
// If this is filtered out without lowering, `?Sized` is not gathered into `ctx.unsized_types`
889893
if let TypeBound::Path(_, TraitBoundModifier::Maybe) = bound {
890-
ctx.lower_where_predicate(pred, generics, true).for_each(drop);
894+
ctx.lower_where_predicate(pred, generics, generics.def(), true).for_each(drop);
891895
}
892896
return false;
893897
}
@@ -924,7 +928,7 @@ pub(crate) fn generic_predicates_for_param_query(
924928
for pred in maybe_parent_generics.where_predicates() {
925929
if predicate(pred, maybe_parent_generics, &mut ctx) {
926930
predicates.extend(
927-
ctx.lower_where_predicate(pred, maybe_parent_generics, true)
931+
ctx.lower_where_predicate(pred, &generics, maybe_parent_generics.def(), true)
928932
.map(|p| make_binders(db, &generics, p)),
929933
);
930934
}
@@ -987,7 +991,9 @@ pub(crate) fn trait_environment_query(
987991
{
988992
ctx.store = maybe_parent_generics.store();
989993
for pred in maybe_parent_generics.where_predicates() {
990-
for pred in ctx.lower_where_predicate(pred, maybe_parent_generics, false) {
994+
for pred in
995+
ctx.lower_where_predicate(pred, &generics, maybe_parent_generics.def(), false)
996+
{
991997
if let WhereClause::Implemented(tr) = pred.skip_binders() {
992998
traits_in_scope
993999
.push((tr.self_type_parameter(Interner).clone(), tr.hir_trait_id()));
@@ -1085,8 +1091,10 @@ where
10851091
ctx.store = maybe_parent_generics.store();
10861092
for pred in maybe_parent_generics.where_predicates() {
10871093
if filter(pred, maybe_parent_generics.def()) {
1094+
// We deliberately use `generics` and not `maybe_parent_generics` here. This is not a mistake!
1095+
// If we use the parent generics
10881096
predicates.extend(
1089-
ctx.lower_where_predicate(pred, maybe_parent_generics, false)
1097+
ctx.lower_where_predicate(pred, &generics, maybe_parent_generics.def(), false)
10901098
.map(|p| make_binders(db, &generics, p)),
10911099
);
10921100
}

crates/ide/src/inlay_hints.rs

+19
Original file line numberDiff line numberDiff line change
@@ -1032,4 +1032,23 @@ fn bar() {
10321032
"#,
10331033
);
10341034
}
1035+
1036+
#[test]
1037+
fn regression_19610() {
1038+
check(
1039+
r#"
1040+
trait Trait {
1041+
type Assoc;
1042+
}
1043+
struct Foo<A>(A);
1044+
impl<A: Trait<Assoc = impl Trait>> Foo<A> {
1045+
fn foo<'a, 'b>(_: &'a [i32], _: &'b [i32]) {}
1046+
}
1047+
1048+
fn bar() {
1049+
Foo::foo(&[1], &[2]);
1050+
}
1051+
"#,
1052+
);
1053+
}
10351054
}

0 commit comments

Comments
 (0)