Skip to content

Commit ee2d5fa

Browse files
Comply with Chalk expectations
Chalk apparently requires associated type values to contain both the impl and the associated ty binders, completely unlike the docs (which say they should only contain those of the associated type). So fix that.
1 parent 629fbaf commit ee2d5fa

File tree

2 files changed

+63
-50
lines changed

2 files changed

+63
-50
lines changed

crates/hir-ty/src/chalk_db.rs

+47-37
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ use crate::{
4747
to_assoc_type_id, to_chalk_trait_id,
4848
traits::ChalkContext,
4949
utils::ClosureSubst,
50-
wrap_empty_binders,
50+
variable_kinds_from_generics, wrap_empty_binders,
5151
};
5252

5353
pub(crate) type AssociatedTyDatum = chalk_solve::rust_ir::AssociatedTyDatum<Interner>;
@@ -1031,9 +1031,14 @@ fn impl_method_rpitit_values(
10311031
DebruijnIndex::INNERMOST,
10321032
);
10331033
let trait_assoc = trait_assoc_id.loc(db);
1034+
// Completely unlike the docs, Chalk requires both the impl generics and the associated type
1035+
// generics in the binder.
10341036
let impl_rpitit_binders = VariableKinds::from_iter(
10351037
Interner,
1036-
&trait_assoc.bounds.binders.as_slice(Interner)[..trait_method_generics.len()],
1038+
trait_assoc.bounds.binders.as_slice(Interner)[..trait_method_generics.len()]
1039+
.iter()
1040+
.cloned()
1041+
.chain(variable_kinds_from_generics(db, impl_method_generics.iter_parent_id())),
10371042
);
10381043
let impl_rpitit = Binders::new(
10391044
impl_rpitit_binders,
@@ -1258,44 +1263,49 @@ pub(crate) fn associated_ty_value_query(
12581263
AnyImplAssocType::Normal(type_alias) => {
12591264
type_alias_associated_ty_value(db, krate, type_alias)
12601265
}
1261-
AnyImplAssocType::Rpitit(assoc_type_id) => {
1262-
let assoc_type = assoc_type_id.loc(db);
1263-
let trait_assoc = assoc_type.trait_assoc.loc(db);
1264-
let all_method_assocs = impl_method_rpitit_values(
1265-
db,
1266-
assoc_type.impl_id,
1267-
trait_assoc.synthesized_from_method,
1268-
);
1269-
let trait_assoc_id = to_assoc_type_id_rpitit(assoc_type.trait_assoc);
1270-
all_method_assocs
1271-
.iter()
1272-
.find(|method_assoc| method_assoc.associated_ty_id == trait_assoc_id)
1273-
.cloned()
1274-
.unwrap_or_else(|| {
1275-
let impl_id = hir_def::ImplId::to_chalk(assoc_type.impl_id, db);
1276-
let trait_method_generics =
1277-
generics(db.upcast(), trait_assoc.synthesized_from_method.into());
1278-
Arc::new(AssociatedTyValue {
1279-
associated_ty_id: trait_assoc_id,
1280-
impl_id,
1281-
// In this situation, we don't know even that the trait and impl generics match, therefore
1282-
// the only binders we can give to comply with the trait's binders are the trait's binders.
1283-
// However, for impl associated types chalk wants only their own generics, excluding
1284-
// those of the impl (unlike in traits), therefore we filter them here.
1285-
value: Binders::new(
1286-
VariableKinds::from_iter(
1287-
Interner,
1288-
&trait_assoc.bounds.binders.as_slice(Interner)
1289-
[..trait_method_generics.len_self()],
1290-
),
1291-
rust_ir::AssociatedTyValueBound { ty: TyKind::Error.intern(Interner) },
1292-
),
1293-
})
1294-
})
1295-
}
1266+
AnyImplAssocType::Rpitit(assoc_type_id) => rpitit_associated_ty_value(db, assoc_type_id),
12961267
}
12971268
}
12981269

