rustc_type_ir/lib.rs
1// tidy-alphabetical-start
2#![allow(rustc::usage_of_ty_tykind)]
3#![allow(rustc::usage_of_type_ir_inherent)]
4#![cfg_attr(
5 feature = "nightly",
6 feature(associated_type_defaults, never_type, rustc_attrs, negative_impls)
7)]
8#![cfg_attr(feature = "nightly", allow(internal_features))]
9#![warn(unreachable_pub)]
10// tidy-alphabetical-end
11
12extern crate self as rustc_type_ir;
13
14use std::fmt;
15use std::hash::Hash;
16
17#[cfg(feature = "nightly")]
18use rustc_macros::{Decodable, Encodable, HashStable_NoContext};
19
20// These modules are `pub` since they are not glob-imported.
21#[macro_use]
22pub mod visit;
23#[cfg(feature = "nightly")]
24pub mod codec;
25pub mod data_structures;
26pub mod elaborate;
27pub mod error;
28pub mod fast_reject;
29pub mod fold;
30#[cfg_attr(feature = "nightly", rustc_diagnostic_item = "type_ir_inherent")]
31pub mod inherent;
32pub mod ir_print;
33pub mod lang_items;
34pub mod lift;
35pub mod outlives;
36pub mod relate;
37pub mod search_graph;
38pub mod solve;
39
40// These modules are not `pub` since they are glob-imported.
41#[macro_use]
42mod macros;
43mod binder;
44mod canonical;
45mod const_kind;
46mod flags;
47mod generic_arg;
48mod infer_ctxt;
49mod interner;
50mod opaque_ty;
51mod predicate;
52mod predicate_kind;
53mod region_kind;
54mod ty_info;
55mod ty_kind;
56mod upcast;
57
58pub use AliasTyKind::*;
59pub use DynKind::*;
60pub use InferTy::*;
61pub use RegionKind::*;
62pub use TyKind::*;
63pub use Variance::*;
64pub use binder::*;
65pub use canonical::*;
66#[cfg(feature = "nightly")]
67pub use codec::*;
68pub use const_kind::*;
69pub use flags::*;
70pub use generic_arg::*;
71pub use infer_ctxt::*;
72pub use interner::*;
73pub use opaque_ty::*;
74pub use predicate::*;
75pub use predicate_kind::*;
76pub use region_kind::*;
77pub use ty_info::*;
78pub use ty_kind::*;
79pub use upcast::*;
80
81rustc_index::newtype_index! {
82 /// A [De Bruijn index][dbi] is a standard means of representing
83 /// regions (and perhaps later types) in a higher-ranked setting. In
84 /// particular, imagine a type like this:
85 /// ```ignore (illustrative)
86 /// for<'a> fn(for<'b> fn(&'b isize, &'a isize), &'a char)
87 /// // ^ ^ | | |
88 /// // | | | | |
89 /// // | +------------+ 0 | |
90 /// // | | |
91 /// // +----------------------------------+ 1 |
92 /// // | |
93 /// // +----------------------------------------------+ 0
94 /// ```
95 /// In this type, there are two binders (the outer fn and the inner
96 /// fn). We need to be able to determine, for any given region, which
97 /// fn type it is bound by, the inner or the outer one. There are
98 /// various ways you can do this, but a De Bruijn index is one of the
99 /// more convenient and has some nice properties. The basic idea is to
100 /// count the number of binders, inside out. Some examples should help
101 /// clarify what I mean.
102 ///
103 /// Let's start with the reference type `&'b isize` that is the first
104 /// argument to the inner function. This region `'b` is assigned a De
105 /// Bruijn index of 0, meaning "the innermost binder" (in this case, a
106 /// fn). The region `'a` that appears in the second argument type (`&'a
107 /// isize`) would then be assigned a De Bruijn index of 1, meaning "the
108 /// second-innermost binder". (These indices are written on the arrows
109 /// in the diagram).
110 ///
111 /// What is interesting is that De Bruijn index attached to a particular
112 /// variable will vary depending on where it appears. For example,
113 /// the final type `&'a char` also refers to the region `'a` declared on
114 /// the outermost fn. But this time, this reference is not nested within
115 /// any other binders (i.e., it is not an argument to the inner fn, but
116 /// rather the outer one). Therefore, in this case, it is assigned a
117 /// De Bruijn index of 0, because the innermost binder in that location
118 /// is the outer fn.
119 ///
120 /// [dbi]: https://en.wikipedia.org/wiki/De_Bruijn_index
121 #[cfg_attr(feature = "nightly", derive(HashStable_NoContext))]
122 #[encodable]
123 #[orderable]
124 #[debug_format = "DebruijnIndex({})"]
125 #[gate_rustc_only]
126 pub struct DebruijnIndex {
127 const INNERMOST = 0;
128 }
129}
130
131impl DebruijnIndex {
132 /// Returns the resulting index when this value is moved into
133 /// `amount` number of new binders. So, e.g., if you had
134 ///
135 /// for<'a> fn(&'a x)
136 ///
137 /// and you wanted to change it to
138 ///
139 /// for<'a> fn(for<'b> fn(&'a x))
140 ///
141 /// you would need to shift the index for `'a` into a new binder.
142 #[inline]
143 #[must_use]
144 pub fn shifted_in(self, amount: u32) -> DebruijnIndex {
145 DebruijnIndex::from_u32(self.as_u32() + amount)
146 }
147
148 /// Update this index in place by shifting it "in" through
149 /// `amount` number of binders.
150 #[inline]
151 pub fn shift_in(&mut self, amount: u32) {
152 *self = self.shifted_in(amount);
153 }
154
155 /// Returns the resulting index when this value is moved out from
156 /// `amount` number of new binders.
157 #[inline]
158 #[must_use]
159 pub fn shifted_out(self, amount: u32) -> DebruijnIndex {
160 DebruijnIndex::from_u32(self.as_u32() - amount)
161 }
162
163 /// Update in place by shifting out from `amount` binders.
164 #[inline]
165 pub fn shift_out(&mut self, amount: u32) {
166 *self = self.shifted_out(amount);
167 }
168
169 /// Adjusts any De Bruijn indices so as to make `to_binder` the
170 /// innermost binder. That is, if we have something bound at `to_binder`,
171 /// it will now be bound at INNERMOST. This is an appropriate thing to do
172 /// when moving a region out from inside binders:
173 ///
174 /// ```ignore (illustrative)
175 /// for<'a> fn(for<'b> for<'c> fn(&'a u32), _)
176 /// // Binder: D3 D2 D1 ^^
177 /// ```
178 ///
179 /// Here, the region `'a` would have the De Bruijn index D3,
180 /// because it is the bound 3 binders out. However, if we wanted
181 /// to refer to that region `'a` in the second argument (the `_`),
182 /// those two binders would not be in scope. In that case, we
183 /// might invoke `shift_out_to_binder(D3)`. This would adjust the
184 /// De Bruijn index of `'a` to D1 (the innermost binder).
185 ///
186 /// If we invoke `shift_out_to_binder` and the region is in fact
187 /// bound by one of the binders we are shifting out of, that is an
188 /// error (and should fail an assertion failure).
189 #[inline]
190 pub fn shifted_out_to_binder(self, to_binder: DebruijnIndex) -> Self {
191 self.shifted_out(to_binder.as_u32() - INNERMOST.as_u32())
192 }
193}
194
195pub fn debug_bound_var<T: std::fmt::Write>(
196 fmt: &mut T,
197 debruijn: DebruijnIndex,
198 var: impl std::fmt::Debug,
199) -> Result<(), std::fmt::Error> {
200 if debruijn == INNERMOST {
201 write!(fmt, "^{var:?}")
202 } else {
203 write!(fmt, "^{}_{:?}", debruijn.index(), var)
204 }
205}
206
207#[derive(Copy, Clone, PartialEq, Eq, Hash)]
208#[cfg_attr(feature = "nightly", derive(Decodable, Encodable, HashStable_NoContext))]
209#[cfg_attr(feature = "nightly", rustc_pass_by_value)]
210pub enum Variance {
211 Covariant, // T<A> <: T<B> iff A <: B -- e.g., function return type
212 Invariant, // T<A> <: T<B> iff B == A -- e.g., type of mutable cell
213 Contravariant, // T<A> <: T<B> iff B <: A -- e.g., function param type
214 Bivariant, // T<A> <: T<B> -- e.g., unused type parameter
215}
216
217impl Variance {
218 /// `a.xform(b)` combines the variance of a context with the
219 /// variance of a type with the following meaning. If we are in a
220 /// context with variance `a`, and we encounter a type argument in
221 /// a position with variance `b`, then `a.xform(b)` is the new
222 /// variance with which the argument appears.
223 ///
224 /// Example 1:
225 /// ```ignore (illustrative)
226 /// *mut Vec<i32>
227 /// ```
228 /// Here, the "ambient" variance starts as covariant. `*mut T` is
229 /// invariant with respect to `T`, so the variance in which the
230 /// `Vec<i32>` appears is `Covariant.xform(Invariant)`, which
231 /// yields `Invariant`. Now, the type `Vec<T>` is covariant with
232 /// respect to its type argument `T`, and hence the variance of
233 /// the `i32` here is `Invariant.xform(Covariant)`, which results
234 /// (again) in `Invariant`.
235 ///
236 /// Example 2:
237 /// ```ignore (illustrative)
238 /// fn(*const Vec<i32>, *mut Vec<i32)
239 /// ```
240 /// The ambient variance is covariant. A `fn` type is
241 /// contravariant with respect to its parameters, so the variance
242 /// within which both pointer types appear is
243 /// `Covariant.xform(Contravariant)`, or `Contravariant`. `*const
244 /// T` is covariant with respect to `T`, so the variance within
245 /// which the first `Vec<i32>` appears is
246 /// `Contravariant.xform(Covariant)` or `Contravariant`. The same
247 /// is true for its `i32` argument. In the `*mut T` case, the
248 /// variance of `Vec<i32>` is `Contravariant.xform(Invariant)`,
249 /// and hence the outermost type is `Invariant` with respect to
250 /// `Vec<i32>` (and its `i32` argument).
251 ///
252 /// Source: Figure 1 of "Taming the Wildcards:
253 /// Combining Definition- and Use-Site Variance" published in PLDI'11.
254 pub fn xform(self, v: Variance) -> Variance {
255 match (self, v) {
256 // Figure 1, column 1.
257 (Variance::Covariant, Variance::Covariant) => Variance::Covariant,
258 (Variance::Covariant, Variance::Contravariant) => Variance::Contravariant,
259 (Variance::Covariant, Variance::Invariant) => Variance::Invariant,
260 (Variance::Covariant, Variance::Bivariant) => Variance::Bivariant,
261
262 // Figure 1, column 2.
263 (Variance::Contravariant, Variance::Covariant) => Variance::Contravariant,
264 (Variance::Contravariant, Variance::Contravariant) => Variance::Covariant,
265 (Variance::Contravariant, Variance::Invariant) => Variance::Invariant,
266 (Variance::Contravariant, Variance::Bivariant) => Variance::Bivariant,
267
268 // Figure 1, column 3.
269 (Variance::Invariant, _) => Variance::Invariant,
270
271 // Figure 1, column 4.
272 (Variance::Bivariant, _) => Variance::Bivariant,
273 }
274 }
275}
276
277impl fmt::Debug for Variance {
278 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
279 f.write_str(match *self {
280 Variance::Covariant => "+",
281 Variance::Contravariant => "-",
282 Variance::Invariant => "o",
283 Variance::Bivariant => "*",
284 })
285 }
286}
287
288rustc_index::newtype_index! {
289 /// "Universes" are used during type- and trait-checking in the
290 /// presence of `for<..>` binders to control what sets of names are
291 /// visible. Universes are arranged into a tree: the root universe
292 /// contains names that are always visible. Each child then adds a new
293 /// set of names that are visible, in addition to those of its parent.
294 /// We say that the child universe "extends" the parent universe with
295 /// new names.
296 ///
297 /// To make this more concrete, consider this program:
298 ///
299 /// ```ignore (illustrative)
300 /// struct Foo { }
301 /// fn bar<T>(x: T) {
302 /// let y: for<'a> fn(&'a u8, Foo) = ...;
303 /// }
304 /// ```
305 ///
306 /// The struct name `Foo` is in the root universe U0. But the type
307 /// parameter `T`, introduced on `bar`, is in an extended universe U1
308 /// -- i.e., within `bar`, we can name both `T` and `Foo`, but outside
309 /// of `bar`, we cannot name `T`. Then, within the type of `y`, the
310 /// region `'a` is in a universe U2 that extends U1, because we can
311 /// name it inside the fn type but not outside.
312 ///
313 /// Universes are used to do type- and trait-checking around these
314 /// "forall" binders (also called **universal quantification**). The
315 /// idea is that when, in the body of `bar`, we refer to `T` as a
316 /// type, we aren't referring to any type in particular, but rather a
317 /// kind of "fresh" type that is distinct from all other types we have
318 /// actually declared. This is called a **placeholder** type, and we
319 /// use universes to talk about this. In other words, a type name in
320 /// universe 0 always corresponds to some "ground" type that the user
321 /// declared, but a type name in a non-zero universe is a placeholder
322 /// type -- an idealized representative of "types in general" that we
323 /// use for checking generic functions.
324 #[cfg_attr(feature = "nightly", derive(HashStable_NoContext))]
325 #[encodable]
326 #[orderable]
327 #[debug_format = "U{}"]
328 #[gate_rustc_only]
329 pub struct UniverseIndex {}
330}
331
332impl UniverseIndex {
333 pub const ROOT: UniverseIndex = UniverseIndex::ZERO;
334
335 /// Returns the "next" universe index in order -- this new index
336 /// is considered to extend all previous universes. This
337 /// corresponds to entering a `forall` quantifier. So, for
338 /// example, suppose we have this type in universe `U`:
339 ///
340 /// ```ignore (illustrative)
341 /// for<'a> fn(&'a u32)
342 /// ```
343 ///
344 /// Once we "enter" into this `for<'a>` quantifier, we are in a
345 /// new universe that extends `U` -- in this new universe, we can
346 /// name the region `'a`, but that region was not nameable from
347 /// `U` because it was not in scope there.
348 pub fn next_universe(self) -> UniverseIndex {
349 UniverseIndex::from_u32(self.as_u32().checked_add(1).unwrap())
350 }
351
352 /// Returns `true` if `self` can name a name from `other` -- in other words,
353 /// if the set of names in `self` is a superset of those in
354 /// `other` (`self >= other`).
355 pub fn can_name(self, other: UniverseIndex) -> bool {
356 self >= other
357 }
358
359 /// Returns `true` if `self` cannot name some names from `other` -- in other
360 /// words, if the set of names in `self` is a strict subset of
361 /// those in `other` (`self < other`).
362 pub fn cannot_name(self, other: UniverseIndex) -> bool {
363 self < other
364 }
365
366 /// Returns `true` if `self` is the root universe, otherwise false.
367 pub fn is_root(self) -> bool {
368 self == Self::ROOT
369 }
370}
371
372impl Default for UniverseIndex {
373 fn default() -> Self {
374 Self::ROOT
375 }
376}
377
378rustc_index::newtype_index! {
379 #[cfg_attr(feature = "nightly", derive(HashStable_NoContext))]
380 #[encodable]
381 #[orderable]
382 #[debug_format = "{}"]
383 #[gate_rustc_only]
384 pub struct BoundVar {}
385}
386
387impl<I: Interner> inherent::BoundVarLike<I> for BoundVar {
388 fn var(self) -> BoundVar {
389 self
390 }
391
392 fn assert_eq(self, _var: I::BoundVarKind) {
393 unreachable!("FIXME: We really should have a separate `BoundConst` for consts")
394 }
395}
396
397/// Represents the various closure traits in the language. This
398/// will determine the type of the environment (`self`, in the
399/// desugaring) argument that the closure expects.
400///
401/// You can get the environment type of a closure using
402/// `tcx.closure_env_ty()`.
403#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
404#[cfg_attr(feature = "nightly", derive(Encodable, Decodable, HashStable_NoContext))]
405pub enum ClosureKind {
406 Fn,
407 FnMut,
408 FnOnce,
409}
410
411impl ClosureKind {
412 /// This is the initial value used when doing upvar inference.
413 pub const LATTICE_BOTTOM: ClosureKind = ClosureKind::Fn;
414
415 pub const fn as_str(self) -> &'static str {
416 match self {
417 ClosureKind::Fn => "Fn",
418 ClosureKind::FnMut => "FnMut",
419 ClosureKind::FnOnce => "FnOnce",
420 }
421 }
422
423 /// Returns `true` if a type that impls this closure kind
424 /// must also implement `other`.
425 #[rustfmt::skip]
426 pub fn extends(self, other: ClosureKind) -> bool {
427 use ClosureKind::*;
428 match (self, other) {
429 (Fn, Fn | FnMut | FnOnce)
430 | (FnMut, FnMut | FnOnce)
431 | (FnOnce, FnOnce) => true,
432 _ => false,
433 }
434 }
435}
436
437impl fmt::Display for ClosureKind {
438 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
439 self.as_str().fmt(f)
440 }
441}