1 //! `TyBuilder`, a helper for building instances of `Ty` and related types.
6 cast::{Cast, CastTo, Caster},
9 AdtId, BoundVar, DebruijnIndex, Scalar,
12 builtin_type::BuiltinType, generics::TypeOrConstParamData, ConstParamId, GenericDefId, TraitId,
15 use smallvec::SmallVec;
18 consteval::unknown_const_as_generic, db::HirDatabase, infer::unify::InferenceTable, primitive,
19 to_assoc_type_id, to_chalk_trait_id, utils::generics, Binders, CallableSig, ConstData,
20 ConstValue, GenericArg, GenericArgData, Interner, ProjectionTy, Substitution, TraitRef, Ty,
21 TyDefId, TyExt, TyKind, ValueTyDefId,
24 #[derive(Debug, Clone, PartialEq, Eq)]
30 /// This is a builder for `Ty` or anything that needs a `Substitution`.
31 pub struct TyBuilder<D> {
32 /// The `data` field is used to keep track of what we're building (e.g. an
33 /// ADT, a `TraitRef`, ...).
35 vec: SmallVec<[GenericArg; 2]>,
36 param_kinds: SmallVec<[ParamKind; 2]>,
39 impl<A> TyBuilder<A> {
40 fn with_data<B>(self, data: B) -> TyBuilder<B> {
41 TyBuilder { data, param_kinds: self.param_kinds, vec: self.vec }
45 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 }
50 fn build_internal(self) -> (D, Substitution) {
51 assert_eq!(self.vec.len(), self.param_kinds.len());
52 for (a, e) in self.vec.iter().zip(self.param_kinds.iter()) {
53 self.assert_match_kind(a, e);
55 let subst = Substitution::from_iter(Interner, self.vec);
59 pub fn push(mut self, arg: impl CastTo<GenericArg>) -> Self {
60 let arg = arg.cast(Interner);
61 let expected_kind = &self.param_kinds[self.vec.len()];
62 let arg_kind = match arg.data(Interner) {
63 chalk_ir::GenericArgData::Ty(_) => ParamKind::Type,
64 chalk_ir::GenericArgData::Lifetime(_) => panic!("Got lifetime in TyBuilder::push"),
65 chalk_ir::GenericArgData::Const(c) => {
66 let c = c.data(Interner);
67 ParamKind::Const(c.ty.clone())
70 assert_eq!(*expected_kind, arg_kind);
75 pub fn remaining(&self) -> usize {
76 self.param_kinds.len() - self.vec.len()
79 pub fn fill_with_bound_vars(self, debruijn: DebruijnIndex, starting_from: usize) -> Self {
80 // self.fill is inlined to make borrow checker happy
82 let other = this.param_kinds.iter().skip(this.vec.len());
83 let filler = (starting_from..).zip(other).map(|(idx, kind)| match kind {
85 GenericArgData::Ty(TyKind::BoundVar(BoundVar::new(debruijn, idx)).intern(Interner))
88 ParamKind::Const(ty) => GenericArgData::Const(
90 value: ConstValue::BoundVar(BoundVar::new(debruijn, idx)),
97 this.vec.extend(filler.take(this.remaining()).casted(Interner));
98 assert_eq!(this.remaining(), 0);
102 pub fn fill_with_unknown(self) -> Self {
103 // self.fill is inlined to make borrow checker happy
105 let filler = this.param_kinds.iter().skip(this.vec.len()).map(|x| match x {
106 ParamKind::Type => GenericArgData::Ty(TyKind::Error.intern(Interner)).intern(Interner),
107 ParamKind::Const(ty) => unknown_const_as_generic(ty.clone()),
109 this.vec.extend(filler.casted(Interner));
110 assert_eq!(this.remaining(), 0);
114 pub(crate) fn fill_with_inference_vars(self, table: &mut InferenceTable<'_>) -> Self {
115 self.fill(|x| match x {
116 ParamKind::Type => GenericArgData::Ty(table.new_type_var()).intern(Interner),
117 ParamKind::Const(ty) => {
118 GenericArgData::Const(table.new_const_var(ty.clone())).intern(Interner)
123 pub fn fill(mut self, filler: impl FnMut(&ParamKind) -> GenericArg) -> Self {
124 self.vec.extend(self.param_kinds.iter().skip(self.vec.len()).map(filler));
125 assert_eq!(self.remaining(), 0);
129 pub fn use_parent_substs(mut self, parent_substs: &Substitution) -> Self {
130 assert!(self.vec.is_empty());
131 assert!(parent_substs.len(Interner) <= self.param_kinds.len());
132 self.extend(parent_substs.iter(Interner).cloned());
136 fn extend(&mut self, it: impl Iterator<Item = GenericArg> + Clone) {
137 for x in it.clone().zip(self.param_kinds.iter().skip(self.vec.len())) {
138 self.assert_match_kind(&x.0, &x.1);
143 fn assert_match_kind(&self, a: &chalk_ir::GenericArg<Interner>, e: &ParamKind) {
144 match (a.data(Interner), e) {
145 (chalk_ir::GenericArgData::Ty(_), ParamKind::Type)
146 | (chalk_ir::GenericArgData::Const(_), ParamKind::Const(_)) => (),
147 _ => panic!("Mismatched kinds: {:?}, {:?}, {:?}", a, self.vec, self.param_kinds),
153 pub fn unit() -> Ty {
154 TyKind::Tuple(0, Substitution::empty(Interner)).intern(Interner)
157 pub fn usize() -> Ty {
158 TyKind::Scalar(chalk_ir::Scalar::Uint(chalk_ir::UintTy::Usize)).intern(Interner)
161 pub fn fn_ptr(sig: CallableSig) -> Ty {
162 TyKind::Function(sig.to_fn_ptr()).intern(Interner)
165 pub fn builtin(builtin: BuiltinType) -> Ty {
167 BuiltinType::Char => TyKind::Scalar(Scalar::Char).intern(Interner),
168 BuiltinType::Bool => TyKind::Scalar(Scalar::Bool).intern(Interner),
169 BuiltinType::Str => TyKind::Str.intern(Interner),
170 BuiltinType::Int(t) => {
171 TyKind::Scalar(Scalar::Int(primitive::int_ty_from_builtin(t))).intern(Interner)
173 BuiltinType::Uint(t) => {
174 TyKind::Scalar(Scalar::Uint(primitive::uint_ty_from_builtin(t))).intern(Interner)
176 BuiltinType::Float(t) => {
177 TyKind::Scalar(Scalar::Float(primitive::float_ty_from_builtin(t))).intern(Interner)
182 pub fn slice(argument: Ty) -> Ty {
183 TyKind::Slice(argument).intern(Interner)
186 pub fn placeholder_subst(db: &dyn HirDatabase, def: impl Into<GenericDefId>) -> Substitution {
187 let params = generics(db.upcast(), def.into());
188 params.placeholder_subst(db)
191 pub fn subst_for_def(db: &dyn HirDatabase, def: impl Into<GenericDefId>) -> TyBuilder<()> {
192 let def = def.into();
193 let params = generics(db.upcast(), def);
198 .map(|(id, data)| match data {
199 TypeOrConstParamData::TypeParamData(_) => ParamKind::Type,
200 TypeOrConstParamData::ConstParamData(_) => {
201 ParamKind::Const(db.const_param_ty(ConstParamId::from_unchecked(id)))
208 pub fn build(self) -> Substitution {
209 let ((), subst) = self.build_internal();
214 impl TyBuilder<hir_def::AdtId> {
215 pub fn adt(db: &dyn HirDatabase, def: hir_def::AdtId) -> TyBuilder<hir_def::AdtId> {
216 TyBuilder::subst_for_def(db, def).with_data(def)
219 pub fn fill_with_defaults(
221 db: &dyn HirDatabase,
222 mut fallback: impl FnMut() -> Ty,
224 let defaults = db.generic_defaults(self.data.into());
225 for default_ty in defaults.iter().skip(self.vec.len()) {
226 if let GenericArgData::Ty(x) = default_ty.skip_binders().data(Interner) {
228 self.vec.push(fallback().cast(Interner));
232 // each default can depend on the previous parameters
233 let subst_so_far = Substitution::from_iter(Interner, self.vec.clone());
234 self.vec.push(default_ty.clone().substitute(Interner, &subst_so_far).cast(Interner));
239 pub fn build(self) -> Ty {
240 let (adt, subst) = self.build_internal();
241 TyKind::Adt(AdtId(adt), subst).intern(Interner)
245 pub struct Tuple(usize);
246 impl TyBuilder<Tuple> {
247 pub fn tuple(size: usize) -> TyBuilder<Tuple> {
248 TyBuilder::new(Tuple(size), iter::repeat(ParamKind::Type).take(size).collect())
251 pub fn build(self) -> Ty {
252 let (Tuple(size), subst) = self.build_internal();
253 TyKind::Tuple(size, subst).intern(Interner)
257 impl TyBuilder<TraitId> {
258 pub fn trait_ref(db: &dyn HirDatabase, def: TraitId) -> TyBuilder<TraitId> {
259 TyBuilder::subst_for_def(db, def).with_data(def)
262 pub fn build(self) -> TraitRef {
263 let (trait_id, substitution) = self.build_internal();
264 TraitRef { trait_id: to_chalk_trait_id(trait_id), substitution }
268 impl TyBuilder<TypeAliasId> {
269 pub fn assoc_type_projection(db: &dyn HirDatabase, def: TypeAliasId) -> TyBuilder<TypeAliasId> {
270 TyBuilder::subst_for_def(db, def).with_data(def)
273 pub fn build(self) -> ProjectionTy {
274 let (type_alias, substitution) = self.build_internal();
275 ProjectionTy { associated_ty_id: to_assoc_type_id(type_alias), substitution }
279 impl<T: HasInterner<Interner = Interner> + TypeFoldable<Interner>> TyBuilder<Binders<T>> {
280 fn subst_binders(b: Binders<T>) -> Self {
285 chalk_ir::VariableKind::Ty(_) => ParamKind::Type,
286 chalk_ir::VariableKind::Lifetime => panic!("Got lifetime parameter"),
287 chalk_ir::VariableKind::Const(ty) => ParamKind::Const(ty.clone()),
290 TyBuilder::new(b, param_kinds)
293 pub fn build(self) -> T {
294 let (b, subst) = self.build_internal();
295 b.substitute(Interner, &subst)
299 impl TyBuilder<Binders<Ty>> {
300 pub fn def_ty(db: &dyn HirDatabase, def: TyDefId) -> TyBuilder<Binders<Ty>> {
301 TyBuilder::subst_binders(db.ty(def))
304 pub fn impl_self_ty(db: &dyn HirDatabase, def: hir_def::ImplId) -> TyBuilder<Binders<Ty>> {
305 TyBuilder::subst_binders(db.impl_self_ty(def))
308 pub fn value_ty(db: &dyn HirDatabase, def: ValueTyDefId) -> TyBuilder<Binders<Ty>> {
309 TyBuilder::subst_binders(db.value_ty(def))