Skip to content

Commit 4385d3d

Browse files
committed
Change generic parameter/argument order
This commit "inverts" the order of generic parameters/arguments of an item and its parent. This is to fulfill chalk's expectation on the order of `Substitution` for generic associated types and it's one step forward for their support (hopefully). Although chalk doesn't put any constraint on the order of `Substitution` for other items, it feels natural to get everything aligned rather than special casing GATs. One complication is that `TyBuilder` now demands its users to pass in parent's `Substitution` upon construction unless it's obvious that the the item has no parent (e.g. an ADT never has parent). All users *should* already know the parent of the item in question, and without this, it cannot be easily reasoned about whether we're pushing the argument for the item or for its parent. Quick comparison of how this commit changes `Substitution`: ```rust trait Trait<TP, const CP: usize> { type Type<TC, const CC: usize> = (); fn f<TC, const CC: usize>() {} } ``` - before this commit: `[Self, TP, CP, TC, CC]` for each trait item - after this commit: `[TC, CC, Self, TP, CP]` for each trait item
1 parent f8f5a5e commit 4385d3d

File tree

3 files changed

+141
-87
lines changed

3 files changed

+141
-87
lines changed

crates/hir-ty/src/builder.rs

Lines changed: 104 additions & 78 deletions
Original file line numberDiff line numberDiff line change
@@ -34,31 +34,51 @@ pub struct TyBuilder<D> {
3434
data: D,
3535
vec: SmallVec<[GenericArg; 2]>,
3636
param_kinds: SmallVec<[ParamKind; 2]>,
37+
parent_subst: Substitution,
3738
}
3839

3940
impl<A> TyBuilder<A> {
4041
fn with_data<B>(self, data: B) -> TyBuilder<B> {
41-
TyBuilder { data, param_kinds: self.param_kinds, vec: self.vec }
42+
TyBuilder {
43+
data,
44+
vec: self.vec,
45+
param_kinds: self.param_kinds,
46+
parent_subst: self.parent_subst,
47+
}
4248
}
4349
}
4450

