diff options
-rw-r--r-- | crates/hir_ty/src/infer/expr.rs | 27 | ||||
-rw-r--r-- | crates/hir_ty/src/infer/pat.rs | 26 | ||||
-rw-r--r-- | crates/hir_ty/src/lib.rs | 87 | ||||
-rw-r--r-- | crates/hir_ty/src/lower.rs | 9 |
4 files changed, 104 insertions, 45 deletions
diff --git a/crates/hir_ty/src/infer/expr.rs b/crates/hir_ty/src/infer/expr.rs index db8aeead2..5eb07126e 100644 --- a/crates/hir_ty/src/infer/expr.rs +++ b/crates/hir_ty/src/infer/expr.rs | |||
@@ -539,17 +539,10 @@ impl<'a> InferenceContext<'a> { | |||
539 | Expr::Box { expr } => { | 539 | Expr::Box { expr } => { |
540 | let inner_ty = self.infer_expr_inner(*expr, &Expectation::none()); | 540 | let inner_ty = self.infer_expr_inner(*expr, &Expectation::none()); |
541 | if let Some(box_) = self.resolve_boxed_box() { | 541 | if let Some(box_) = self.resolve_boxed_box() { |
542 | let mut sb = | 542 | TyBuilder::adt(self.db, box_) |
543 | Substitution::build_for_generics(&generics(self.db.upcast(), box_.into())); | 543 | .push(inner_ty) |
544 | sb = sb.push(inner_ty); | 544 | .fill_with_defaults(self.db, || self.table.new_type_var()) |
545 | match self.db.generic_defaults(box_.into()).get(1) { | 545 | .build() |
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()) | ||
553 | } else { | 546 | } else { |
554 | self.err_ty() | 547 | self.err_ty() |
555 | } | 548 | } |
@@ -639,31 +632,31 @@ impl<'a> InferenceContext<'a> { | |||
639 | let rhs_ty = rhs.map(|e| self.infer_expr(e, &rhs_expect)); | 632 | let rhs_ty = rhs.map(|e| self.infer_expr(e, &rhs_expect)); |
640 | match (range_type, lhs_ty, rhs_ty) { | 633 | match (range_type, lhs_ty, rhs_ty) { |
641 | (RangeOp::Exclusive, None, None) => match self.resolve_range_full() { | 634 | (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(), |
643 | None => self.err_ty(), | 636 | None => self.err_ty(), |
644 | }, | 637 | }, |
645 | (RangeOp::Exclusive, None, Some(ty)) => match self.resolve_range_to() { | 638 | (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(), |
647 | None => self.err_ty(), | 640 | None => self.err_ty(), |
648 | }, | 641 | }, |
649 | (RangeOp::Inclusive, None, Some(ty)) => { | 642 | (RangeOp::Inclusive, None, Some(ty)) => { |
650 | match self.resolve_range_to_inclusive() { | 643 | 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(), |
652 | None => self.err_ty(), | 645 | None => self.err_ty(), |
653 | } | 646 | } |
654 | } | 647 | } |
655 | (RangeOp::Exclusive, Some(_), Some(ty)) => match self.resolve_range() { | 648 | (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(), |
657 | None => self.err_ty(), | 650 | None => self.err_ty(), |
658 | }, | 651 | }, |
659 | (RangeOp::Inclusive, Some(_), Some(ty)) => { | 652 | (RangeOp::Inclusive, Some(_), Some(ty)) => { |
660 | match self.resolve_range_inclusive() { | 653 | 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(), |
662 | None => self.err_ty(), | 655 | None => self.err_ty(), |
663 | } | 656 | } |
664 | } | 657 | } |
665 | (RangeOp::Exclusive, Some(ty), None) => match self.resolve_range_from() { | 658 | (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(), |
667 | None => self.err_ty(), | 660 | None => self.err_ty(), |
668 | }, | 661 | }, |
669 | (RangeOp::Inclusive, _, None) => self.err_ty(), | 662 | (RangeOp::Inclusive, _, None) => self.err_ty(), |
diff --git a/crates/hir_ty/src/infer/pat.rs b/crates/hir_ty/src/infer/pat.rs index 10df8d8cb..5b70d5e5a 100644 --- a/crates/hir_ty/src/infer/pat.rs +++ b/crates/hir_ty/src/infer/pat.rs | |||
@@ -13,9 +13,8 @@ use hir_expand::name::Name; | |||
13 | 13 | ||
14 | use super::{BindingMode, Expectation, InferenceContext}; | 14 | use super::{BindingMode, Expectation, InferenceContext}; |
15 | use crate::{ | 15 | use crate::{ |
16 | lower::lower_to_chalk_mutability, | 16 | lower::lower_to_chalk_mutability, utils::variant_data, Interner, Substitution, Ty, TyBuilder, |
17 | utils::{generics, variant_data}, | 17 | TyKind, |
18 | Interner, Substitution, Ty, TyKind, | ||
19 | }; | 18 | }; |
20 | 19 | ||
21 | impl<'a> InferenceContext<'a> { | 20 | impl<'a> InferenceContext<'a> { |
@@ -246,23 +245,12 @@ impl<'a> InferenceContext<'a> { | |||
246 | }; | 245 | }; |
247 | 246 | ||
248 | let inner_ty = self.infer_pat(*inner, &inner_ty, default_bm); | 247 | let inner_ty = self.infer_pat(*inner, &inner_ty, default_bm); |
249 | let mut sb = Substitution::build_for_generics(&generics( | 248 | let mut b = TyBuilder::adt(self.db, box_adt).push(inner_ty); |
250 | self.db.upcast(), | 249 | |
251 | box_adt.into(), | 250 | if let Some(alloc_ty) = alloc_ty { |
252 | )); | 251 | b = b.push(alloc_ty); |
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 | }); | ||
264 | } | 252 | } |
265 | Ty::adt_ty(box_adt, sb.build()) | 253 | b.fill_with_defaults(self.db, || self.table.new_type_var()).build() |
266 | } | 254 | } |
267 | None => self.err_ty(), | 255 | None => self.err_ty(), |
268 | }, | 256 | }, |
diff --git a/crates/hir_ty/src/lib.rs b/crates/hir_ty/src/lib.rs index fd44efa07..afe5424d6 100644 --- a/crates/hir_ty/src/lib.rs +++ b/crates/hir_ty/src/lib.rs | |||
@@ -812,9 +812,59 @@ impl TypeWalk for CallableSig { | |||
812 | } | 812 | } |
813 | } | 813 | } |
814 | 814 | ||
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 | } | ||
816 | 866 | ||
817 | impl TyBuilder { | 867 | impl TyBuilder<()> { |
818 | pub fn unit() -> Ty { | 868 | pub fn unit() -> Ty { |
819 | TyKind::Tuple(0, Substitution::empty(&Interner)).intern(&Interner) | 869 | TyKind::Tuple(0, Substitution::empty(&Interner)).intern(&Interner) |
820 | } | 870 | } |
@@ -829,11 +879,38 @@ impl TyBuilder { | |||
829 | } | 879 | } |
830 | } | 880 | } |
831 | 881 | ||
832 | impl Ty { | 882 | impl TyBuilder<hir_def::AdtId> { |
833 | pub fn adt_ty(adt: hir_def::AdtId, substs: Substitution) -> Ty { | 883 | pub fn adt(db: &dyn HirDatabase, adt: hir_def::AdtId) -> TyBuilder<hir_def::AdtId> { |
834 | TyKind::Adt(AdtId(adt), substs).intern(&Interner) | 884 | let generics = generics(db.upcast(), adt.into()); |
885 | let param_count = generics.len(); | ||
886 | TyBuilder::new(adt, param_count) | ||
835 | } | 887 | } |
836 | 888 | ||
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 { | ||
837 | pub fn builtin(builtin: BuiltinType) -> Self { | 914 | pub fn builtin(builtin: BuiltinType) -> Self { |
838 | match builtin { | 915 | match builtin { |
839 | BuiltinType::Char => TyKind::Scalar(Scalar::Char).intern(&Interner), | 916 | BuiltinType::Char => TyKind::Scalar(Scalar::Char).intern(&Interner), |
diff --git a/crates/hir_ty/src/lower.rs b/crates/hir_ty/src/lower.rs index e60d7c730..5e2024f0a 100644 --- a/crates/hir_ty/src/lower.rs +++ b/crates/hir_ty/src/lower.rs | |||
@@ -36,7 +36,7 @@ use crate::{ | |||
36 | AliasEq, AliasTy, Binders, BoundVar, CallableSig, DebruijnIndex, DynTy, FnPointer, FnSig, | 36 | AliasEq, AliasTy, Binders, BoundVar, CallableSig, DebruijnIndex, DynTy, FnPointer, FnSig, |
37 | ImplTraitId, OpaqueTy, PolyFnSig, ProjectionTy, QuantifiedWhereClause, QuantifiedWhereClauses, | 37 | ImplTraitId, OpaqueTy, PolyFnSig, ProjectionTy, QuantifiedWhereClause, QuantifiedWhereClauses, |
38 | ReturnTypeImplTrait, ReturnTypeImplTraits, Substitution, TraitEnvironment, TraitRef, Ty, | 38 | ReturnTypeImplTrait, ReturnTypeImplTraits, Substitution, TraitEnvironment, TraitRef, Ty, |
39 | TyKind, TypeWalk, WhereClause, | 39 | TyBuilder, TyKind, TypeWalk, WhereClause, |
40 | }; | 40 | }; |
41 | 41 | ||
42 | #[derive(Debug)] | 42 | #[derive(Debug)] |
@@ -1141,9 +1141,10 @@ fn type_for_enum_variant_constructor(db: &dyn HirDatabase, def: EnumVariantId) - | |||
1141 | } | 1141 | } |
1142 | 1142 | ||
1143 | fn type_for_adt(db: &dyn HirDatabase, adt: AdtId) -> Binders<Ty> { | 1143 | fn type_for_adt(db: &dyn HirDatabase, adt: AdtId) -> Binders<Ty> { |
1144 | let generics = generics(db.upcast(), adt.into()); | 1144 | let b = TyBuilder::adt(db, adt); |
1145 | let substs = Substitution::bound_vars(&generics, DebruijnIndex::INNERMOST); | 1145 | let num_binders = b.remaining(); |
1146 | Binders::new(substs.len(&Interner), Ty::adt_ty(adt, substs)) | 1146 | let ty = b.fill_with_bound_vars(DebruijnIndex::INNERMOST, 0).build(); |
1147 | Binders::new(num_binders, ty) | ||
1147 | } | 1148 | } |
1148 | 1149 | ||
1149 | fn type_for_type_alias(db: &dyn HirDatabase, t: TypeAliasId) -> Binders<Ty> { | 1150 | fn type_for_type_alias(db: &dyn HirDatabase, t: TypeAliasId) -> Binders<Ty> { |