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