Skip to content

Commit fdc5413

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 0e480cc commit fdc5413

File tree

3 files changed

+69
-58
lines changed

3 files changed

+69
-58
lines changed

crates/hir-ty/src/chalk_db.rs

Lines changed: 46 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ use crate::{
5050
to_assoc_type_id, to_chalk_trait_id,
5151
traits::ChalkContext,
5252
utils::ClosureSubst,
53-
wrap_empty_binders,
53+
variable_kinds_from_generics, wrap_empty_binders,
5454
};
5555

5656
pub(crate) type AssociatedTyDatum = chalk_solve::rust_ir::AssociatedTyDatum<Interner>;
@@ -1059,9 +1059,14 @@ fn impl_method_rpitit_values(
10591059
DebruijnIndex::INNERMOST,
10601060
);
10611061
let trait_assoc = trait_assoc_id.loc(db);
1062+
// Completely unlike the docs, Chalk requires both the impl generics and the associated type
1063+
// generics in the binder.
10621064
let impl_rpitit_binders = VariableKinds::from_iter(
10631065
Interner,
1064-
&trait_assoc.bounds.binders.as_slice(Interner)[..trait_method_generics.len()],
1066+
trait_assoc.bounds.binders.as_slice(Interner)[..trait_method_generics.len()]
1067+
.iter()
1068+
.cloned()
1069+
.chain(variable_kinds_from_generics(db, impl_method_generics.iter_parent_id())),
10651070
);
10661071
let impl_rpitit = Binders::new(
10671072
impl_rpitit_binders,
@@ -1288,44 +1293,48 @@ pub(crate) fn associated_ty_value_query(
12881293
AnyImplAssocType::Normal(type_alias) => {
12891294
type_alias_associated_ty_value(db, krate, type_alias)
12901295
}
1291-
AnyImplAssocType::Rpitit(assoc_type_id) => {
1292-
let assoc_type = assoc_type_id.loc(db);
1293-
let trait_assoc = assoc_type.trait_assoc.loc(db);
1294-
let all_method_assocs = impl_method_rpitit_values(
1295-
db,
1296-
assoc_type.impl_id,
1297-
trait_assoc.synthesized_from_method,
1298-
);
1299-
let trait_assoc_id = to_assoc_type_id_rpitit(assoc_type.trait_assoc);
1300-
all_method_assocs
1301-
.iter()
1302-
.find(|method_assoc| method_assoc.associated_ty_id == trait_assoc_id)
1303-
.cloned()
1304-
.unwrap_or_else(|| {
1305-
let impl_id = hir_def::ImplId::to_chalk(assoc_type.impl_id, db);
1306-
let trait_method_generics =
1307-
generics(db, trait_assoc.synthesized_from_method.into());
1308-
Arc::new(AssociatedTyValue {
1309-
associated_ty_id: trait_assoc_id,
1310-
impl_id,
1311-
// In this situation, we don't know even that the trait and impl generics match, therefore
1312-
// the only binders we can give to comply with the trait's binders are the trait's binders.
1313-
// However, for impl associated types chalk wants only their own generics, excluding
1314-
// those of the impl (unlike in traits), therefore we filter them here.
1315-
value: Binders::new(
1316-
VariableKinds::from_iter(
1317-
Interner,
1318-
&trait_assoc.bounds.binders.as_slice(Interner)
1319-
[..trait_method_generics.len_self()],
1320-
),
1321-
rust_ir::AssociatedTyValueBound { ty: TyKind::Error.intern(Interner) },
1322-
),
1323-
})
1324-
})
1325-
}
1296+
AnyImplAssocType::Rpitit(assoc_type_id) => rpitit_associated_ty_value(db, assoc_type_id),
13261297
}
13271298
}
13281299