1270+
fn rpitit_associated_ty_value(
1271+
db: &dyn HirDatabase,
1272+
assoc_type_id: RpititImplAssocTyId,
1273+
) -> Arc<AssociatedTyValue> {
1274+
let assoc_type = assoc_type_id.loc(db);
1275+
let trait_assoc = assoc_type.trait_assoc.loc(db);
1276+
let all_method_assocs =
1277+
impl_method_rpitit_values(db, assoc_type.impl_id, trait_assoc.synthesized_from_method);
1278+
let trait_assoc_id = to_assoc_type_id_rpitit(assoc_type.trait_assoc);
1279+
all_method_assocs
1280+
.iter()
1281+
.find(|method_assoc| method_assoc.associated_ty_id == trait_assoc_id)
1282+
.cloned()
1283+
.unwrap_or_else(|| {
1284+
let impl_id = hir_def::ImplId::to_chalk(assoc_type.impl_id, db);
1285+
let trait_method_generics =
1286+
generics(db.upcast(), trait_assoc.synthesized_from_method.into());
1287+
let impl_generics = generics(db.upcast(), assoc_type.impl_id.into());
1288+
// In this situation, we don't know even that the trait and impl generics match, therefore
1289+
// the only binders we can give to comply with the trait's binders are the trait's binders.
1290+
// However, for impl associated types chalk wants only their own generics, excluding
1291+
// those of the impl (unlike in traits), therefore we filter them here.
1292+
// Completely unlike the docs, Chalk requires both the impl generics and the associated type
1293+
// generics in the binder.
1294+
let value = Binders::new(
1295+
VariableKinds::from_iter(
1296+
Interner,
1297+
trait_assoc.bounds.binders.as_slice(Interner)
1298+
[..trait_method_generics.len_self()]
1299+
.iter()
1300+
.cloned()
1301+
.chain(variable_kinds_from_generics(db, impl_generics.iter_id())),
1302+
),
1303+
rust_ir::AssociatedTyValueBound { ty: TyKind::Error.intern(Interner) },
1304+
);
1305+
Arc::new(AssociatedTyValue { associated_ty_id: trait_assoc_id, impl_id, value })
1306+
})
1307+
}
1308+
12991309
fn type_alias_associated_ty_value(
13001310
db: &dyn HirDatabase,
13011311
_krate: Crate,

crates/hir-ty/src/lib.rs

+16-13
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,10 @@ use chalk_ir::{
6262
interner::HasInterner,
6363
};
6464
use either::Either;
65-
use hir_def::{CallableDefId, GeneralConstId, TypeOrConstParamId, hir::ExprId, type_ref::Rawness};
65+
use hir_def::{
66+
CallableDefId, GeneralConstId, GenericParamId, TypeOrConstParamId, hir::ExprId,
67+
type_ref::Rawness,
68+
};
6669
use hir_expand::name::Name;
6770
use indexmap::{IndexMap, map::Entry};
6871
use intern::{Symbol, sym};
@@ -343,24 +346,24 @@ pub(crate) fn make_single_type_binders<T: HasInterner<Interner = Interner>>(
343346
)
344347
}
345348

349+
pub(crate) fn variable_kinds_from_generics(
350+
db: &dyn HirDatabase,
351+
generics: impl Iterator<Item = GenericParamId>,
352+
) -> impl Iterator<Item = VariableKind> {
353+
generics.map(|x| match x {
354+
GenericParamId::ConstParamId(id) => VariableKind::Const(db.const_param_ty(id)),
355+
GenericParamId::TypeParamId(_) => VariableKind::Ty(chalk_ir::TyVariableKind::General),
356+
GenericParamId::LifetimeParamId(_) => VariableKind::Lifetime,
357+
})
358+
}
359+
346360
pub(crate) fn make_binders<T: HasInterner<Interner = Interner>>(
347361
db: &dyn HirDatabase,
348362
generics: &Generics,
349363
value: T,
350364
) -> Binders<T> {
351365
Binders::new(
352-
VariableKinds::from_iter(
353-
Interner,
354-
generics.iter_id().map(|x| match x {
355-
hir_def::GenericParamId::ConstParamId(id) => {
356-
chalk_ir::VariableKind::Const(db.const_param_ty(id))
357-
}
358-
hir_def::GenericParamId::TypeParamId(_) => {
359-
chalk_ir::VariableKind::Ty(chalk_ir::TyVariableKind::General)
360-
}
361-
hir_def::GenericParamId::LifetimeParamId(_) => chalk_ir::VariableKind::Lifetime,
362-
}),
363-
),
366+
VariableKinds::from_iter(Interner, variable_kinds_from_generics(db, generics.iter_id())),
364367
value,
365368
)
366369
}

0 commit comments

Comments
 (0)