diff options
Diffstat (limited to 'crates/hir_ty/src/types.rs')
-rw-r--r-- | crates/hir_ty/src/types.rs | 416 |
1 files changed, 416 insertions, 0 deletions
diff --git a/crates/hir_ty/src/types.rs b/crates/hir_ty/src/types.rs new file mode 100644 index 000000000..53662fcdc --- /dev/null +++ b/crates/hir_ty/src/types.rs | |||
@@ -0,0 +1,416 @@ | |||
1 | //! This is the home of `Ty` etc. until they get replaced by their chalk_ir | ||
2 | //! equivalents. | ||
3 | |||
4 | use std::sync::Arc; | ||
5 | |||
6 | use chalk_ir::{ | ||
7 | cast::{CastTo, Caster}, | ||
8 | BoundVar, Mutability, Scalar, TyVariableKind, | ||
9 | }; | ||
10 | use hir_def::LifetimeParamId; | ||
11 | use smallvec::SmallVec; | ||
12 | |||
13 | use crate::{ | ||
14 | AssocTypeId, CanonicalVarKinds, ChalkTraitId, ClosureId, FnDefId, FnSig, ForeignDefId, | ||
15 | InferenceVar, Interner, OpaqueTyId, PlaceholderIndex, | ||
16 | }; | ||
17 | |||
18 | #[derive(Clone, PartialEq, Eq, Debug, Hash)] | ||
19 | pub enum Lifetime { | ||
20 | Parameter(LifetimeParamId), | ||
21 | Static, | ||
22 | } | ||
23 | |||
24 | #[derive(Clone, PartialEq, Eq, Debug, Hash)] | ||
25 | pub struct OpaqueTy { | ||
26 | pub opaque_ty_id: OpaqueTyId, | ||
27 | pub substitution: Substitution, | ||
28 | } | ||
29 | |||
30 | /// A "projection" type corresponds to an (unnormalized) | ||
31 | /// projection like `<P0 as Trait<P1..Pn>>::Foo`. Note that the | ||
32 | /// trait and all its parameters are fully known. | ||
33 | #[derive(Clone, PartialEq, Eq, Debug, Hash)] | ||
34 | pub struct ProjectionTy { | ||
35 | pub associated_ty_id: AssocTypeId, | ||
36 | pub substitution: Substitution, | ||
37 | } | ||
38 | |||
39 | #[derive(Clone, PartialEq, Eq, Debug, Hash)] | ||
40 | pub struct DynTy { | ||
41 | /// The unknown self type. | ||
42 | pub bounds: Binders<QuantifiedWhereClauses>, | ||
43 | } | ||
44 | |||
45 | #[derive(Clone, PartialEq, Eq, Debug, Hash)] | ||
46 | pub struct FnPointer { | ||
47 | pub num_args: usize, | ||
48 | pub sig: FnSig, | ||
49 | pub substs: Substitution, | ||
50 | } | ||
51 | |||
52 | #[derive(Clone, PartialEq, Eq, Debug, Hash)] | ||
53 | pub enum AliasTy { | ||
54 | /// A "projection" type corresponds to an (unnormalized) | ||
55 | /// projection like `<P0 as Trait<P1..Pn>>::Foo`. Note that the | ||
56 | /// trait and all its parameters are fully known. | ||
57 | Projection(ProjectionTy), | ||
58 | /// An opaque type (`impl Trait`). | ||
59 | /// | ||
60 | /// This is currently only used for return type impl trait; each instance of | ||
61 | /// `impl Trait` in a return type gets its own ID. | ||
62 | Opaque(OpaqueTy), | ||
63 | } | ||
64 | |||
65 | /// A type. | ||
66 | /// | ||
67 | /// See also the `TyKind` enum in rustc (librustc/ty/sty.rs), which represents | ||
68 | /// the same thing (but in a different way). | ||
69 | /// | ||
70 | /// This should be cheap to clone. | ||
71 | #[derive(Clone, PartialEq, Eq, Debug, Hash)] | ||
72 | pub enum TyKind { | ||
73 | /// Structures, enumerations and unions. | ||
74 | Adt(chalk_ir::AdtId<Interner>, Substitution), | ||
75 | |||
76 | /// Represents an associated item like `Iterator::Item`. This is used | ||
77 | /// when we have tried to normalize a projection like `T::Item` but | ||
78 | /// couldn't find a better representation. In that case, we generate | ||
79 | /// an **application type** like `(Iterator::Item)<T>`. | ||
80 | AssociatedType(AssocTypeId, Substitution), | ||
81 | |||
82 | /// a scalar type like `bool` or `u32` | ||
83 | Scalar(Scalar), | ||
84 | |||
85 | /// A tuple type. For example, `(i32, bool)`. | ||
86 | Tuple(usize, Substitution), | ||
87 | |||
88 | /// An array with the given length. Written as `[T; n]`. | ||
89 | Array(Ty), | ||
90 | |||
91 | /// The pointee of an array slice. Written as `[T]`. | ||
92 | Slice(Ty), | ||
93 | |||
94 | /// A raw pointer. Written as `*mut T` or `*const T` | ||
95 | Raw(Mutability, Ty), | ||
96 | |||
97 | /// A reference; a pointer with an associated lifetime. Written as | ||
98 | /// `&'a mut T` or `&'a T`. | ||
99 | Ref(Mutability, Ty), | ||
100 | |||
101 | /// This represents a placeholder for an opaque type in situations where we | ||
102 | /// don't know the hidden type (i.e. currently almost always). This is | ||
103 | /// analogous to the `AssociatedType` type constructor. | ||
104 | /// It is also used as the type of async block, with one type parameter | ||
105 | /// representing the Future::Output type. | ||
106 | OpaqueType(OpaqueTyId, Substitution), | ||
107 | |||
108 | /// The anonymous type of a function declaration/definition. Each | ||
109 | /// function has a unique type, which is output (for a function | ||
110 | /// named `foo` returning an `i32`) as `fn() -> i32 {foo}`. | ||
111 | /// | ||
112 | /// This includes tuple struct / enum variant constructors as well. | ||
113 | /// | ||
114 | /// For example the type of `bar` here: | ||
115 | /// | ||
116 | /// ``` | ||
117 | /// fn foo() -> i32 { 1 } | ||
118 | /// let bar = foo; // bar: fn() -> i32 {foo} | ||
119 | /// ``` | ||
120 | FnDef(FnDefId, Substitution), | ||
121 | |||
122 | /// The pointee of a string slice. Written as `str`. | ||
123 | Str, | ||
124 | |||
125 | /// The never type `!`. | ||
126 | Never, | ||
127 | |||
128 | /// The type of a specific closure. | ||
129 | /// | ||
130 | /// The closure signature is stored in a `FnPtr` type in the first type | ||
131 | /// parameter. | ||
132 | Closure(ClosureId, Substitution), | ||
133 | |||
134 | /// Represents a foreign type declared in external blocks. | ||
135 | ForeignType(ForeignDefId), | ||
136 | |||
137 | /// A pointer to a function. Written as `fn() -> i32`. | ||
138 | /// | ||
139 | /// For example the type of `bar` here: | ||
140 | /// | ||
141 | /// ``` | ||
142 | /// fn foo() -> i32 { 1 } | ||
143 | /// let bar: fn() -> i32 = foo; | ||
144 | /// ``` | ||
145 | Function(FnPointer), | ||
146 | |||
147 | /// An "alias" type represents some form of type alias, such as: | ||
148 | /// - An associated type projection like `<T as Iterator>::Item` | ||
149 | /// - `impl Trait` types | ||
150 | /// - Named type aliases like `type Foo<X> = Vec<X>` | ||
151 | Alias(AliasTy), | ||
152 | |||
153 | /// A placeholder for a type parameter; for example, `T` in `fn f<T>(x: T) | ||
154 | /// {}` when we're type-checking the body of that function. In this | ||
155 | /// situation, we know this stands for *some* type, but don't know the exact | ||
156 | /// type. | ||
157 | Placeholder(PlaceholderIndex), | ||
158 | |||
159 | /// A bound type variable. This is used in various places: when representing | ||
160 | /// some polymorphic type like the type of function `fn f<T>`, the type | ||
161 | /// parameters get turned into variables; during trait resolution, inference | ||
162 | /// variables get turned into bound variables and back; and in `Dyn` the | ||
163 | /// `Self` type is represented with a bound variable as well. | ||
164 | BoundVar(BoundVar), | ||
165 | |||
166 | /// A type variable used during type checking. | ||
167 | InferenceVar(InferenceVar, TyVariableKind), | ||
168 | |||
169 | /// A trait object (`dyn Trait` or bare `Trait` in pre-2018 Rust). | ||
170 | /// | ||
171 | /// The predicates are quantified over the `Self` type, i.e. `Ty::Bound(0)` | ||
172 | /// represents the `Self` type inside the bounds. This is currently | ||
173 | /// implicit; Chalk has the `Binders` struct to make it explicit, but it | ||
174 | /// didn't seem worth the overhead yet. | ||
175 | Dyn(DynTy), | ||
176 | |||
177 | /// A placeholder for a type which could not be computed; this is propagated | ||
178 | /// to avoid useless error messages. Doubles as a placeholder where type | ||
179 | /// variables are inserted before type checking, since we want to try to | ||
180 | /// infer a better type here anyway -- for the IDE use case, we want to try | ||
181 | /// to infer as much as possible even in the presence of type errors. | ||
182 | Unknown, | ||
183 | } | ||
184 | |||
185 | #[derive(Clone, PartialEq, Eq, Debug, Hash)] | ||
186 | pub struct Ty(Arc<TyKind>); | ||
187 | |||
188 | impl TyKind { | ||
189 | pub fn intern(self, _interner: &Interner) -> Ty { | ||
190 | Ty(Arc::new(self)) | ||
191 | } | ||
192 | } | ||
193 | |||
194 | impl Ty { | ||
195 | pub fn kind(&self, _interner: &Interner) -> &TyKind { | ||
196 | &self.0 | ||
197 | } | ||
198 | |||
199 | pub fn interned_mut(&mut self) -> &mut TyKind { | ||
200 | Arc::make_mut(&mut self.0) | ||
201 | } | ||
202 | |||
203 | pub fn into_inner(self) -> TyKind { | ||
204 | Arc::try_unwrap(self.0).unwrap_or_else(|a| (*a).clone()) | ||
205 | } | ||
206 | } | ||
207 | |||
208 | #[derive(Clone, PartialEq, Eq, Debug, Hash)] | ||
209 | pub struct GenericArg { | ||
210 | interned: GenericArgData, | ||
211 | } | ||
212 | |||
213 | #[derive(Clone, PartialEq, Eq, Debug, Hash)] | ||
214 | pub enum GenericArgData { | ||
215 | Ty(Ty), | ||
216 | } | ||
217 | |||
218 | impl GenericArg { | ||
219 | /// Constructs a generic argument using `GenericArgData`. | ||
220 | pub fn new(_interner: &Interner, data: GenericArgData) -> Self { | ||
221 | GenericArg { interned: data } | ||
222 | } | ||
223 | |||
224 | /// Gets the interned value. | ||
225 | pub fn interned(&self) -> &GenericArgData { | ||
226 | &self.interned | ||
227 | } | ||
228 | |||
229 | /// Asserts that this is a type argument. | ||
230 | pub fn assert_ty_ref(&self, interner: &Interner) -> &Ty { | ||
231 | self.ty(interner).unwrap() | ||
232 | } | ||
233 | |||
234 | /// Checks whether the generic argument is a type. | ||
235 | pub fn is_ty(&self, _interner: &Interner) -> bool { | ||
236 | match self.interned() { | ||
237 | GenericArgData::Ty(_) => true, | ||
238 | } | ||
239 | } | ||
240 | |||
241 | /// Returns the type if it is one, `None` otherwise. | ||
242 | pub fn ty(&self, _interner: &Interner) -> Option<&Ty> { | ||
243 | match self.interned() { | ||
244 | GenericArgData::Ty(t) => Some(t), | ||
245 | } | ||
246 | } | ||
247 | |||
248 | pub fn interned_mut(&mut self) -> &mut GenericArgData { | ||
249 | &mut self.interned | ||
250 | } | ||
251 | } | ||
252 | |||
253 | /// A list of substitutions for generic parameters. | ||
254 | #[derive(Clone, PartialEq, Eq, Debug, Hash)] | ||
255 | pub struct Substitution(SmallVec<[GenericArg; 2]>); | ||
256 | |||
257 | impl Substitution { | ||
258 | pub fn interned(&self) -> &[GenericArg] { | ||
259 | &self.0 | ||
260 | } | ||
261 | |||
262 | pub fn len(&self, _: &Interner) -> usize { | ||
263 | self.0.len() | ||
264 | } | ||
265 | |||
266 | pub fn is_empty(&self, _: &Interner) -> bool { | ||
267 | self.0.is_empty() | ||
268 | } | ||
269 | |||
270 | pub fn at(&self, _: &Interner, i: usize) -> &GenericArg { | ||
271 | &self.0[i] | ||
272 | } | ||
273 | |||
274 | pub fn empty(_: &Interner) -> Substitution { | ||
275 | Substitution(SmallVec::new()) | ||
276 | } | ||
277 | |||
278 | pub fn iter(&self, _: &Interner) -> std::slice::Iter<'_, GenericArg> { | ||
279 | self.0.iter() | ||
280 | } | ||
281 | |||
282 | pub fn from_iter( | ||
283 | interner: &Interner, | ||
284 | elements: impl IntoIterator<Item = impl CastTo<GenericArg>>, | ||
285 | ) -> Self { | ||
286 | Substitution(elements.into_iter().casted(interner).collect()) | ||
287 | } | ||
288 | |||
289 | // We can hopefully add this to Chalk | ||
290 | pub fn intern(interned: SmallVec<[GenericArg; 2]>) -> Substitution { | ||
291 | Substitution(interned) | ||
292 | } | ||
293 | |||
294 | pub fn interned_mut(&mut self) -> &mut SmallVec<[GenericArg; 2]> { | ||
295 | &mut self.0 | ||
296 | } | ||
297 | } | ||
298 | |||
299 | #[derive(Copy, Clone, PartialEq, Eq, Debug, Hash)] | ||
300 | pub struct Binders<T> { | ||
301 | pub num_binders: usize, | ||
302 | pub value: T, | ||
303 | } | ||
304 | |||
305 | /// A trait with type parameters. This includes the `Self`, so this represents a concrete type implementing the trait. | ||
306 | #[derive(Clone, PartialEq, Eq, Debug, Hash)] | ||
307 | pub struct TraitRef { | ||
308 | pub trait_id: ChalkTraitId, | ||
309 | pub substitution: Substitution, | ||
310 | } | ||
311 | |||
312 | /// Like `generics::WherePredicate`, but with resolved types: A condition on the | ||
313 | /// parameters of a generic item. | ||
314 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] | ||
315 | pub enum WhereClause { | ||
316 | /// The given trait needs to be implemented for its type parameters. | ||
317 | Implemented(TraitRef), | ||
318 | /// An associated type bindings like in `Iterator<Item = T>`. | ||
319 | AliasEq(AliasEq), | ||
320 | } | ||
321 | |||
322 | pub type QuantifiedWhereClause = Binders<WhereClause>; | ||
323 | |||
324 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] | ||
325 | pub struct QuantifiedWhereClauses(Arc<[QuantifiedWhereClause]>); | ||
326 | |||
327 | impl QuantifiedWhereClauses { | ||
328 | pub fn from_iter( | ||
329 | _interner: &Interner, | ||
330 | elements: impl IntoIterator<Item = QuantifiedWhereClause>, | ||
331 | ) -> Self { | ||
332 | QuantifiedWhereClauses(elements.into_iter().collect()) | ||
333 | } | ||
334 | |||
335 | pub fn interned(&self) -> &Arc<[QuantifiedWhereClause]> { | ||
336 | &self.0 | ||
337 | } | ||
338 | |||
339 | pub fn interned_mut(&mut self) -> &mut Arc<[QuantifiedWhereClause]> { | ||
340 | &mut self.0 | ||
341 | } | ||
342 | } | ||
343 | |||
344 | /// Basically a claim (currently not validated / checked) that the contained | ||
345 | /// type / trait ref contains no inference variables; any inference variables it | ||
346 | /// contained have been replaced by bound variables, and `kinds` tells us how | ||
347 | /// many there are and whether they were normal or float/int variables. This is | ||
348 | /// used to erase irrelevant differences between types before using them in | ||
349 | /// queries. | ||
350 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] | ||
351 | pub struct Canonical<T> { | ||
352 | pub value: T, | ||
353 | pub binders: CanonicalVarKinds, | ||
354 | } | ||
355 | |||
356 | /// Something (usually a goal), along with an environment. | ||
357 | #[derive(Clone, Debug, PartialEq, Eq, Hash)] | ||
358 | pub struct InEnvironment<T> { | ||
359 | pub environment: chalk_ir::Environment<Interner>, | ||
360 | pub goal: T, | ||
361 | } | ||
362 | |||
363 | impl<T> InEnvironment<T> { | ||
364 | pub fn new(environment: chalk_ir::Environment<Interner>, value: T) -> InEnvironment<T> { | ||
365 | InEnvironment { environment, goal: value } | ||
366 | } | ||
367 | } | ||
368 | |||
369 | /// Something that needs to be proven (by Chalk) during type checking, e.g. that | ||
370 | /// a certain type implements a certain trait. Proving the Obligation might | ||
371 | /// result in additional information about inference variables. | ||
372 | #[derive(Clone, Debug, PartialEq, Eq, Hash)] | ||
373 | pub enum DomainGoal { | ||
374 | Holds(WhereClause), | ||
375 | } | ||
376 | |||
377 | #[derive(Clone, Debug, PartialEq, Eq, Hash)] | ||
378 | pub struct AliasEq { | ||
379 | pub alias: AliasTy, | ||
380 | pub ty: Ty, | ||
381 | } | ||
382 | |||
383 | #[derive(Clone, Debug, PartialEq, Eq)] | ||
384 | pub struct SolutionVariables(pub Canonical<Substitution>); | ||
385 | |||
386 | #[derive(Clone, Debug, PartialEq, Eq)] | ||
387 | /// A (possible) solution for a proposed goal. | ||
388 | pub enum Solution { | ||
389 | /// The goal indeed holds, and there is a unique value for all existential | ||
390 | /// variables. | ||
391 | Unique(SolutionVariables), | ||
392 | |||
393 | /// The goal may be provable in multiple ways, but regardless we may have some guidance | ||
394 | /// for type inference. In this case, we don't return any lifetime | ||
395 | /// constraints, since we have not "committed" to any particular solution | ||
396 | /// yet. | ||
397 | Ambig(Guidance), | ||
398 | } | ||
399 | |||
400 | #[derive(Clone, Debug, PartialEq, Eq)] | ||
401 | /// When a goal holds ambiguously (e.g., because there are multiple possible | ||
402 | /// solutions), we issue a set of *guidance* back to type inference. | ||
403 | pub enum Guidance { | ||
404 | /// The existential variables *must* have the given values if the goal is | ||
405 | /// ever to hold, but that alone isn't enough to guarantee the goal will | ||
406 | /// actually hold. | ||
407 | Definite(SolutionVariables), | ||
408 | |||
409 | /// There are multiple plausible values for the existentials, but the ones | ||
410 | /// here are suggested as the preferred choice heuristically. These should | ||
411 | /// be used for inference fallback only. | ||
412 | Suggested(SolutionVariables), | ||
413 | |||
414 | /// There's no useful information to feed back to type inference | ||
415 | Unknown, | ||
416 | } | ||