mirror of
https://github.com/rust-lang/rust-analyzer.git
synced 2025-10-30 03:27:44 +00:00
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.
This commit is contained in:
parent
ea273513ed
commit
e1962d2e22
2 changed files with 32 additions and 5 deletions
|
|
@ -464,10 +464,14 @@ impl<'a> TyLoweringContext<'a> {
|
||||||
self.lower_trait_ref_from_path(trait_ref.path, explicit_self_ty).map(|it| it.0)
|
self.lower_trait_ref_from_path(trait_ref.path, explicit_self_ty).map(|it| it.0)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// When lowering predicates from parents (impl, traits) for children defs (fns, consts, types), `generics` should
|
||||||
|
/// contain the `Generics` for the **child**, while `predicate_owner` should contain the `GenericDefId` of the
|
||||||
|
/// **parent**. This is important so we generate the correct bound var/placeholder.
|
||||||
pub(crate) fn lower_where_predicate<'b>(
|
pub(crate) fn lower_where_predicate<'b>(
|
||||||
&'b mut self,
|
&'b mut self,
|
||||||
where_predicate: &'b WherePredicate,
|
where_predicate: &'b WherePredicate,
|
||||||
generics: &'b Generics,
|
generics: &'b Generics,
|
||||||
|
predicate_owner: GenericDefId,
|
||||||
ignore_bindings: bool,
|
ignore_bindings: bool,
|
||||||
) -> impl Iterator<Item = QuantifiedWhereClause> + use<'a, 'b> {
|
) -> impl Iterator<Item = QuantifiedWhereClause> + use<'a, 'b> {
|
||||||
match where_predicate {
|
match where_predicate {
|
||||||
|
|
@ -477,7 +481,7 @@ impl<'a> TyLoweringContext<'a> {
|
||||||
WherePredicateTypeTarget::TypeRef(type_ref) => self.lower_ty(*type_ref),
|
WherePredicateTypeTarget::TypeRef(type_ref) => self.lower_ty(*type_ref),
|
||||||
&WherePredicateTypeTarget::TypeOrConstParam(local_id) => {
|
&WherePredicateTypeTarget::TypeOrConstParam(local_id) => {
|
||||||
let param_id =
|
let param_id =
|
||||||
hir_def::TypeOrConstParamId { parent: generics.def(), local_id };
|
hir_def::TypeOrConstParamId { parent: predicate_owner, local_id };
|
||||||
match self.type_param_mode {
|
match self.type_param_mode {
|
||||||
ParamLoweringMode::Placeholder => {
|
ParamLoweringMode::Placeholder => {
|
||||||
TyKind::Placeholder(to_placeholder_idx(self.db, param_id))
|
TyKind::Placeholder(to_placeholder_idx(self.db, param_id))
|
||||||
|
|
@ -887,7 +891,7 @@ pub(crate) fn generic_predicates_for_param_query(
|
||||||
if invalid_target {
|
if invalid_target {
|
||||||
// If this is filtered out without lowering, `?Sized` is not gathered into `ctx.unsized_types`
|
// If this is filtered out without lowering, `?Sized` is not gathered into `ctx.unsized_types`
|
||||||
if let TypeBound::Path(_, TraitBoundModifier::Maybe) = bound {
|
if let TypeBound::Path(_, TraitBoundModifier::Maybe) = bound {
|
||||||
ctx.lower_where_predicate(pred, generics, true).for_each(drop);
|
ctx.lower_where_predicate(pred, generics, generics.def(), true).for_each(drop);
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
@ -924,7 +928,7 @@ pub(crate) fn generic_predicates_for_param_query(
|
||||||
for pred in maybe_parent_generics.where_predicates() {
|
for pred in maybe_parent_generics.where_predicates() {
|
||||||
if predicate(pred, maybe_parent_generics, &mut ctx) {
|
if predicate(pred, maybe_parent_generics, &mut ctx) {
|
||||||
predicates.extend(
|
predicates.extend(
|
||||||
ctx.lower_where_predicate(pred, maybe_parent_generics, true)
|
ctx.lower_where_predicate(pred, &generics, maybe_parent_generics.def(), true)
|
||||||
.map(|p| make_binders(db, &generics, p)),
|
.map(|p| make_binders(db, &generics, p)),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
@ -987,7 +991,9 @@ pub(crate) fn trait_environment_query(
|
||||||
{
|
{
|
||||||
ctx.store = maybe_parent_generics.store();
|
ctx.store = maybe_parent_generics.store();
|
||||||
for pred in maybe_parent_generics.where_predicates() {
|
for pred in maybe_parent_generics.where_predicates() {
|
||||||
for pred in ctx.lower_where_predicate(pred, maybe_parent_generics, false) {
|
for pred in
|
||||||
|
ctx.lower_where_predicate(pred, &generics, maybe_parent_generics.def(), false)
|
||||||
|
{
|
||||||
if let WhereClause::Implemented(tr) = pred.skip_binders() {
|
if let WhereClause::Implemented(tr) = pred.skip_binders() {
|
||||||
traits_in_scope
|
traits_in_scope
|
||||||
.push((tr.self_type_parameter(Interner).clone(), tr.hir_trait_id()));
|
.push((tr.self_type_parameter(Interner).clone(), tr.hir_trait_id()));
|
||||||
|
|
@ -1085,8 +1091,10 @@ where
|
||||||
ctx.store = maybe_parent_generics.store();
|
ctx.store = maybe_parent_generics.store();
|
||||||
for pred in maybe_parent_generics.where_predicates() {
|
for pred in maybe_parent_generics.where_predicates() {
|
||||||
if filter(pred, maybe_parent_generics.def()) {
|
if filter(pred, maybe_parent_generics.def()) {
|
||||||
|
// We deliberately use `generics` and not `maybe_parent_generics` here. This is not a mistake!
|
||||||
|
// If we use the parent generics
|
||||||
predicates.extend(
|
predicates.extend(
|
||||||
ctx.lower_where_predicate(pred, maybe_parent_generics, false)
|
ctx.lower_where_predicate(pred, &generics, maybe_parent_generics.def(), false)
|
||||||
.map(|p| make_binders(db, &generics, p)),
|
.map(|p| make_binders(db, &generics, p)),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1032,4 +1032,23 @@ fn bar() {
|
||||||
"#,
|
"#,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn regression_19610() {
|
||||||
|
check(
|
||||||
|
r#"
|
||||||
|
trait Trait {
|
||||||
|
type Assoc;
|
||||||
|
}
|
||||||
|
struct Foo<A>(A);
|
||||||
|
impl<A: Trait<Assoc = impl Trait>> Foo<A> {
|
||||||
|
fn foo<'a, 'b>(_: &'a [i32], _: &'b [i32]) {}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn bar() {
|
||||||
|
Foo::foo(&[1], &[2]);
|
||||||
|
}
|
||||||
|
"#,
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue