1 //! `TyBuilder`, a helper for building instances of `Ty` and related types.
6 cast::{Cast, CastTo, Caster},
9 AdtId, BoundVar, DebruijnIndex, Scalar,
11 use hir_def::{builtin_type::BuiltinType, GenericDefId, TraitId, TypeAliasId};
12 use smallvec::SmallVec;
15 db::HirDatabase, primitive, to_assoc_type_id, to_chalk_trait_id, utils::generics, Binders,
16 CallableSig, GenericArg, Interner, ProjectionTy, Substitution, TraitRef, Ty, TyDefId, TyExt,
20 /// This is a builder for `Ty` or anything that needs a `Substitution`.
21 pub struct TyBuilder<D> {
22 /// The `data` field is used to keep track of what we're building (e.g. an
23 /// ADT, a `TraitRef`, ...).
25 vec: SmallVec<[GenericArg; 2]>,
29 impl<D> TyBuilder<D> {
30 fn new(data: D, param_count: usize) -> TyBuilder<D> {
31 TyBuilder { data, param_count, vec: SmallVec::with_capacity(param_count) }
34 fn build_internal(self) -> (D, Substitution) {
35 assert_eq!(self.vec.len(), self.param_count);
36 let subst = Substitution::from_iter(Interner, self.vec);
40 pub fn push(mut self, arg: impl CastTo<GenericArg>) -> Self {
41 self.vec.push(arg.cast(Interner));
45 pub fn remaining(&self) -> usize {
46 self.param_count - self.vec.len()
49 pub fn fill_with_bound_vars(self, debruijn: DebruijnIndex, starting_from: usize) -> Self {
52 .map(|idx| TyKind::BoundVar(BoundVar::new(debruijn, idx)).intern(Interner)),
56 pub fn fill_with_unknown(self) -> Self {
57 self.fill(iter::repeat(TyKind::Error.intern(Interner)))
60 pub fn fill(mut self, filler: impl Iterator<Item = impl CastTo<GenericArg>>) -> Self {
61 self.vec.extend(filler.take(self.remaining()).casted(Interner));
62 assert_eq!(self.remaining(), 0);
66 pub fn use_parent_substs(mut self, parent_substs: &Substitution) -> Self {
67 assert!(self.vec.is_empty());
68 assert!(parent_substs.len(Interner) <= self.param_count);
69 self.vec.extend(parent_substs.iter(Interner).cloned());
76 TyKind::Tuple(0, Substitution::empty(Interner)).intern(Interner)
79 pub fn fn_ptr(sig: CallableSig) -> Ty {
80 TyKind::Function(sig.to_fn_ptr()).intern(Interner)
83 pub fn builtin(builtin: BuiltinType) -> Ty {
85 BuiltinType::Char => TyKind::Scalar(Scalar::Char).intern(Interner),
86 BuiltinType::Bool => TyKind::Scalar(Scalar::Bool).intern(Interner),
87 BuiltinType::Str => TyKind::Str.intern(Interner),
88 BuiltinType::Int(t) => {
89 TyKind::Scalar(Scalar::Int(primitive::int_ty_from_builtin(t))).intern(Interner)
91 BuiltinType::Uint(t) => {
92 TyKind::Scalar(Scalar::Uint(primitive::uint_ty_from_builtin(t))).intern(Interner)
94 BuiltinType::Float(t) => {
95 TyKind::Scalar(Scalar::Float(primitive::float_ty_from_builtin(t))).intern(Interner)
100 pub fn slice(argument: Ty) -> Ty {
101 TyKind::Slice(argument).intern(Interner)
104 pub fn type_params_subst(db: &dyn HirDatabase, def: impl Into<GenericDefId>) -> Substitution {
105 let params = generics(db.upcast(), def.into());
106 params.type_params_subst(db)
109 pub fn subst_for_def(db: &dyn HirDatabase, def: impl Into<GenericDefId>) -> TyBuilder<()> {
110 let def = def.into();
111 let params = generics(db.upcast(), def);
112 let param_count = params.len();
113 TyBuilder::new((), param_count)
116 pub fn build(self) -> Substitution {
117 let ((), subst) = self.build_internal();
122 impl TyBuilder<hir_def::AdtId> {
123 pub fn adt(db: &dyn HirDatabase, adt: hir_def::AdtId) -> TyBuilder<hir_def::AdtId> {
124 let generics = generics(db.upcast(), adt.into());
125 let param_count = generics.len();
126 TyBuilder::new(adt, param_count)
129 pub fn fill_with_defaults(
131 db: &dyn HirDatabase,
132 mut fallback: impl FnMut() -> Ty,
134 let defaults = db.generic_defaults(self.data.into());
135 for default_ty in defaults.iter().skip(self.vec.len()) {
136 if default_ty.skip_binders().is_unknown() {
137 self.vec.push(fallback().cast(Interner));
139 // each default can depend on the previous parameters
140 let subst_so_far = Substitution::from_iter(Interner, self.vec.clone());
142 .push(default_ty.clone().substitute(Interner, &subst_so_far).cast(Interner));
148 pub fn build(self) -> Ty {
149 let (adt, subst) = self.build_internal();
150 TyKind::Adt(AdtId(adt), subst).intern(Interner)
154 pub struct Tuple(usize);
155 impl TyBuilder<Tuple> {
156 pub fn tuple(size: usize) -> TyBuilder<Tuple> {
157 TyBuilder::new(Tuple(size), size)
160 pub fn build(self) -> Ty {
161 let (Tuple(size), subst) = self.build_internal();
162 TyKind::Tuple(size, subst).intern(Interner)
166 impl TyBuilder<TraitId> {
167 pub fn trait_ref(db: &dyn HirDatabase, trait_id: TraitId) -> TyBuilder<TraitId> {
168 let generics = generics(db.upcast(), trait_id.into());
169 let param_count = generics.len();
170 TyBuilder::new(trait_id, param_count)
173 pub fn build(self) -> TraitRef {
174 let (trait_id, substitution) = self.build_internal();
175 TraitRef { trait_id: to_chalk_trait_id(trait_id), substitution }
179 impl TyBuilder<TypeAliasId> {
180 pub fn assoc_type_projection(
181 db: &dyn HirDatabase,
182 type_alias: TypeAliasId,
183 ) -> TyBuilder<TypeAliasId> {
184 let generics = generics(db.upcast(), type_alias.into());
185 let param_count = generics.len();
186 TyBuilder::new(type_alias, param_count)
189 pub fn build(self) -> ProjectionTy {
190 let (type_alias, substitution) = self.build_internal();
191 ProjectionTy { associated_ty_id: to_assoc_type_id(type_alias), substitution }
195 impl<T: HasInterner<Interner = Interner> + Fold<Interner>> TyBuilder<Binders<T>> {
196 fn subst_binders(b: Binders<T>) -> Self {
197 let param_count = b.binders.len(Interner);
198 TyBuilder::new(b, param_count)
201 pub fn build(self) -> <T as Fold<Interner>>::Result {
202 let (b, subst) = self.build_internal();
203 b.substitute(Interner, &subst)
207 impl TyBuilder<Binders<Ty>> {
208 pub fn def_ty(db: &dyn HirDatabase, def: TyDefId) -> TyBuilder<Binders<Ty>> {
209 TyBuilder::subst_binders(db.ty(def))
212 pub fn impl_self_ty(db: &dyn HirDatabase, def: hir_def::ImplId) -> TyBuilder<Binders<Ty>> {
213 TyBuilder::subst_binders(db.impl_self_ty(def))
216 pub fn value_ty(db: &dyn HirDatabase, def: ValueTyDefId) -> TyBuilder<Binders<Ty>> {
217 TyBuilder::subst_binders(db.value_ty(def))