diff options
Diffstat (limited to 'crates/hir_ty/src/lib.rs')
-rw-r--r-- | crates/hir_ty/src/lib.rs | 87 |
1 files changed, 82 insertions, 5 deletions
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), |