1300+
fn rpitit_associated_ty_value(
1301+
db: &dyn HirDatabase,
1302+
assoc_type_id: RpititImplAssocTyId,
1303+
) -> Arc<AssociatedTyValue> {
1304+
let assoc_type = assoc_type_id.loc(db);
1305+
let trait_assoc = assoc_type.trait_assoc.loc(db);
1306+
let all_method_assocs =
1307+
impl_method_rpitit_values(db, assoc_type.impl_id, trait_assoc.synthesized_from_method);
1308+
let trait_assoc_id = to_assoc_type_id_rpitit(assoc_type.trait_assoc);
1309+
all_method_assocs
1310+
.iter()
1311+
.find(|method_assoc| method_assoc.associated_ty_id == trait_assoc_id)
1312+
.cloned()
1313+
.unwrap_or_else(|| {
1314+
let impl_id = hir_def::ImplId::to_chalk(assoc_type.impl_id, db);
1315+
let trait_method_generics = generics(db, trait_assoc.synthesized_from_method.into());
1316+
let impl_generics = generics(db, assoc_type.impl_id.into());
1317+
// In this situation, we don't know even that the trait and impl generics match, therefore
1318+
// the only binders we can give to comply with the trait's binders are the trait's binders.
1319+
// However, for impl associated types chalk wants only their own generics, excluding
1320+
// those of the impl (unlike in traits), therefore we filter them here.
1321+
// Completely unlike the docs, Chalk requires both the impl generics and the associated type
1322+
// generics in the binder.
1323+
let value = Binders::new(
1324+
VariableKinds::from_iter(
1325+
Interner,
1326+
trait_assoc.bounds.binders.as_slice(Interner)
1327+
[..trait_method_generics.len_self()]
1328+
.iter()
1329+
.cloned()
1330+
.chain(variable_kinds_from_generics(db, impl_generics.iter_id())),
1331+
),
1332+
rust_ir::AssociatedTyValueBound { ty: TyKind::Error.intern(Interner) },
1333+
);
1334+
Arc::new(AssociatedTyValue { associated_ty_id: trait_assoc_id, impl_id, value })
1335+
})
1336+
}
1337+
13291338
fn type_alias_associated_ty_value(
13301339
db: &dyn HirDatabase,
13311340
_krate: Crate,

crates/hir-ty/src/lib.rs

Lines changed: 18 additions & 19 deletions
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,29 +346,25 @@ 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> {
351-
Binders::new(variable_kinds_from_iter(db, generics.iter_id()), value)
352-
}
353-
354-
pub(crate) fn variable_kinds_from_iter(
355-
db: &dyn HirDatabase,
356-
iter: impl Iterator<Item = hir_def::GenericParamId>,
357-
) -> VariableKinds {
358-
VariableKinds::from_iter(
359-
Interner,
360-
iter.map(|x| match x {
361-
hir_def::GenericParamId::ConstParamId(id) => {
362-
chalk_ir::VariableKind::Const(db.const_param_ty(id))
363-
}
364-
hir_def::GenericParamId::TypeParamId(_) => {
365-
chalk_ir::VariableKind::Ty(chalk_ir::TyVariableKind::General)
366-
}
367-
hir_def::GenericParamId::LifetimeParamId(_) => chalk_ir::VariableKind::Lifetime,
368-
}),
365+
Binders::new(
366+
VariableKinds::from_iter(Interner, variable_kinds_from_generics(db, generics.iter_id())),
367+
value,
369368
)
370369
}
371370

crates/hir-ty/src/lower.rs

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ use crate::{
6666
mapping::{ToChalk, from_chalk_trait_id, lt_to_placeholder_idx, to_assoc_type_id_rpitit},
6767
static_lifetime, to_chalk_trait_id, to_placeholder_idx,
6868
utils::all_super_trait_refs,
69-
variable_kinds_from_iter,
69+
variable_kinds_from_generics,
7070
};
7171

7272
#[derive(Debug, Default)]
@@ -1448,7 +1448,10 @@ pub(crate) fn generic_defaults_with_diagnostics_query(
14481448
p: GenericParamDataRef<'_>,
14491449
generic_params: &Generics,
14501450
) -> (Binders<crate::GenericArg>, bool) {
1451-
let binders = variable_kinds_from_iter(ctx.db, generic_params.iter_id().take(idx));
1451+
let binders = VariableKinds::from_iter(
1452+
Interner,
1453+
variable_kinds_from_generics(ctx.db, generic_params.iter_id().take(idx)),
1454+
);
14521455
match p {
14531456
GenericParamDataRef::TypeParamData(p) => {
14541457
let ty = p.default.as_ref().map_or_else(

0 commit comments

Comments
 (0)