2021-04-04 05:55:47 -05:00
|
|
|
//! `TyBuilder`, a helper for building instances of `Ty` and related types.
|
|
|
|
|
|
|
|
use std::iter;
|
|
|
|
|
|
|
|
use chalk_ir::{
|
|
|
|
cast::{Cast, CastTo, Caster},
|
2022-07-03 02:22:10 -05:00
|
|
|
fold::TypeFoldable,
|
2021-04-04 05:55:47 -05:00
|
|
|
interner::HasInterner,
|
2022-10-02 04:39:42 -05:00
|
|
|
AdtId, DebruijnIndex, Scalar,
|
2021-04-04 05:55:47 -05:00
|
|
|
};
|
2022-03-09 12:50:24 -06:00
|
|
|
use hir_def::{
|
2022-09-09 01:20:18 -05:00
|
|
|
builtin_type::BuiltinType, generics::TypeOrConstParamData, ConstParamId, DefWithBodyId,
|
|
|
|
GenericDefId, TraitId, TypeAliasId,
|
2022-03-09 12:50:24 -06:00
|
|
|
};
|
2021-04-04 05:55:47 -05:00
|
|
|
use smallvec::SmallVec;
|
|
|
|
|
|
|
|
use crate::{
|
2022-03-17 06:39:42 -05:00
|
|
|
consteval::unknown_const_as_generic, db::HirDatabase, infer::unify::InferenceTable, primitive,
|
2022-10-02 04:39:42 -05:00
|
|
|
to_assoc_type_id, to_chalk_trait_id, utils::generics, Binders, BoundVar, CallableSig,
|
2023-08-08 10:47:29 -05:00
|
|
|
GenericArg, GenericArgData, Interner, ProjectionTy, Substitution, TraitRef, Ty, TyDefId, TyExt,
|
|
|
|
TyKind,
|
2021-04-04 05:55:47 -05:00
|
|
|
};
|
|
|
|
|
2022-03-09 12:50:24 -06:00
|
|
|
#[derive(Debug, Clone, PartialEq, Eq)]
|
|
|
|
pub enum ParamKind {
|
|
|
|
Type,
|
|
|
|
Const(Ty),
|
|
|
|
}
|
|
|
|
|
2021-04-04 06:23:22 -05:00
|
|
|
/// This is a builder for `Ty` or anything that needs a `Substitution`.
|
2021-04-04 05:55:47 -05:00
|
|
|
pub struct TyBuilder<D> {
|
2021-04-04 06:23:22 -05:00
|
|
|
/// The `data` field is used to keep track of what we're building (e.g. an
|
|
|
|
/// ADT, a `TraitRef`, ...).
|
2021-04-04 05:55:47 -05:00
|
|
|
data: D,
|
|
|
|
vec: SmallVec<[GenericArg; 2]>,
|
2022-03-09 12:50:24 -06:00
|
|
|
param_kinds: SmallVec<[ParamKind; 2]>,
|
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
2022-10-02 07:13:21 -05:00
|
|
|
parent_subst: Substitution,
|
2022-03-09 12:50:24 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
impl<A> TyBuilder<A> {
|
|
|
|
fn with_data<B>(self, data: B) -> TyBuilder<B> {
|
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
2022-10-02 07:13:21 -05:00
|
|
|
TyBuilder {
|
|
|
|
data,
|
|
|
|
vec: self.vec,
|
|
|
|
param_kinds: self.param_kinds,
|
|
|
|
parent_subst: self.parent_subst,
|
|
|
|
}
|
2022-03-09 12:50:24 -06:00
|
|
|
}
|
2021-04-04 05:55:47 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
impl<D> TyBuilder<D> {
|
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
2022-10-02 07:13:21 -05:00
|
|
|
fn new(
|
|
|
|
data: D,
|
|
|
|
param_kinds: SmallVec<[ParamKind; 2]>,
|
|
|
|
parent_subst: Option<Substitution>,
|
|
|
|
) -> Self {
|
|
|
|
let parent_subst = parent_subst.unwrap_or_else(|| Substitution::empty(Interner));
|
|
|
|
Self { data, vec: SmallVec::with_capacity(param_kinds.len()), param_kinds, parent_subst }
|
|
|
|
}
|
|
|
|
|
|
|
|
fn new_empty(data: D) -> Self {
|
|
|
|
TyBuilder::new(data, SmallVec::new(), None)
|
2021-04-04 05:55:47 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
fn build_internal(self) -> (D, Substitution) {
|
2023-01-27 04:06:41 -06:00
|
|
|
assert_eq!(self.vec.len(), self.param_kinds.len(), "{:?}", &self.param_kinds);
|
2022-03-09 12:50:24 -06:00
|
|
|
for (a, e) in self.vec.iter().zip(self.param_kinds.iter()) {
|
|
|
|
self.assert_match_kind(a, e);
|
|
|
|
}
|
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
2022-10-02 07:13:21 -05:00
|
|
|
let subst = Substitution::from_iter(
|
|
|
|
Interner,
|
|
|
|
self.vec.into_iter().chain(self.parent_subst.iter(Interner).cloned()),
|
|
|
|
);
|
2021-04-04 05:55:47 -05:00
|
|
|
(self.data, subst)
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn push(mut self, arg: impl CastTo<GenericArg>) -> Self {
|
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
2022-10-02 07:13:21 -05:00
|
|
|
assert!(self.remaining() > 0);
|
2022-03-09 12:50:24 -06:00
|
|
|
let arg = arg.cast(Interner);
|
|
|
|
let expected_kind = &self.param_kinds[self.vec.len()];
|
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
2022-10-02 07:13:21 -05:00
|
|
|
|
2022-03-09 12:50:24 -06:00
|
|
|
let arg_kind = match arg.data(Interner) {
|
2023-08-08 10:47:29 -05:00
|
|
|
GenericArgData::Ty(_) => ParamKind::Type,
|
|
|
|
GenericArgData::Lifetime(_) => panic!("Got lifetime in TyBuilder::push"),
|
|
|
|
GenericArgData::Const(c) => {
|
2022-03-09 12:50:24 -06:00
|
|
|
let c = c.data(Interner);
|
|
|
|
ParamKind::Const(c.ty.clone())
|
|
|
|
}
|
|
|
|
};
|
|
|
|
assert_eq!(*expected_kind, arg_kind);
|
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
2022-10-02 07:13:21 -05:00
|
|
|
|
2022-03-09 12:50:24 -06:00
|
|
|
self.vec.push(arg);
|
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
2022-10-02 07:13:21 -05:00
|
|
|
|
2021-04-04 05:55:47 -05:00
|
|
|
self
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn remaining(&self) -> usize {
|
2022-03-09 12:50:24 -06:00
|
|
|
self.param_kinds.len() - self.vec.len()
|
2021-04-04 05:55:47 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
pub fn fill_with_bound_vars(self, debruijn: DebruijnIndex, starting_from: usize) -> Self {
|
2022-03-09 12:50:24 -06:00
|
|
|
// self.fill is inlined to make borrow checker happy
|
|
|
|
let mut this = self;
|
2022-10-02 04:39:42 -05:00
|
|
|
let other = &this.param_kinds[this.vec.len()..];
|
2022-03-09 12:50:24 -06:00
|
|
|
let filler = (starting_from..).zip(other).map(|(idx, kind)| match kind {
|
2022-10-02 04:39:42 -05:00
|
|
|
ParamKind::Type => BoundVar::new(debruijn, idx).to_ty(Interner).cast(Interner),
|
|
|
|
ParamKind::Const(ty) => {
|
|
|
|
BoundVar::new(debruijn, idx).to_const(Interner, ty.clone()).cast(Interner)
|
2022-03-09 12:50:24 -06:00
|
|
|
}
|
|
|
|
});
|
|
|
|
this.vec.extend(filler.take(this.remaining()).casted(Interner));
|
|
|
|
assert_eq!(this.remaining(), 0);
|
|
|
|
this
|
2021-04-04 05:55:47 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
pub fn fill_with_unknown(self) -> Self {
|
2022-03-09 12:50:24 -06:00
|
|
|
// self.fill is inlined to make borrow checker happy
|
|
|
|
let mut this = self;
|
2022-10-02 04:39:42 -05:00
|
|
|
let filler = this.param_kinds[this.vec.len()..].iter().map(|x| match x {
|
|
|
|
ParamKind::Type => TyKind::Error.intern(Interner).cast(Interner),
|
2022-03-09 12:50:24 -06:00
|
|
|
ParamKind::Const(ty) => unknown_const_as_generic(ty.clone()),
|
|
|
|
});
|
|
|
|
this.vec.extend(filler.casted(Interner));
|
|
|
|
assert_eq!(this.remaining(), 0);
|
|
|
|
this
|
2021-04-04 05:55:47 -05:00
|
|
|
}
|
|
|
|
|
2024-02-01 15:10:32 -06:00
|
|
|
#[tracing::instrument(skip_all)]
|
2022-07-20 08:02:08 -05:00
|
|
|
pub(crate) fn fill_with_inference_vars(self, table: &mut InferenceTable<'_>) -> Self {
|
2022-03-17 06:39:42 -05:00
|
|
|
self.fill(|x| match x {
|
2022-10-02 04:39:42 -05:00
|
|
|
ParamKind::Type => table.new_type_var().cast(Interner),
|
|
|
|
ParamKind::Const(ty) => table.new_const_var(ty.clone()).cast(Interner),
|
2022-03-17 06:39:42 -05:00
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2022-03-09 12:50:24 -06:00
|
|
|
pub fn fill(mut self, filler: impl FnMut(&ParamKind) -> GenericArg) -> Self {
|
2022-10-02 04:39:42 -05:00
|
|
|
self.vec.extend(self.param_kinds[self.vec.len()..].iter().map(filler));
|
2021-04-04 05:55:47 -05:00
|
|
|
assert_eq!(self.remaining(), 0);
|
|
|
|
self
|
|
|
|
}
|
|
|
|
|
2022-03-09 12:50:24 -06:00
|
|
|
fn assert_match_kind(&self, a: &chalk_ir::GenericArg<Interner>, e: &ParamKind) {
|
|
|
|
match (a.data(Interner), e) {
|
2023-08-08 10:47:29 -05:00
|
|
|
(GenericArgData::Ty(_), ParamKind::Type)
|
|
|
|
| (GenericArgData::Const(_), ParamKind::Const(_)) => (),
|
2022-12-23 12:42:58 -06:00
|
|
|
_ => panic!("Mismatched kinds: {a:?}, {:?}, {:?}", self.vec, self.param_kinds),
|
2022-03-09 12:50:24 -06:00
|
|
|
}
|
|
|
|
}
|
2021-04-04 05:55:47 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
impl TyBuilder<()> {
|
|
|
|
pub fn unit() -> Ty {
|
2021-12-19 10:58:39 -06:00
|
|
|
TyKind::Tuple(0, Substitution::empty(Interner)).intern(Interner)
|
2021-04-04 05:55:47 -05:00
|
|
|
}
|
|
|
|
|
2023-02-03 05:16:25 -06:00
|
|
|
// FIXME: rustc's ty is dependent on the adt type, maybe we need to do that as well
|
|
|
|
pub fn discr_ty() -> Ty {
|
|
|
|
TyKind::Scalar(chalk_ir::Scalar::Int(chalk_ir::IntTy::I128)).intern(Interner)
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn bool() -> Ty {
|
|
|
|
TyKind::Scalar(chalk_ir::Scalar::Bool).intern(Interner)
|
|
|
|
}
|
|
|
|
|
2022-04-06 20:00:33 -05:00
|
|
|
pub fn usize() -> Ty {
|
|
|
|
TyKind::Scalar(chalk_ir::Scalar::Uint(chalk_ir::UintTy::Usize)).intern(Interner)
|
|
|
|
}
|
|
|
|
|
2021-04-04 05:55:47 -05:00
|
|
|
pub fn fn_ptr(sig: CallableSig) -> Ty {
|
2021-12-19 10:58:39 -06:00
|
|
|
TyKind::Function(sig.to_fn_ptr()).intern(Interner)
|
2021-04-04 05:55:47 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
pub fn builtin(builtin: BuiltinType) -> Ty {
|
|
|
|
match builtin {
|
2021-12-19 10:58:39 -06:00
|
|
|
BuiltinType::Char => TyKind::Scalar(Scalar::Char).intern(Interner),
|
|
|
|
BuiltinType::Bool => TyKind::Scalar(Scalar::Bool).intern(Interner),
|
|
|
|
BuiltinType::Str => TyKind::Str.intern(Interner),
|
2021-04-04 05:55:47 -05:00
|
|
|
BuiltinType::Int(t) => {
|
2021-12-19 10:58:39 -06:00
|
|
|
TyKind::Scalar(Scalar::Int(primitive::int_ty_from_builtin(t))).intern(Interner)
|
2021-04-04 05:55:47 -05:00
|
|
|
}
|
|
|
|
BuiltinType::Uint(t) => {
|
2021-12-19 10:58:39 -06:00
|
|
|
TyKind::Scalar(Scalar::Uint(primitive::uint_ty_from_builtin(t))).intern(Interner)
|
2021-04-04 05:55:47 -05:00
|
|
|
}
|
|
|
|
BuiltinType::Float(t) => {
|
2021-12-19 10:58:39 -06:00
|
|
|
TyKind::Scalar(Scalar::Float(primitive::float_ty_from_builtin(t))).intern(Interner)
|
2021-04-04 05:55:47 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-09-29 07:04:32 -05:00
|
|
|
pub fn slice(argument: Ty) -> Ty {
|
2021-12-19 10:58:39 -06:00
|
|
|
TyKind::Slice(argument).intern(Interner)
|
2021-09-29 07:04:32 -05:00
|
|
|
}
|
|
|
|
|
2022-03-09 12:50:24 -06:00
|
|
|
pub fn placeholder_subst(db: &dyn HirDatabase, def: impl Into<GenericDefId>) -> Substitution {
|
2021-04-04 06:16:16 -05:00
|
|
|
let params = generics(db.upcast(), def.into());
|
2022-03-09 12:50:24 -06:00
|
|
|
params.placeholder_subst(db)
|
2021-04-04 06:16:16 -05:00
|
|
|
}
|
|
|
|
|
2023-05-28 06:30:34 -05:00
|
|
|
pub fn unknown_subst(db: &dyn HirDatabase, def: impl Into<GenericDefId>) -> Substitution {
|
|
|
|
let params = generics(db.upcast(), def.into());
|
|
|
|
Substitution::from_iter(
|
|
|
|
Interner,
|
|
|
|
params.iter_id().map(|id| match id {
|
|
|
|
either::Either::Left(_) => TyKind::Error.intern(Interner).cast(Interner),
|
|
|
|
either::Either::Right(id) => {
|
|
|
|
unknown_const_as_generic(db.const_param_ty(id)).cast(Interner)
|
|
|
|
}
|
|
|
|
}),
|
|
|
|
)
|
|
|
|
}
|
|
|
|
|
2024-02-01 15:10:32 -06:00
|
|
|
#[tracing::instrument(skip_all)]
|
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
2022-10-02 07:13:21 -05:00
|
|
|
pub fn subst_for_def(
|
|
|
|
db: &dyn HirDatabase,
|
|
|
|
def: impl Into<GenericDefId>,
|
|
|
|
parent_subst: Option<Substitution>,
|
|
|
|
) -> TyBuilder<()> {
|
|
|
|
let generics = generics(db.upcast(), def.into());
|
2022-10-03 10:07:34 -05:00
|
|
|
assert!(generics.parent_generics().is_some() == parent_subst.is_some());
|
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
2022-10-02 07:13:21 -05:00
|
|
|
let params = generics
|
|
|
|
.iter_self()
|
|
|
|
.map(|(id, data)| match data {
|
|
|
|
TypeOrConstParamData::TypeParamData(_) => ParamKind::Type,
|
|
|
|
TypeOrConstParamData::ConstParamData(_) => {
|
|
|
|
ParamKind::Const(db.const_param_ty(ConstParamId::from_unchecked(id)))
|
|
|
|
}
|
|
|
|
})
|
|
|
|
.collect();
|
|
|
|
TyBuilder::new((), params, parent_subst)
|
2021-04-04 05:55:47 -05:00
|
|
|
}
|
|
|
|
|
2023-12-25 16:12:45 -06:00
|
|
|
/// Creates a `TyBuilder` to build `Substitution` for a coroutine defined in `parent`.
|
2022-09-09 01:20:18 -05:00
|
|
|
///
|
2023-12-25 16:12:45 -06:00
|
|
|
/// A coroutine's substitution consists of:
|
|
|
|
/// - resume type of coroutine
|
|
|
|
/// - yield type of coroutine ([`Coroutine::Yield`](std::ops::Coroutine::Yield))
|
|
|
|
/// - return type of coroutine ([`Coroutine::Return`](std::ops::Coroutine::Return))
|
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
2022-10-02 07:13:21 -05:00
|
|
|
/// - generic parameters in scope on `parent`
|
2022-09-09 01:20:18 -05:00
|
|
|
/// in this order.
|
|
|
|
///
|
|
|
|
/// This method prepopulates the builder with placeholder substitution of `parent`, so you
|
|
|
|
/// should only push exactly 3 `GenericArg`s before building.
|
2023-12-25 16:12:45 -06:00
|
|
|
pub fn subst_for_coroutine(db: &dyn HirDatabase, parent: DefWithBodyId) -> TyBuilder<()> {
|
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
2022-10-02 07:13:21 -05:00
|
|
|
let parent_subst =
|
|
|
|
parent.as_generic_def_id().map(|p| generics(db.upcast(), p).placeholder_subst(db));
|
2023-12-25 16:12:45 -06:00
|
|
|
// These represent resume type, yield type, and return type of coroutine.
|
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
2022-10-02 07:13:21 -05:00
|
|
|
let params = std::iter::repeat(ParamKind::Type).take(3).collect();
|
|
|
|
TyBuilder::new((), params, parent_subst)
|
2022-09-09 01:20:18 -05:00
|
|
|
}
|
|
|
|
|
2023-04-28 12:14:30 -05:00
|
|
|
pub fn subst_for_closure(
|
|
|
|
db: &dyn HirDatabase,
|
|
|
|
parent: DefWithBodyId,
|
|
|
|
sig_ty: Ty,
|
|
|
|
) -> Substitution {
|
|
|
|
let sig_ty = sig_ty.cast(Interner);
|
|
|
|
let self_subst = iter::once(&sig_ty);
|
|
|
|
let Some(parent) = parent.as_generic_def_id() else {
|
|
|
|
return Substitution::from_iter(Interner, self_subst);
|
|
|
|
};
|
|
|
|
Substitution::from_iter(
|
|
|
|
Interner,
|
|
|
|
self_subst
|
|
|
|
.chain(generics(db.upcast(), parent).placeholder_subst(db).iter(Interner))
|
|
|
|
.cloned()
|
|
|
|
.collect::<Vec<_>>(),
|
|
|
|
)
|
|
|
|
}
|
|
|
|
|
2021-04-04 05:55:47 -05:00
|
|
|
pub fn build(self) -> Substitution {
|
|
|
|
let ((), subst) = self.build_internal();
|
|
|
|
subst
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl TyBuilder<hir_def::AdtId> {
|
2022-03-09 12:50:24 -06:00
|
|
|
pub fn adt(db: &dyn HirDatabase, def: hir_def::AdtId) -> TyBuilder<hir_def::AdtId> {
|
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
2022-10-02 07:13:21 -05:00
|
|
|
TyBuilder::subst_for_def(db, def, None).with_data(def)
|
2021-04-04 05:55:47 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
pub fn fill_with_defaults(
|
|
|
|
mut self,
|
|
|
|
db: &dyn HirDatabase,
|
|
|
|
mut fallback: impl FnMut() -> Ty,
|
|
|
|
) -> Self {
|
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
2022-10-02 07:13:21 -05:00
|
|
|
// Note that we're building ADT, so we never have parent generic parameters.
|
2021-04-04 05:55:47 -05:00
|
|
|
let defaults = db.generic_defaults(self.data.into());
|
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
2022-10-02 07:13:21 -05:00
|
|
|
let dummy_ty = TyKind::Error.intern(Interner).cast(Interner);
|
2021-04-04 05:55:47 -05:00
|
|
|
for default_ty in defaults.iter().skip(self.vec.len()) {
|
2022-10-02 04:39:42 -05:00
|
|
|
// NOTE(skip_binders): we only check if the arg type is error type.
|
|
|
|
if let Some(x) = default_ty.skip_binders().ty(Interner) {
|
2022-03-09 12:50:24 -06:00
|
|
|
if x.is_unknown() {
|
|
|
|
self.vec.push(fallback().cast(Interner));
|
|
|
|
continue;
|
|
|
|
}
|
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
2022-10-02 07:13:21 -05:00
|
|
|
}
|
|
|
|
// Each default can only depend on the previous parameters.
|
|
|
|
// FIXME: we don't handle const generics here.
|
|
|
|
let subst_so_far = Substitution::from_iter(
|
|
|
|
Interner,
|
|
|
|
self.vec
|
|
|
|
.iter()
|
|
|
|
.cloned()
|
|
|
|
.chain(iter::repeat(dummy_ty.clone()))
|
|
|
|
.take(self.param_kinds.len()),
|
|
|
|
);
|
2022-03-09 12:50:24 -06:00
|
|
|
self.vec.push(default_ty.clone().substitute(Interner, &subst_so_far).cast(Interner));
|
2021-04-04 05:55:47 -05:00
|
|
|
}
|
|
|
|
self
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn build(self) -> Ty {
|
|
|
|
let (adt, subst) = self.build_internal();
|
2021-12-19 10:58:39 -06:00
|
|
|
TyKind::Adt(AdtId(adt), subst).intern(Interner)
|
2021-04-04 05:55:47 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub struct Tuple(usize);
|
|
|
|
impl TyBuilder<Tuple> {
|
|
|
|
pub fn tuple(size: usize) -> TyBuilder<Tuple> {
|
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
2022-10-02 07:13:21 -05:00
|
|
|
TyBuilder::new(Tuple(size), iter::repeat(ParamKind::Type).take(size).collect(), None)
|
2021-04-04 05:55:47 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
pub fn build(self) -> Ty {
|
|
|
|
let (Tuple(size), subst) = self.build_internal();
|
2021-12-19 10:58:39 -06:00
|
|
|
TyKind::Tuple(size, subst).intern(Interner)
|
2021-04-04 05:55:47 -05:00
|
|
|
}
|
2023-01-27 04:06:41 -06:00
|
|
|
|
|
|
|
pub fn tuple_with<I>(elements: I) -> Ty
|
|
|
|
where
|
|
|
|
I: IntoIterator<Item = Ty>,
|
|
|
|
<I as IntoIterator>::IntoIter: ExactSizeIterator,
|
|
|
|
{
|
|
|
|
let elements = elements.into_iter();
|
|
|
|
let len = elements.len();
|
|
|
|
let mut b =
|
|
|
|
TyBuilder::new(Tuple(len), iter::repeat(ParamKind::Type).take(len).collect(), None);
|
|
|
|
for e in elements {
|
|
|
|
b = b.push(e);
|
|
|
|
}
|
|
|
|
b.build()
|
|
|
|
}
|
2021-04-04 05:55:47 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
impl TyBuilder<TraitId> {
|
2022-03-09 12:50:24 -06:00
|
|
|
pub fn trait_ref(db: &dyn HirDatabase, def: TraitId) -> TyBuilder<TraitId> {
|
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
2022-10-02 07:13:21 -05:00
|
|
|
TyBuilder::subst_for_def(db, def, None).with_data(def)
|
2021-04-04 05:55:47 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
pub fn build(self) -> TraitRef {
|
|
|
|
let (trait_id, substitution) = self.build_internal();
|
|
|
|
TraitRef { trait_id: to_chalk_trait_id(trait_id), substitution }
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl TyBuilder<TypeAliasId> {
|
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
2022-10-02 07:13:21 -05:00
|
|
|
pub fn assoc_type_projection(
|
|
|
|
db: &dyn HirDatabase,
|
|
|
|
def: TypeAliasId,
|
|
|
|
parent_subst: Option<Substitution>,
|
|
|
|
) -> TyBuilder<TypeAliasId> {
|
|
|
|
TyBuilder::subst_for_def(db, def, parent_subst).with_data(def)
|
2021-04-04 05:55:47 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
pub fn build(self) -> ProjectionTy {
|
|
|
|
let (type_alias, substitution) = self.build_internal();
|
|
|
|
ProjectionTy { associated_ty_id: to_assoc_type_id(type_alias), substitution }
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-07-03 02:22:10 -05:00
|
|
|
impl<T: HasInterner<Interner = Interner> + TypeFoldable<Interner>> TyBuilder<Binders<T>> {
|
|
|
|
pub fn build(self) -> T {
|
2021-04-04 05:55:47 -05:00
|
|
|
let (b, subst) = self.build_internal();
|
2021-12-19 10:58:39 -06:00
|
|
|
b.substitute(Interner, &subst)
|
2021-04-04 05:55:47 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl TyBuilder<Binders<Ty>> {
|
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
2022-10-02 07:13:21 -05:00
|
|
|
pub fn def_ty(
|
|
|
|
db: &dyn HirDatabase,
|
|
|
|
def: TyDefId,
|
|
|
|
parent_subst: Option<Substitution>,
|
|
|
|
) -> TyBuilder<Binders<Ty>> {
|
|
|
|
let poly_ty = db.ty(def);
|
|
|
|
let id: GenericDefId = match def {
|
|
|
|
TyDefId::BuiltinType(_) => {
|
|
|
|
assert!(parent_subst.is_none());
|
|
|
|
return TyBuilder::new_empty(poly_ty);
|
|
|
|
}
|
|
|
|
TyDefId::AdtId(id) => id.into(),
|
|
|
|
TyDefId::TypeAliasId(id) => id.into(),
|
|
|
|
};
|
|
|
|
TyBuilder::subst_for_def(db, id, parent_subst).with_data(poly_ty)
|
2021-04-04 05:55:47 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
pub fn impl_self_ty(db: &dyn HirDatabase, def: hir_def::ImplId) -> TyBuilder<Binders<Ty>> {
|
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
2022-10-02 07:13:21 -05:00
|
|
|
TyBuilder::subst_for_def(db, def, None).with_data(db.impl_self_ty(def))
|
2021-04-04 05:55:47 -05:00
|
|
|
}
|
|
|
|
}
|