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