aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--crates/hir_ty/src/builder.rs211
-rw-r--r--crates/hir_ty/src/lib.rs214
2 files changed, 221 insertions, 204 deletions
diff --git a/crates/hir_ty/src/builder.rs b/crates/hir_ty/src/builder.rs
new file mode 100644
index 000000000..ba158a749
--- /dev/null
+++ b/crates/hir_ty/src/builder.rs
@@ -0,0 +1,211 @@
1//! `TyBuilder`, a helper for building instances of `Ty` and related types.
2
3use std::iter;
4
5use chalk_ir::{
6 cast::{Cast, CastTo, Caster},
7 interner::HasInterner,
8 AdtId, BoundVar, DebruijnIndex, Safety, Scalar,
9};
10use hir_def::{builtin_type::BuiltinType, GenericDefId, TraitId, TypeAliasId};
11use smallvec::SmallVec;
12
13use crate::{
14 db::HirDatabase, primitive, to_assoc_type_id, to_chalk_trait_id, utils::generics, Binders,
15 CallableSig, FnPointer, FnSig, GenericArg, Interner, ProjectionTy, Substitution, TraitRef, Ty,
16 TyDefId, TyKind, TypeWalk, ValueTyDefId,
17};
18
19pub struct TyBuilder<D> {
20 data: D,
21 vec: SmallVec<[GenericArg; 2]>,
22 param_count: usize,
23}
24
25impl<D> TyBuilder<D> {
26 fn new(data: D, param_count: usize) -> TyBuilder<D> {
27 TyBuilder { data, param_count, vec: SmallVec::with_capacity(param_count) }
28 }
29
30 fn build_internal(self) -> (D, Substitution) {
31 assert_eq!(self.vec.len(), self.param_count);
32 // FIXME: would be good to have a way to construct a chalk_ir::Substitution from the interned form
33 let subst = Substitution(self.vec);
34 (self.data, subst)
35 }
36
37 pub fn push(mut self, arg: impl CastTo<GenericArg>) -> Self {
38 self.vec.push(arg.cast(&Interner));
39 self
40 }
41
42 pub fn remaining(&self) -> usize {
43 self.param_count - self.vec.len()
44 }
45
46 pub fn fill_with_bound_vars(self, debruijn: DebruijnIndex, starting_from: usize) -> Self {
47 self.fill(
48 (starting_from..)
49 .map(|idx| TyKind::BoundVar(BoundVar::new(debruijn, idx)).intern(&Interner)),
50 )
51 }
52
53 pub fn fill_with_unknown(self) -> Self {
54 self.fill(iter::repeat(TyKind::Unknown.intern(&Interner)))
55 }
56
57 pub fn fill(mut self, filler: impl Iterator<Item = impl CastTo<GenericArg>>) -> Self {
58 self.vec.extend(filler.take(self.remaining()).casted(&Interner));
59 assert_eq!(self.remaining(), 0);
60 self
61 }
62
63 pub fn use_parent_substs(mut self, parent_substs: &Substitution) -> Self {
64 assert!(self.vec.is_empty());
65 assert!(parent_substs.len(&Interner) <= self.param_count);
66 self.vec.extend(parent_substs.iter(&Interner).cloned());
67 self
68 }
69}
70
71impl TyBuilder<()> {
72 pub fn unit() -> Ty {
73 TyKind::Tuple(0, Substitution::empty(&Interner)).intern(&Interner)
74 }
75
76 pub fn fn_ptr(sig: CallableSig) -> Ty {
77 TyKind::Function(FnPointer {
78 num_args: sig.params().len(),
79 sig: FnSig { abi: (), safety: Safety::Safe, variadic: sig.is_varargs },
80 substs: Substitution::from_iter(&Interner, sig.params_and_return.iter().cloned()),
81 })
82 .intern(&Interner)
83 }
84
85 pub fn builtin(builtin: BuiltinType) -> Ty {
86 match builtin {
87 BuiltinType::Char => TyKind::Scalar(Scalar::Char).intern(&Interner),
88 BuiltinType::Bool => TyKind::Scalar(Scalar::Bool).intern(&Interner),
89 BuiltinType::Str => TyKind::Str.intern(&Interner),
90 BuiltinType::Int(t) => {
91 TyKind::Scalar(Scalar::Int(primitive::int_ty_from_builtin(t))).intern(&Interner)
92 }
93 BuiltinType::Uint(t) => {
94 TyKind::Scalar(Scalar::Uint(primitive::uint_ty_from_builtin(t))).intern(&Interner)
95 }
96 BuiltinType::Float(t) => {
97 TyKind::Scalar(Scalar::Float(primitive::float_ty_from_builtin(t))).intern(&Interner)
98 }
99 }
100 }
101
102 pub fn subst_for_def(db: &dyn HirDatabase, def: impl Into<GenericDefId>) -> TyBuilder<()> {
103 let def = def.into();
104 let params = generics(db.upcast(), def);
105 let param_count = params.len();
106 TyBuilder::new((), param_count)
107 }
108
109 pub fn build(self) -> Substitution {
110 let ((), subst) = self.build_internal();
111 subst
112 }
113}
114
115impl TyBuilder<hir_def::AdtId> {
116 pub fn adt(db: &dyn HirDatabase, adt: hir_def::AdtId) -> TyBuilder<hir_def::AdtId> {
117 let generics = generics(db.upcast(), adt.into());
118 let param_count = generics.len();
119 TyBuilder::new(adt, param_count)
120 }
121
122 pub fn fill_with_defaults(
123 mut self,
124 db: &dyn HirDatabase,
125 mut fallback: impl FnMut() -> Ty,
126 ) -> Self {
127 let defaults = db.generic_defaults(self.data.into());
128 for default_ty in defaults.iter().skip(self.vec.len()) {
129 if default_ty.skip_binders().is_unknown() {
130 self.vec.push(fallback().cast(&Interner));
131 } else {
132 // each default can depend on the previous parameters
133 let subst_so_far = Substitution(self.vec.clone());
134 self.vec.push(default_ty.clone().subst(&subst_so_far).cast(&Interner));
135 }
136 }
137 self
138 }
139
140 pub fn build(self) -> Ty {
141 let (adt, subst) = self.build_internal();
142 TyKind::Adt(AdtId(adt), subst).intern(&Interner)
143 }
144}
145
146pub struct Tuple(usize);
147impl TyBuilder<Tuple> {
148 pub fn tuple(size: usize) -> TyBuilder<Tuple> {
149 TyBuilder::new(Tuple(size), size)
150 }
151
152 pub fn build(self) -> Ty {
153 let (Tuple(size), subst) = self.build_internal();
154 TyKind::Tuple(size, subst).intern(&Interner)
155 }
156}
157
158impl TyBuilder<TraitId> {
159 pub fn trait_ref(db: &dyn HirDatabase, trait_id: TraitId) -> TyBuilder<TraitId> {
160 let generics = generics(db.upcast(), trait_id.into());
161 let param_count = generics.len();
162 TyBuilder::new(trait_id, param_count)
163 }
164
165 pub fn build(self) -> TraitRef {
166 let (trait_id, substitution) = self.build_internal();
167 TraitRef { trait_id: to_chalk_trait_id(trait_id), substitution }
168 }
169}
170
171impl TyBuilder<TypeAliasId> {
172 pub fn assoc_type_projection(
173 db: &dyn HirDatabase,
174 type_alias: TypeAliasId,
175 ) -> TyBuilder<TypeAliasId> {
176 let generics = generics(db.upcast(), type_alias.into());
177 let param_count = generics.len();
178 TyBuilder::new(type_alias, param_count)
179 }
180
181 pub fn build(self) -> ProjectionTy {
182 let (type_alias, substitution) = self.build_internal();
183 ProjectionTy { associated_ty_id: to_assoc_type_id(type_alias), substitution }
184 }
185}
186
187impl<T: TypeWalk + HasInterner<Interner = Interner>> TyBuilder<Binders<T>> {
188 fn subst_binders(b: Binders<T>) -> Self {
189 let param_count = b.num_binders;
190 TyBuilder::new(b, param_count)
191 }
192
193 pub fn build(self) -> T {
194 let (b, subst) = self.build_internal();
195 b.subst(&subst)
196 }
197}
198
199impl TyBuilder<Binders<Ty>> {
200 pub fn def_ty(db: &dyn HirDatabase, def: TyDefId) -> TyBuilder<Binders<Ty>> {
201 TyBuilder::subst_binders(db.ty(def.into()))
202 }
203
204 pub fn impl_self_ty(db: &dyn HirDatabase, def: hir_def::ImplId) -> TyBuilder<Binders<Ty>> {
205 TyBuilder::subst_binders(db.impl_self_ty(def))
206 }
207
208 pub fn value_ty(db: &dyn HirDatabase, def: ValueTyDefId) -> TyBuilder<Binders<Ty>> {
209 TyBuilder::subst_binders(db.value_ty(def))
210 }
211}
diff --git a/crates/hir_ty/src/lib.rs b/crates/hir_ty/src/lib.rs
index f99b70f2b..ebdcc4804 100644
--- a/crates/hir_ty/src/lib.rs
+++ b/crates/hir_ty/src/lib.rs
@@ -14,6 +14,8 @@ mod lower;
14pub(crate) mod infer; 14pub(crate) mod infer;
15pub(crate) mod utils; 15pub(crate) mod utils;
16mod chalk_cast; 16mod chalk_cast;
17mod chalk_ext;
18mod builder;
17 19
18pub mod display; 20pub mod display;
19pub mod db; 21pub mod db;
@@ -23,21 +25,18 @@ pub mod diagnostics;
23mod tests; 25mod tests;
24#[cfg(test)] 26#[cfg(test)]
25mod test_db; 27mod test_db;
26mod chalk_ext;
27 28
28use std::{iter, mem, sync::Arc}; 29use std::{mem, sync::Arc};
30
31use chalk_ir::cast::{CastTo, Caster};
32use itertools::Itertools;
33use smallvec::SmallVec;
29 34
30use base_db::salsa; 35use base_db::salsa;
31use chalk_ir::{
32 cast::{CastTo, Caster},
33 interner::HasInterner,
34};
35use hir_def::{ 36use hir_def::{
36 builtin_type::BuiltinType, expr::ExprId, type_ref::Rawness, AssocContainerId, FunctionId, 37 expr::ExprId, type_ref::Rawness, AssocContainerId, FunctionId, GenericDefId, HasModule,
37 GenericDefId, HasModule, LifetimeParamId, Lookup, TraitId, TypeAliasId, TypeParamId, 38 LifetimeParamId, Lookup, TraitId, TypeAliasId, TypeParamId,
38}; 39};
39use itertools::Itertools;
40use smallvec::SmallVec;
41 40
42use crate::{ 41use crate::{
43 db::HirDatabase, 42 db::HirDatabase,
@@ -46,6 +45,7 @@ use crate::{
46}; 45};
47 46
48pub use autoderef::autoderef; 47pub use autoderef::autoderef;
48pub use builder::TyBuilder;
49pub use chalk_ext::TyExt; 49pub use chalk_ext::TyExt;
50pub use infer::{could_unify, InferenceResult, InferenceVar}; 50pub use infer::{could_unify, InferenceResult, InferenceVar};
51pub use lower::{ 51pub use lower::{
@@ -744,200 +744,6 @@ impl TypeWalk for CallableSig {
744 } 744 }
745} 745}
746 746
747pub struct TyBuilder<D> {
748 data: D,
749 vec: SmallVec<[GenericArg; 2]>,
750 param_count: usize,
751}
752
753impl<D> TyBuilder<D> {
754 fn new(data: D, param_count: usize) -> TyBuilder<D> {
755 TyBuilder { data, param_count, vec: SmallVec::with_capacity(param_count) }
756 }
757
758 fn build_internal(self) -> (D, Substitution) {
759 assert_eq!(self.vec.len(), self.param_count);
760 // FIXME: would be good to have a way to construct a chalk_ir::Substitution from the interned form
761 let subst = Substitution(self.vec);
762 (self.data, subst)
763 }
764
765 pub fn push(mut self, arg: impl CastTo<GenericArg>) -> Self {
766 self.vec.push(arg.cast(&Interner));
767 self
768 }
769
770 fn remaining(&self) -> usize {
771 self.param_count - self.vec.len()
772 }
773
774 pub fn fill_with_bound_vars(self, debruijn: DebruijnIndex, starting_from: usize) -> Self {
775 self.fill(
776 (starting_from..)
777 .map(|idx| TyKind::BoundVar(BoundVar::new(debruijn, idx)).intern(&Interner)),
778 )
779 }
780
781 pub fn fill_with_unknown(self) -> Self {
782 self.fill(iter::repeat(TyKind::Unknown.intern(&Interner)))
783 }
784
785 pub fn fill(mut self, filler: impl Iterator<Item = impl CastTo<GenericArg>>) -> Self {
786 self.vec.extend(filler.take(self.remaining()).casted(&Interner));
787 assert_eq!(self.remaining(), 0);
788 self
789 }
790
791 pub fn use_parent_substs(mut self, parent_substs: &Substitution) -> Self {
792 assert!(self.vec.is_empty());
793 assert!(parent_substs.len(&Interner) <= self.param_count);
794 self.vec.extend(parent_substs.iter(&Interner).cloned());
795 self
796 }
797}
798
799impl TyBuilder<()> {
800 pub fn unit() -> Ty {
801 TyKind::Tuple(0, Substitution::empty(&Interner)).intern(&Interner)
802 }
803
804 pub fn fn_ptr(sig: CallableSig) -> Ty {
805 TyKind::Function(FnPointer {
806 num_args: sig.params().len(),
807 sig: FnSig { abi: (), safety: Safety::Safe, variadic: sig.is_varargs },
808 substs: Substitution::from_iter(&Interner, sig.params_and_return.iter().cloned()),
809 })
810 .intern(&Interner)
811 }
812
813 pub fn builtin(builtin: BuiltinType) -> Ty {
814 match builtin {
815 BuiltinType::Char => TyKind::Scalar(Scalar::Char).intern(&Interner),
816 BuiltinType::Bool => TyKind::Scalar(Scalar::Bool).intern(&Interner),
817 BuiltinType::Str => TyKind::Str.intern(&Interner),
818 BuiltinType::Int(t) => {
819 TyKind::Scalar(Scalar::Int(primitive::int_ty_from_builtin(t))).intern(&Interner)
820 }
821 BuiltinType::Uint(t) => {
822 TyKind::Scalar(Scalar::Uint(primitive::uint_ty_from_builtin(t))).intern(&Interner)
823 }
824 BuiltinType::Float(t) => {
825 TyKind::Scalar(Scalar::Float(primitive::float_ty_from_builtin(t))).intern(&Interner)
826 }
827 }
828 }
829
830 pub fn subst_for_def(db: &dyn HirDatabase, def: impl Into<GenericDefId>) -> TyBuilder<()> {
831 let def = def.into();
832 let params = generics(db.upcast(), def);
833 let param_count = params.len();
834 TyBuilder::new((), param_count)
835 }
836
837 pub fn build(self) -> Substitution {
838 let ((), subst) = self.build_internal();
839 subst
840 }
841}
842
843impl TyBuilder<hir_def::AdtId> {
844 pub fn adt(db: &dyn HirDatabase, adt: hir_def::AdtId) -> TyBuilder<hir_def::AdtId> {
845 let generics = generics(db.upcast(), adt.into());
846 let param_count = generics.len();
847 TyBuilder::new(adt, param_count)
848 }
849
850 pub fn fill_with_defaults(
851 mut self,
852 db: &dyn HirDatabase,
853 mut fallback: impl FnMut() -> Ty,
854 ) -> Self {
855 let defaults = db.generic_defaults(self.data.into());
856 for default_ty in defaults.iter().skip(self.vec.len()) {
857 if default_ty.skip_binders().is_unknown() {
858 self.vec.push(fallback().cast(&Interner));
859 } else {
860 // each default can depend on the previous parameters
861 let subst_so_far = Substitution(self.vec.clone());
862 self.vec.push(default_ty.clone().subst(&subst_so_far).cast(&Interner));
863 }
864 }
865 self
866 }
867
868 pub fn build(self) -> Ty {
869 let (adt, subst) = self.build_internal();
870 TyKind::Adt(AdtId(adt), subst).intern(&Interner)
871 }
872}
873
874struct Tuple(usize);
875impl TyBuilder<Tuple> {
876 pub fn tuple(size: usize) -> TyBuilder<Tuple> {
877 TyBuilder::new(Tuple(size), size)
878 }
879
880 pub fn build(self) -> Ty {
881 let (Tuple(size), subst) = self.build_internal();
882 TyKind::Tuple(size, subst).intern(&Interner)
883 }
884}
885
886impl TyBuilder<TraitId> {
887 pub fn trait_ref(db: &dyn HirDatabase, trait_id: TraitId) -> TyBuilder<TraitId> {
888 let generics = generics(db.upcast(), trait_id.into());
889 let param_count = generics.len();
890 TyBuilder::new(trait_id, param_count)
891 }
892
893 pub fn build(self) -> TraitRef {
894 let (trait_id, substitution) = self.build_internal();
895 TraitRef { trait_id: to_chalk_trait_id(trait_id), substitution }
896 }
897}
898
899impl TyBuilder<TypeAliasId> {
900 pub fn assoc_type_projection(
901 db: &dyn HirDatabase,
902 type_alias: TypeAliasId,
903 ) -> TyBuilder<TypeAliasId> {
904 let generics = generics(db.upcast(), type_alias.into());
905 let param_count = generics.len();
906 TyBuilder::new(type_alias, param_count)
907 }
908
909 pub fn build(self) -> ProjectionTy {
910 let (type_alias, substitution) = self.build_internal();
911 ProjectionTy { associated_ty_id: to_assoc_type_id(type_alias), substitution }
912 }
913}
914
915impl<T: TypeWalk + HasInterner<Interner = Interner>> TyBuilder<Binders<T>> {
916 fn subst_binders(b: Binders<T>) -> Self {
917 let param_count = b.num_binders;
918 TyBuilder::new(b, param_count)
919 }
920
921 pub fn build(self) -> T {
922 let (b, subst) = self.build_internal();
923 b.subst(&subst)
924 }
925}
926
927impl TyBuilder<Binders<Ty>> {
928 pub fn def_ty(db: &dyn HirDatabase, def: TyDefId) -> TyBuilder<Binders<Ty>> {
929 TyBuilder::subst_binders(db.ty(def.into()))
930 }
931
932 pub fn impl_self_ty(db: &dyn HirDatabase, def: hir_def::ImplId) -> TyBuilder<Binders<Ty>> {
933 TyBuilder::subst_binders(db.impl_self_ty(def))
934 }
935
936 pub fn value_ty(db: &dyn HirDatabase, def: ValueTyDefId) -> TyBuilder<Binders<Ty>> {
937 TyBuilder::subst_binders(db.value_ty(def))
938 }
939}
940
941impl Ty { 747impl Ty {
942 pub fn as_reference(&self) -> Option<(&Ty, Mutability)> { 748 pub fn as_reference(&self) -> Option<(&Ty, Mutability)> {
943 match self.kind(&Interner) { 749 match self.kind(&Interner) {