Skip to content

Commit 620769f

Browse files
committed
Add TyBuilder::adt
1 parent e6f007d commit 620769f

File tree

4 files changed

+104
-45
lines changed

4 files changed

+104
-45
lines changed

crates/hir_ty/src/infer/expr.rs

Lines changed: 10 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -539,17 +539,10 @@ impl<'a> InferenceContext<'a> {
539539
Expr::Box { expr } => {
540540
let inner_ty = self.infer_expr_inner(*expr, &Expectation::none());
541541
if let Some(box_) = self.resolve_boxed_box() {
542-
let mut sb =
543-
Substitution::build_for_generics(&generics(self.db.upcast(), box_.into()));
544-
sb = sb.push(inner_ty);
545-
match self.db.generic_defaults(box_.into()).get(1) {
546-
Some(alloc_ty) if !alloc_ty.value.is_unknown() && sb.remaining() > 0 => {
547-
sb = sb.push(alloc_ty.value.clone());
548-
}
549-
_ => (),
550-
}
551-
sb = sb.fill(repeat_with(|| self.table.new_type_var()));
552-
Ty::adt_ty(box_, sb.build())
542+
TyBuilder::adt(self.db, box_)
543+
.push(inner_ty)
544+
.fill_with_defaults(self.db, || self.table.new_type_var())
545+
.build()
553546
} else {
554547
self.err_ty()
555548
}
@@ -639,31 +632,31 @@ impl<'a> InferenceContext<'a> {
639632
let rhs_ty = rhs.map(|e| self.infer_expr(e, &rhs_expect));
640633
match (range_type, lhs_ty, rhs_ty) {
641634
(RangeOp::Exclusive, None, None) => match self.resolve_range_full() {
642-
Some(adt) => Ty::adt_ty(adt, Substitution::empty(&Interner)),
635+
Some(adt) => TyBuilder::adt(self.db, adt).build(),
643636
None => self.err_ty(),
644637
},
645638
(RangeOp::Exclusive, None, Some(ty)) => match self.resolve_range_to() {
646-
Some(adt) => Ty::adt_ty(adt, Substitution::single(ty)),
639+
Some(adt) => TyBuilder::adt(self.db, adt).push(ty).build(),
647640
None => self.err_ty(),
648641
},
649642
(RangeOp::Inclusive, None, Some(ty)) => {
650643
match self.resolve_range_to_inclusive() {
651-
Some(adt) => Ty::adt_ty(adt, Substitution::single(ty)),
644+
Some(adt) => TyBuilder::adt(self.db, adt).push(ty).build(),
652645
None => self.err_ty(),
653646
}
654647
}
655648
(RangeOp::Exclusive, Some(_), Some(ty)) => match self.resolve_range() {
656-
Some(adt) => Ty::adt_ty(adt, Substitution::single(ty)),
649+
Some(adt) => TyBuilder::adt(self.db, adt).push(ty).build(),
657650
None => self.err_ty(),
658651
},
659652
(RangeOp::Inclusive, Some(_), Some(ty)) => {
660653
match self.resolve_range_inclusive() {
661-
Some(adt) => Ty::adt_ty(adt, Substitution::single(ty)),
654+
Some(adt) => TyBuilder::adt(self.db, adt).push(ty).build(),
662655
None => self.err_ty(),
663656
}
664657
}
665658
(RangeOp::Exclusive, Some(ty), None) => match self.resolve_range_from() {
666-
Some(adt) => Ty::adt_ty(adt, Substitution::single(ty)),
659+
Some(adt) => TyBuilder::adt(self.db, adt).push(ty).build(),
667660
None => self.err_ty(),
668661
},
669662
(RangeOp::Inclusive, _, None) => self.err_ty(),

crates/hir_ty/src/infer/pat.rs

Lines changed: 7 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,8 @@ use hir_expand::name::Name;
1313

1414
use super::{BindingMode, Expectation, InferenceContext};
1515
use crate::{
16-
lower::lower_to_chalk_mutability,
17-
utils::{generics, variant_data},
18-
Interner, Substitution, Ty, TyKind,
16+
lower::lower_to_chalk_mutability, utils::variant_data, Interner, Substitution, Ty, TyBuilder,
17+
TyKind,
1918
};
2019

2120
impl<'a> InferenceContext<'a> {
@@ -246,23 +245,12 @@ impl<'a> InferenceContext<'a> {
246245
};
247246

248247
let inner_ty = self.infer_pat(*inner, &inner_ty, default_bm);
249-
let mut sb = Substitution::build_for_generics(&generics(
250-
self.db.upcast(),
251-
box_adt.into(),
252-
));
253-
sb = sb.push(inner_ty);
254-
if sb.remaining() == 1 {
255-
sb = sb.push(match alloc_ty {
256-
Some(alloc_ty) if !alloc_ty.is_unknown() => alloc_ty,
257-
_ => match self.db.generic_defaults(box_adt.into()).get(1) {
258-
Some(alloc_ty) if !alloc_ty.value.is_unknown() => {
259-
alloc_ty.value.clone()
260-
}
261-
_ => self.table.new_type_var(),
262-
},
263-
});
248+
let mut b = TyBuilder::adt(self.db, box_adt).push(inner_ty);
249+
250+
if let Some(alloc_ty) = alloc_ty {
251+
b = b.push(alloc_ty);
264252
}
265-
Ty::adt_ty(box_adt, sb.build())
253+
b.fill_with_defaults(self.db, || self.table.new_type_var()).build()
266254
}
267255
None => self.err_ty(),
268256
},

crates/hir_ty/src/lib.rs

Lines changed: 82 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -812,9 +812,59 @@ impl TypeWalk for CallableSig {
812812
}
813813
}
814814

815-
struct TyBuilder {}
815+
pub struct TyBuilder<D> {
816+
data: D,
817+
vec: SmallVec<[GenericArg; 2]>,
818+
param_count: usize,
819+
}
820+
821+
impl<D> TyBuilder<D> {
822+
fn new(data: D, param_count: usize) -> TyBuilder<D> {
823+
TyBuilder { data, param_count, vec: SmallVec::with_capacity(param_count) }
824+
}
825+
826+
fn build_internal(self) -> (D, Substitution) {
827+
assert_eq!(self.vec.len(), self.param_count);
828+
// FIXME: would be good to have a way to construct a chalk_ir::Substitution from the interned form
829+
let subst = Substitution(self.vec);
830+
(self.data, subst)
831+
}
832+
833+
pub fn push(mut self, arg: impl CastTo<GenericArg>) -> Self {
834+
self.vec.push(arg.cast(&Interner));
835+
self
836+
}
837+
838+
fn remaining(&self) -> usize {
839+
self.param_count - self.vec.len()
840+
}
841+
842+
pub fn fill_with_bound_vars(self, debruijn: DebruijnIndex, starting_from: usize) -> Self {
843+
self.fill(
844+
(starting_from..)
845+
.map(|idx| TyKind::BoundVar(BoundVar::new(debruijn, idx)).intern(&Interner)),
846+
)
847+
}
848+
849+
pub fn fill_with_unknown(self) -> Self {
850+
self.fill(iter::repeat(TyKind::Unknown.intern(&Interner)))
851+
}
852+
853+
pub fn fill(mut self, filler: impl Iterator<Item = impl CastTo<GenericArg>>) -> Self {
854+
self.vec.extend(filler.take(self.remaining()).casted(&Interner));
855+
assert_eq!(self.remaining(), 0);
856+
self
857+
}
858+
859+
pub fn use_parent_substs(mut self, parent_substs: &Substitution) -> Self {
860+
assert!(self.vec.is_empty());
861+
assert!(parent_substs.len(&Interner) <= self.param_count);
862+
self.vec.extend(parent_substs.iter(&Interner).cloned());
863+
self
864+
}
865+
}
816866

817-
impl TyBuilder {
867+
impl TyBuilder<()> {
818868
pub fn unit() -> Ty {
819869
TyKind::Tuple(0, Substitution::empty(&Interner)).intern(&Interner)
820870
}
@@ -829,11 +879,38 @@ impl TyBuilder {
829879
}
830880
}
831881

832-
impl Ty {
833-
pub fn adt_ty(adt: hir_def::AdtId, substs: Substitution) -> Ty {
834-
TyKind::Adt(AdtId(adt), substs).intern(&Interner)
882+
impl TyBuilder<hir_def::AdtId> {
883+
pub fn adt(db: &dyn HirDatabase, adt: hir_def::AdtId) -> TyBuilder<hir_def::AdtId> {
884+
let generics = generics(db.upcast(), adt.into());
885+
let param_count = generics.len();
886+
TyBuilder::new(adt, param_count)
835887
}
836888

889+
pub fn fill_with_defaults(
890+
mut self,
891+
db: &dyn HirDatabase,
892+
mut fallback: impl FnMut() -> Ty,
893+
) -> Self {
894+
let defaults = db.generic_defaults(self.data.into());
895+
for default_ty in defaults.iter().skip(self.vec.len()) {
896+
if default_ty.skip_binders().is_unknown() {
897+
self.vec.push(fallback().cast(&Interner));
898+
} else {
899+
// each default can depend on the previous parameters
900+
let subst_so_far = Substitution(self.vec.clone());
901+
self.vec.push(default_ty.clone().subst(&subst_so_far).cast(&Interner));
902+
}
903+
}
904+
self
905+
}
906+
907+
pub fn build(self) -> Ty {
908+
let (adt, subst) = self.build_internal();
909+
TyKind::Adt(AdtId(adt), subst).intern(&Interner)
910+
}
911+
}
912+
913+
impl Ty {
837914
pub fn builtin(builtin: BuiltinType) -> Self {
838915
match builtin {
839916
BuiltinType::Char => TyKind::Scalar(Scalar::Char).intern(&Interner),

crates/hir_ty/src/lower.rs

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ use crate::{
3636
AliasEq, AliasTy, Binders, BoundVar, CallableSig, DebruijnIndex, DynTy, FnPointer, FnSig,
3737
ImplTraitId, OpaqueTy, PolyFnSig, ProjectionTy, QuantifiedWhereClause, QuantifiedWhereClauses,
3838
ReturnTypeImplTrait, ReturnTypeImplTraits, Substitution, TraitEnvironment, TraitRef, Ty,
39-
TyKind, TypeWalk, WhereClause,
39+
TyBuilder, TyKind, TypeWalk, WhereClause,
4040
};
4141

4242
#[derive(Debug)]
@@ -1141,9 +1141,10 @@ fn type_for_enum_variant_constructor(db: &dyn HirDatabase, def: EnumVariantId) -
11411141
}
11421142

11431143
fn type_for_adt(db: &dyn HirDatabase, adt: AdtId) -> Binders<Ty> {
1144-
let generics = generics(db.upcast(), adt.into());
1145-
let substs = Substitution::bound_vars(&generics, DebruijnIndex::INNERMOST);
1146-
Binders::new(substs.len(&Interner), Ty::adt_ty(adt, substs))
1144+
let b = TyBuilder::adt(db, adt);
1145+
let num_binders = b.remaining();
1146+
let ty = b.fill_with_bound_vars(DebruijnIndex::INNERMOST, 0).build();
1147+
Binders::new(num_binders, ty)
11471148
}
11481149

11491150
fn type_for_type_alias(db: &dyn HirDatabase, t: TypeAliasId) -> Binders<Ty> {

0 commit comments

Comments
 (0)