aboutsummaryrefslogtreecommitdiff
path: root/crates/hir_ty/src/types.rs
diff options
context:
space:
mode:
Diffstat (limited to 'crates/hir_ty/src/types.rs')
-rw-r--r--crates/hir_ty/src/types.rs416
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
4use std::sync::Arc;
5
6use chalk_ir::{
7 cast::{CastTo, Caster},
8 BoundVar, Mutability, Scalar, TyVariableKind,
9};
10use hir_def::LifetimeParamId;
11use smallvec::SmallVec;
12
13use crate::{
14 AssocTypeId, CanonicalVarKinds, ChalkTraitId, ClosureId, FnDefId, FnSig, ForeignDefId,
15 InferenceVar, Interner, OpaqueTyId, PlaceholderIndex,
16};
17
18#[derive(Clone, PartialEq, Eq, Debug, Hash)]
19pub enum Lifetime {
20 Parameter(LifetimeParamId),
21 Static,
22}
23
24#[derive(Clone, PartialEq, Eq, Debug, Hash)]
25pub 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)]
34pub struct ProjectionTy {
35 pub associated_ty_id: AssocTypeId,
36 pub substitution: Substitution,
37}
38
39#[derive(Clone, PartialEq, Eq, Debug, Hash)]
40pub struct DynTy {
41 /// The unknown self type.
42 pub bounds: Binders<QuantifiedWhereClauses>,
43}
44
45#[derive(Clone, PartialEq, Eq, Debug, Hash)]
46pub struct FnPointer {
47 pub num_args: usize,
48 pub sig: FnSig,
49 pub substs: Substitution,
50}
51
52#[derive(Clone, PartialEq, Eq, Debug, Hash)]
53pub 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)]
72pub 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)]
186pub struct Ty(Arc<TyKind>);
187
188impl TyKind {
189 pub fn intern(self, _interner: &Interner) -> Ty {
190 Ty(Arc::new(self))
191 }
192}
193
194impl 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)]
209pub struct GenericArg {
210 interned: GenericArgData,
211}
212
213#[derive(Clone, PartialEq, Eq, Debug, Hash)]
214pub enum GenericArgData {
215 Ty(Ty),
216}
217
218impl 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)]
255pub struct Substitution(SmallVec<[GenericArg; 2]>);
256
257impl 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)]
300pub 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)]
307pub 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)]
315pub 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
322pub type QuantifiedWhereClause = Binders<WhereClause>;
323
324#[derive(Debug, Clone, PartialEq, Eq, Hash)]
325pub struct QuantifiedWhereClauses(Arc<[QuantifiedWhereClause]>);
326
327impl 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)]
351pub 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)]
358pub struct InEnvironment<T> {
359 pub environment: chalk_ir::Environment<Interner>,
360 pub goal: T,
361}
362
363impl<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)]
373pub enum DomainGoal {
374 Holds(WhereClause),
375}
376
377#[derive(Clone, Debug, PartialEq, Eq, Hash)]
378pub struct AliasEq {
379 pub alias: AliasTy,
380 pub ty: Ty,
381}
382
383#[derive(Clone, Debug, PartialEq, Eq)]
384pub struct SolutionVariables(pub Canonical<Substitution>);
385
386#[derive(Clone, Debug, PartialEq, Eq)]
387/// A (possible) solution for a proposed goal.
388pub 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.
403pub 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}