4551
impl<D> TyBuilder<D> {
46-
fn new(data: D, param_kinds: SmallVec<[ParamKind; 2]>) -> TyBuilder<D> {
47-
TyBuilder { data, vec: SmallVec::with_capacity(param_kinds.len()), param_kinds }
52+
fn new(
53+
data: D,
54+
param_kinds: SmallVec<[ParamKind; 2]>,
55+
parent_subst: Option<Substitution>,
56+
) -> Self {
57+
let parent_subst = parent_subst.unwrap_or_else(|| Substitution::empty(Interner));
58+
Self { data, vec: SmallVec::with_capacity(param_kinds.len()), param_kinds, parent_subst }
59+
}
60+
61+
fn new_empty(data: D) -> Self {
62+
TyBuilder::new(data, SmallVec::new(), None)
4863
}
4964

5065
fn build_internal(self) -> (D, Substitution) {
5166
assert_eq!(self.vec.len(), self.param_kinds.len());
5267
for (a, e) in self.vec.iter().zip(self.param_kinds.iter()) {
5368
self.assert_match_kind(a, e);
5469
}
55-
let subst = Substitution::from_iter(Interner, self.vec);
70+
let subst = Substitution::from_iter(
71+
Interner,
72+
self.vec.into_iter().chain(self.parent_subst.iter(Interner).cloned()),
73+
);
5674
(self.data, subst)
5775
}
5876

5977
pub fn push(mut self, arg: impl CastTo<GenericArg>) -> Self {
78+
assert!(self.remaining() > 0);
6079
let arg = arg.cast(Interner);
6180
let expected_kind = &self.param_kinds[self.vec.len()];
81+
6282
let arg_kind = match arg.data(Interner) {
6383
chalk_ir::GenericArgData::Ty(_) => ParamKind::Type,
6484
chalk_ir::GenericArgData::Lifetime(_) => panic!("Got lifetime in TyBuilder::push"),
@@ -68,7 +88,9 @@ impl<D> TyBuilder<D> {
6888
}
6989
};
7090
assert_eq!(*expected_kind, arg_kind);
91+
7192
self.vec.push(arg);
93+
7294
self
7395
}
7496

@@ -116,20 +138,6 @@ impl<D> TyBuilder<D> {
116138
self
117139
}
118140

119-
pub fn use_parent_substs(mut self, parent_substs: &Substitution) -> Self {
120-
assert!(self.vec.is_empty());
121-
assert!(parent_substs.len(Interner) <= self.param_kinds.len());
122-
self.extend(parent_substs.iter(Interner).cloned());
123-
self
124-
}
125-
126-
fn extend(&mut self, it: impl Iterator<Item = GenericArg> + Clone) {
127-
for x in it.clone().zip(self.param_kinds.iter().skip(self.vec.len())) {
128-
self.assert_match_kind(&x.0, &x.1);
129-
}
130-
self.vec.extend(it);
131-
}
132-
133141
fn assert_match_kind(&self, a: &chalk_ir::GenericArg<Interner>, e: &ParamKind) {
134142
match (a.data(Interner), e) {
135143
(chalk_ir::GenericArgData::Ty(_), ParamKind::Type)
@@ -178,53 +186,44 @@ impl TyBuilder<()> {
178186
params.placeholder_subst(db)
179187
}
180188

181-
pub fn subst_for_def(db: &dyn HirDatabase, def: impl Into<GenericDefId>) -> TyBuilder<()> {
182-
let def = def.into();
183-
let params = generics(db.upcast(), def);
184-
TyBuilder::new(
185-
(),
186-
params
187-
.iter()
188-
.map(|(id, data)| match data {
189-
TypeOrConstParamData::TypeParamData(_) => ParamKind::Type,
190-
TypeOrConstParamData::ConstParamData(_) => {
191-
ParamKind::Const(db.const_param_ty(ConstParamId::from_unchecked(id)))
192-
}
193-
})
194-
.collect(),
195-
)
189+
pub fn subst_for_def(
190+
db: &dyn HirDatabase,
191+
def: impl Into<GenericDefId>,
192+
parent_subst: Option<Substitution>,
193+
) -> TyBuilder<()> {
194+
let generics = generics(db.upcast(), def.into());
195+
// FIXME: this assertion should hold but some adjustment around
196+
// `ValueTyDefId::EnumVariantId` is needed.
197+
// assert!(generics.parent_generics().is_some() == parent_subst.is_some());
198+
let params = generics
199+
.iter_self()
200+
.map(|(id, data)| match data {
201+
TypeOrConstParamData::TypeParamData(_) => ParamKind::Type,
202+
TypeOrConstParamData::ConstParamData(_) => {
203+
ParamKind::Const(db.const_param_ty(ConstParamId::from_unchecked(id)))
204+
}
205+
})
206+
.collect();
207+
TyBuilder::new((), params, parent_subst)
196208
}
197209

198210
/// Creates a `TyBuilder` to build `Substitution` for a generator defined in `parent`.
199211
///
200212
/// A generator's substitution consists of:
201-
/// - generic parameters in scope on `parent`
202213
/// - resume type of generator
203214
/// - yield type of generator ([`Generator::Yield`](std::ops::Generator::Yield))
204215
/// - return type of generator ([`Generator::Return`](std::ops::Generator::Return))
216+
/// - generic parameters in scope on `parent`
205217
/// in this order.
206218
///
207219
/// This method prepopulates the builder with placeholder substitution of `parent`, so you
208220
/// should only push exactly 3 `GenericArg`s before building.
209221
pub fn subst_for_generator(db: &dyn HirDatabase, parent: DefWithBodyId) -> TyBuilder<()> {
210-
let parent_subst = match parent.as_generic_def_id() {
211-
Some(parent) => generics(db.upcast(), parent).placeholder_subst(db),
212-
// Static initializers *may* contain generators.
213-
None => Substitution::empty(Interner),
214-
};
215-
let builder = TyBuilder::new(
216-
(),
217-
parent_subst
218-
.iter(Interner)
219-
.map(|arg| match arg.constant(Interner) {
220-
Some(c) => ParamKind::Const(c.data(Interner).ty.clone()),
221-
None => ParamKind::Type,
222-
})
223-
// These represent resume type, yield type, and return type of generator.
224-
.chain(std::iter::repeat(ParamKind::Type).take(3))
225-
.collect(),
226-
);
227-
builder.use_parent_substs(&parent_subst)
222+
let parent_subst =
223+
parent.as_generic_def_id().map(|p| generics(db.upcast(), p).placeholder_subst(db));
224+
// These represent resume type, yield type, and return type of generator.
225+
let params = std::iter::repeat(ParamKind::Type).take(3).collect();
226+
TyBuilder::new((), params, parent_subst)
228227
}
229228

230229
pub fn build(self) -> Substitution {
@@ -235,25 +234,35 @@ impl TyBuilder<()> {
235234

236235
impl TyBuilder<hir_def::AdtId> {
237236
pub fn adt(db: &dyn HirDatabase, def: hir_def::AdtId) -> TyBuilder<hir_def::AdtId> {
238-
TyBuilder::subst_for_def(db, def).with_data(def)
237+
TyBuilder::subst_for_def(db, def, None).with_data(def)
239238
}
240239

241240
pub fn fill_with_defaults(
242241
mut self,
243242
db: &dyn HirDatabase,
244243
mut fallback: impl FnMut() -> Ty,
245244
) -> Self {
245+
// Note that we're building ADT, so we never have parent generic parameters.
246246
let defaults = db.generic_defaults(self.data.into());
247+
let dummy_ty = TyKind::Error.intern(Interner).cast(Interner);
247248
for default_ty in defaults.iter().skip(self.vec.len()) {
248249
// NOTE(skip_binders): we only check if the arg type is error type.
249250
if let Some(x) = default_ty.skip_binders().ty(Interner) {
250251
if x.is_unknown() {
251252
self.vec.push(fallback().cast(Interner));
252253
continue;
253254
}
254-
};
255-
// each default can depend on the previous parameters
256-
let subst_so_far = Substitution::from_iter(Interner, self.vec.clone());
255+
}
256+
// Each default can only depend on the previous parameters.
257+
// FIXME: we don't handle const generics here.
258+
let subst_so_far = Substitution::from_iter(
259+
Interner,
260+
self.vec
261+
.iter()
262+
.cloned()
263+
.chain(iter::repeat(dummy_ty.clone()))
264+
.take(self.param_kinds.len()),
265+
);
257266
self.vec.push(default_ty.clone().substitute(Interner, &subst_so_far).cast(Interner));
258267
}
259268
self
@@ -268,7 +277,7 @@ impl TyBuilder<hir_def::AdtId> {
268277
pub struct Tuple(usize);
269278
impl TyBuilder<Tuple> {
270279
pub fn tuple(size: usize) -> TyBuilder<Tuple> {
271-
TyBuilder::new(Tuple(size), iter::repeat(ParamKind::Type).take(size).collect())
280+
TyBuilder::new(Tuple(size), iter::repeat(ParamKind::Type).take(size).collect(), None)
272281
}
273282

274283
pub fn build(self) -> Ty {
@@ -279,7 +288,7 @@ impl TyBuilder<Tuple> {
279288

280289
impl TyBuilder<TraitId> {
281290
pub fn trait_ref(db: &dyn HirDatabase, def: TraitId) -> TyBuilder<TraitId> {
282-
TyBuilder::subst_for_def(db, def).with_data(def)
291+
TyBuilder::subst_for_def(db, def, None).with_data(def)
283292
}
284293

285294
pub fn build(self) -> TraitRef {
@@ -289,8 +298,12 @@ impl TyBuilder<TraitId> {
289298
}
290299

291300
impl TyBuilder<TypeAliasId> {
292-
pub fn assoc_type_projection(db: &dyn HirDatabase, def: TypeAliasId) -> TyBuilder<TypeAliasId> {
293-
TyBuilder::subst_for_def(db, def).with_data(def)
301+
pub fn assoc_type_projection(
302+
db: &dyn HirDatabase,
303+
def: TypeAliasId,
304+
parent_subst: Option<Substitution>,
305+
) -> TyBuilder<TypeAliasId> {
306+
TyBuilder::subst_for_def(db, def, parent_subst).with_data(def)
294307
}
295308

296309
pub fn build(self) -> ProjectionTy {
@@ -300,35 +313,48 @@ impl TyBuilder<TypeAliasId> {
300313
}
301314

302315
impl<T: HasInterner<Interner = Interner> + TypeFoldable<Interner>> TyBuilder<Binders<T>> {
303-
fn subst_binders(b: Binders<T>) -> Self {
304-
let param_kinds = b
305-
.binders
306-
.iter(Interner)
307-
.map(|x| match x {
308-
chalk_ir::VariableKind::Ty(_) => ParamKind::Type,
309-
chalk_ir::VariableKind::Lifetime => panic!("Got lifetime parameter"),
310-
chalk_ir::VariableKind::Const(ty) => ParamKind::Const(ty.clone()),
311-
})
312-
.collect();
313-
TyBuilder::new(b, param_kinds)
314-
}
315-
316316
pub fn build(self) -> T {
317317
let (b, subst) = self.build_internal();
318318
b.substitute(Interner, &subst)
319319
}
320320
}
321321

322322
impl TyBuilder<Binders<Ty>> {
323-
pub fn def_ty(db: &dyn HirDatabase, def: TyDefId) -> TyBuilder<Binders<Ty>> {
324-
TyBuilder::subst_binders(db.ty(def))
323+
pub fn def_ty(
324+
db: &dyn HirDatabase,
325+
def: TyDefId,
326+
parent_subst: Option<Substitution>,
327+
) -> TyBuilder<Binders<Ty>> {
328+
let poly_ty = db.ty(def);
329+
let id: GenericDefId = match def {
330+
TyDefId::BuiltinType(_) => {
331+
assert!(parent_subst.is_none());
332+
return TyBuilder::new_empty(poly_ty);
333+
}
334+
TyDefId::AdtId(id) => id.into(),
335+
TyDefId::TypeAliasId(id) => id.into(),
336+
};
337+
TyBuilder::subst_for_def(db, id, parent_subst).with_data(poly_ty)
325338
}
326339

327340
pub fn impl_self_ty(db: &dyn HirDatabase, def: hir_def::ImplId) -> TyBuilder<Binders<Ty>> {
328-
TyBuilder::subst_binders(db.impl_self_ty(def))
341+
TyBuilder::subst_for_def(db, def, None).with_data(db.impl_self_ty(def))
329342
}
330343

331-
pub fn value_ty(db: &dyn HirDatabase, def: ValueTyDefId) -> TyBuilder<Binders<Ty>> {
332-
TyBuilder::subst_binders(db.value_ty(def))
344+
pub fn value_ty(
345+
db: &dyn HirDatabase,
346+
def: ValueTyDefId,
347+
parent_subst: Option<Substitution>,
348+
) -> TyBuilder<Binders<Ty>> {
349+
let poly_value_ty = db.value_ty(def);
350+
let id = match def.to_generic_def_id() {
351+
Some(id) => id,
352+
None => {
353+
// static items
354+
assert!(parent_subst.is_none());
355+
return TyBuilder::new_empty(poly_value_ty);
356+
}
357+
};
358+
TyBuilder::subst_for_def(db, id, parent_subst).with_data(poly_value_ty)
333359
}
334360
}

crates/hir-ty/src/lower.rs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1641,6 +1641,19 @@ pub enum ValueTyDefId {
16411641
}
16421642
impl_from!(FunctionId, StructId, UnionId, EnumVariantId, ConstId, StaticId for ValueTyDefId);
16431643

1644+
impl ValueTyDefId {
1645+
pub(crate) fn to_generic_def_id(self) -> Option<GenericDefId> {
1646+
match self {
1647+
Self::FunctionId(id) => Some(id.into()),
1648+
Self::StructId(id) => Some(id.into()),
1649+
Self::UnionId(id) => Some(id.into()),
1650+
Self::EnumVariantId(var) => Some(var.parent.into()),
1651+
Self::ConstId(id) => Some(id.into()),
1652+
Self::StaticId(_) => None,
1653+
}
1654+
}
1655+
}
1656+
16441657
/// Build the declared type of an item. This depends on the namespace; e.g. for
16451658
/// `struct Foo(usize)`, we have two types: The type of the struct itself, and
16461659
/// the constructor function `(usize) -> Foo` which lives in the values

crates/hir-ty/src/utils.rs

Lines changed: 24 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -220,36 +220,49 @@ impl Generics {
220220
})
221221
}
222222

223-
/// Iterator over types and const params of parent, then self.
223+
/// Iterator over types and const params of self, then parent.
224224
pub(crate) fn iter<'a>(
225225
&'a self,
226226
) -> impl DoubleEndedIterator<Item = (TypeOrConstParamId, &'a TypeOrConstParamData)> + 'a {
227227
let to_toc_id = |it: &'a Generics| {
228228
move |(local_id, p)| (TypeOrConstParamId { parent: it.def, local_id }, p)
229229
};
230-
self.parent_generics()
231-
.into_iter()
232-
.flat_map(move |it| it.params.iter().map(to_toc_id(it)))
233-
.chain(self.params.iter().map(to_toc_id(self)))
230+
self.params.iter().map(to_toc_id(self)).chain(self.iter_parent())
231+
}
232+
233+
/// Iterate over types and const params without parent params.
234+
pub(crate) fn iter_self<'a>(
235+
&'a self,
236+
) -> impl DoubleEndedIterator<Item = (TypeOrConstParamId, &'a TypeOrConstParamData)> + 'a {
237+
let to_toc_id = |it: &'a Generics| {
238+
move |(local_id, p)| (TypeOrConstParamId { parent: it.def, local_id }, p)
239+
};
240+
self.params.iter().map(to_toc_id(self))
234241
}
235242

236243
/// Iterator over types and const params of parent.
237244
pub(crate) fn iter_parent<'a>(
238245
&'a self,
239-
) -> impl Iterator<Item = (TypeOrConstParamId, &'a TypeOrConstParamData)> + 'a {
246+
) -> impl DoubleEndedIterator<Item = (TypeOrConstParamId, &'a TypeOrConstParamData)> + 'a {
240247
self.parent_generics().into_iter().flat_map(|it| {
241248
let to_toc_id =
242249
move |(local_id, p)| (TypeOrConstParamId { parent: it.def, local_id }, p);
243250
it.params.iter().map(to_toc_id)
244251
})
245252
}
246253

254+
/// Returns total number of generic parameters in scope, including those from parent.
247255
pub(crate) fn len(&self) -> usize {
248256
let parent = self.parent_generics().map_or(0, Generics::len);
249257
let child = self.params.type_or_consts.len();
250258
parent + child
251259
}
252260

261+
/// Returns numbers of generic parameters excluding those from parent.
262+
pub(crate) fn len_self(&self) -> usize {
263+
self.params.type_or_consts.len()
264+
}
265+
253266
/// (parent total, self param, type param list, const param list, impl trait)
254267
pub(crate) fn provenance_split(&self) -> (usize, usize, usize, usize, usize) {
255268
let ty_iter = || self.params.iter().filter_map(|x| x.1.type_param());
@@ -274,10 +287,12 @@ impl Generics {
274287
if param.parent == self.def {
275288
let (idx, (_local_id, data)) =
276289
self.params.iter().enumerate().find(|(_, (idx, _))| *idx == param.local_id)?;
277-
let parent_len = self.parent_generics().map_or(0, Generics::len);
278-
Some((parent_len + idx, data))
290+
Some((idx, data))
279291
} else {
280-
self.parent_generics().and_then(|g| g.find_param(param))
292+
self.parent_generics()
293+
.and_then(|g| g.find_param(param))
294+
// Remember that parent parameters come after parameters for self.
295+
.map(|(idx, data)| (self.len_self() + idx, data))
281296
}
282297
}
283298

0 commit comments

Comments
 (0)