Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit 6f43680

Browse files
committedOct 17, 2023
Begin to abstract rustc_type_ir for rust-analyzer
1 parent 49691b1 commit 6f43680

File tree

9 files changed

+337
-152
lines changed

9 files changed

+337
-152
lines changed
 

‎compiler/rustc_type_ir/Cargo.toml‎

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,19 @@ edition = "2021"
77

88
[dependencies]
99
bitflags = "1.2.1"
10-
rustc_index = { path = "../rustc_index" }
11-
rustc_serialize = { path = "../rustc_serialize" }
12-
rustc_data_structures = { path = "../rustc_data_structures" }
13-
rustc_macros = { path = "../rustc_macros" }
14-
smallvec = { version = "1.8.1", features = ["union", "may_dangle"] }
10+
rustc_index = { path = "../rustc_index", default-features = false }
11+
rustc_serialize = { path = "../rustc_serialize", optional = true }
12+
rustc_data_structures = { path = "../rustc_data_structures", optional = true }
13+
rustc_macros = { path = "../rustc_macros", optional = true }
14+
smallvec = { version = "1.8.1" }
15+
16+
[features]
17+
default = ["nightly"]
18+
nightly = [
19+
"smallvec/may_dangle",
20+
"smallvec/union",
21+
"rustc_index/nightly",
22+
"rustc_serialize",
23+
"rustc_data_structures",
24+
"rustc_macros"
25+
]

‎compiler/rustc_type_ir/src/fold.rs‎

Lines changed: 21 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,12 @@
4646
//! ```
4747
use crate::{visit::TypeVisitable, Interner};
4848

49+
#[cfg(feature = "nightly")]
50+
type Never = !;
51+
52+
#[cfg(not(feature = "nightly"))]
53+
type Never = std::convert::Infallible;
54+
4955
/// This trait is implemented for every type that can be folded,
5056
/// providing the skeleton of the traversal.
5157
///
@@ -74,7 +80,10 @@ pub trait TypeFoldable<I: Interner>: TypeVisitable<I> {
7480
/// folders. Do not override this method, to ensure coherence with
7581
/// `try_fold_with`.
7682
fn fold_with<F: TypeFolder<I>>(self, folder: &mut F) -> Self {
77-
self.try_fold_with(folder).into_ok()
83+
match self.try_fold_with(folder) {
84+
Ok(t) => t,
85+
Err(_) => unreachable!(),
86+
}
7887
}
7988
}
8089

@@ -95,7 +104,10 @@ pub trait TypeSuperFoldable<I: Interner>: TypeFoldable<I> {
95104
/// infallible folders. Do not override this method, to ensure coherence
96105
/// with `try_super_fold_with`.
97106
fn super_fold_with<F: TypeFolder<I>>(self, folder: &mut F) -> Self {
98-
self.try_super_fold_with(folder).into_ok()
107+
match self.try_super_fold_with(folder) {
108+
Ok(t) => t,
109+
Err(_) => unreachable!(),
110+
}
99111
}
100112
}
101113

@@ -108,7 +120,7 @@ pub trait TypeSuperFoldable<I: Interner>: TypeFoldable<I> {
108120
/// A blanket implementation of [`FallibleTypeFolder`] will defer to
109121
/// the infallible methods of this trait to ensure that the two APIs
110122
/// are coherent.
111-
pub trait TypeFolder<I: Interner>: FallibleTypeFolder<I, Error = !> {
123+
pub trait TypeFolder<I: Interner>: FallibleTypeFolder<I, Error = Never> {
112124
fn interner(&self) -> I;
113125

114126
fn fold_binder<T>(&mut self, t: I::Binder<T>) -> I::Binder<T>
@@ -203,39 +215,39 @@ impl<I: Interner, F> FallibleTypeFolder<I> for F
203215
where
204216
F: TypeFolder<I>,
205217
{
206-
type Error = !;
218+
type Error = Never;
207219

208220
fn interner(&self) -> I {
209221
TypeFolder::interner(self)
210222
}
211223

212-
fn try_fold_binder<T>(&mut self, t: I::Binder<T>) -> Result<I::Binder<T>, !>
224+
fn try_fold_binder<T>(&mut self, t: I::Binder<T>) -> Result<I::Binder<T>, Never>
213225
where
214226
T: TypeFoldable<I>,
215227
I::Binder<T>: TypeSuperFoldable<I>,
216228
{
217229
Ok(self.fold_binder(t))
218230
}
219231

220-
fn try_fold_ty(&mut self, t: I::Ty) -> Result<I::Ty, !>
232+
fn try_fold_ty(&mut self, t: I::Ty) -> Result<I::Ty, Never>
221233
where
222234
I::Ty: TypeSuperFoldable<I>,
223235
{
224236
Ok(self.fold_ty(t))
225237
}
226238

227-
fn try_fold_region(&mut self, r: I::Region) -> Result<I::Region, !> {
239+
fn try_fold_region(&mut self, r: I::Region) -> Result<I::Region, Never> {
228240
Ok(self.fold_region(r))
229241
}
230242

231-
fn try_fold_const(&mut self, c: I::Const) -> Result<I::Const, !>
243+
fn try_fold_const(&mut self, c: I::Const) -> Result<I::Const, Never>
232244
where
233245
I::Const: TypeSuperFoldable<I>,
234246
{
235247
Ok(self.fold_const(c))
236248
}
237249

238-
fn try_fold_predicate(&mut self, p: I::Predicate) -> Result<I::Predicate, !>
250+
fn try_fold_predicate(&mut self, p: I::Predicate) -> Result<I::Predicate, Never>
239251
where
240252
I::Predicate: TypeSuperFoldable<I>,
241253
{
Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
#[derive(Copy, Clone, Hash, Eq, PartialEq, Ord, PartialOrd, Debug)]
2+
pub struct DebruijnIndex {
3+
pub(crate) private: u32,
4+
}
5+
6+
impl DebruijnIndex {
7+
pub const fn from_u32(u: u32) -> Self {
8+
Self { private: u }
9+
}
10+
11+
pub const fn as_u32(self) -> u32 {
12+
self.private
13+
}
14+
}
15+
16+
pub const INNERMOST: DebruijnIndex = DebruijnIndex { private: 0 };
17+
18+
#[derive(Copy, Clone, Hash, Eq, PartialEq, Ord, PartialOrd, Debug)]
19+
pub struct UniverseIndex {
20+
pub(crate) private: u32,
21+
}
22+
23+
impl UniverseIndex {
24+
pub const fn from_u32(u: u32) -> Self {
25+
Self { private: u }
26+
}
27+
28+
pub const fn as_u32(self) -> u32 {
29+
self.private
30+
}
31+
}
32+
33+
#[derive(Copy, Clone, Hash, Eq, PartialEq, Ord, PartialOrd, Debug)]
34+
pub struct TyVid {
35+
pub(crate) private: u32,
36+
}
37+
38+
impl TyVid {
39+
pub const fn from_u32(u: u32) -> Self {
40+
Self { private: u }
41+
}
42+
43+
pub const fn as_u32(self) -> u32 {
44+
self.private
45+
}
46+
}
47+
48+
#[derive(Copy, Clone, Hash, Eq, PartialEq, Ord, PartialOrd, Debug)]
49+
pub struct FloatVid {
50+
pub(crate) private: u32,
51+
}
52+
53+
impl FloatVid {
54+
pub const fn from_u32(u: u32) -> Self {
55+
Self { private: u }
56+
}
57+
58+
pub const fn as_u32(self) -> u32 {
59+
self.private
60+
}
61+
}
62+
63+
#[derive(Copy, Clone, Hash, Eq, PartialEq, Ord, PartialOrd, Debug)]
64+
pub struct IntVid {
65+
pub(crate) private: u32,
66+
}
67+
68+
impl IntVid {
69+
pub const fn from_u32(u: u32) -> Self {
70+
Self { private: u }
71+
}
72+
73+
pub const fn as_u32(self) -> u32 {
74+
self.private
75+
}
76+
}
Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
rustc_index::newtype_index! {
2+
/// A [De Bruijn index][dbi] is a standard means of representing
3+
/// regions (and perhaps later types) in a higher-ranked setting. In
4+
/// particular, imagine a type like this:
5+
/// ```ignore (illustrative)
6+
/// for<'a> fn(for<'b> fn(&'b isize, &'a isize), &'a char)
7+
/// // ^ ^ | | |
8+
/// // | | | | |
9+
/// // | +------------+ 0 | |
10+
/// // | | |
11+
/// // +----------------------------------+ 1 |
12+
/// // | |
13+
/// // +----------------------------------------------+ 0
14+
/// ```
15+
/// In this type, there are two binders (the outer fn and the inner
16+
/// fn). We need to be able to determine, for any given region, which
17+
/// fn type it is bound by, the inner or the outer one. There are
18+
/// various ways you can do this, but a De Bruijn index is one of the
19+
/// more convenient and has some nice properties. The basic idea is to
20+
/// count the number of binders, inside out. Some examples should help
21+
/// clarify what I mean.
22+
///
23+
/// Let's start with the reference type `&'b isize` that is the first
24+
/// argument to the inner function. This region `'b` is assigned a De
25+
/// Bruijn index of 0, meaning "the innermost binder" (in this case, a
26+
/// fn). The region `'a` that appears in the second argument type (`&'a
27+
/// isize`) would then be assigned a De Bruijn index of 1, meaning "the
28+
/// second-innermost binder". (These indices are written on the arrows
29+
/// in the diagram).
30+
///
31+
/// What is interesting is that De Bruijn index attached to a particular
32+
/// variable will vary depending on where it appears. For example,
33+
/// the final type `&'a char` also refers to the region `'a` declared on
34+
/// the outermost fn. But this time, this reference is not nested within
35+
/// any other binders (i.e., it is not an argument to the inner fn, but
36+
/// rather the outer one). Therefore, in this case, it is assigned a
37+
/// De Bruijn index of 0, because the innermost binder in that location
38+
/// is the outer fn.
39+
///
40+
/// [dbi]: https://en.wikipedia.org/wiki/De_Bruijn_index
41+
#[derive(HashStable_Generic)]
42+
#[debug_format = "DebruijnIndex({})"]
43+
pub struct DebruijnIndex {
44+
const INNERMOST = 0;
45+
}
46+
}
47+
48+
rustc_index::newtype_index! {
49+
/// A **ty**pe **v**ariable **ID**.
50+
#[debug_format = "?{}t"]
51+
pub struct TyVid {}
52+
}
53+
54+
rustc_index::newtype_index! {
55+
/// An **int**egral (`u32`, `i32`, `usize`, etc.) type **v**ariable **ID**.
56+
#[debug_format = "?{}i"]
57+
pub struct IntVid {}
58+
}
59+
60+
rustc_index::newtype_index! {
61+
/// A **float**ing-point (`f32` or `f64`) type **v**ariable **ID**.
62+
#[debug_format = "?{}f"]
63+
pub struct FloatVid {}
64+
}
65+
66+
rustc_index::newtype_index! {
67+
/// "Universes" are used during type- and trait-checking in the
68+
/// presence of `for<..>` binders to control what sets of names are
69+
/// visible. Universes are arranged into a tree: the root universe
70+
/// contains names that are always visible. Each child then adds a new
71+
/// set of names that are visible, in addition to those of its parent.
72+
/// We say that the child universe "extends" the parent universe with
73+
/// new names.
74+
///
75+
/// To make this more concrete, consider this program:
76+
///
77+
/// ```ignore (illustrative)
78+
/// struct Foo { }
79+
/// fn bar<T>(x: T) {
80+
/// let y: for<'a> fn(&'a u8, Foo) = ...;
81+
/// }
82+
/// ```
83+
///
84+
/// The struct name `Foo` is in the root universe U0. But the type
85+
/// parameter `T`, introduced on `bar`, is in an extended universe U1
86+
/// -- i.e., within `bar`, we can name both `T` and `Foo`, but outside
87+
/// of `bar`, we cannot name `T`. Then, within the type of `y`, the
88+
/// region `'a` is in a universe U2 that extends U1, because we can
89+
/// name it inside the fn type but not outside.
90+
///
91+
/// Universes are used to do type- and trait-checking around these
92+
/// "forall" binders (also called **universal quantification**). The
93+
/// idea is that when, in the body of `bar`, we refer to `T` as a
94+
/// type, we aren't referring to any type in particular, but rather a
95+
/// kind of "fresh" type that is distinct from all other types we have
96+
/// actually declared. This is called a **placeholder** type, and we
97+
/// use universes to talk about this. In other words, a type name in
98+
/// universe 0 always corresponds to some "ground" type that the user
99+
/// declared, but a type name in a non-zero universe is a placeholder
100+
/// type -- an idealized representative of "types in general" that we
101+
/// use for checking generic functions.
102+
#[derive(HashStable_Generic)]
103+
#[debug_format = "U{}"]
104+
pub struct UniverseIndex {}
105+
}

‎compiler/rustc_type_ir/src/lib.rs‎

Lines changed: 44 additions & 123 deletions
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,46 @@
1-
#![feature(associated_type_defaults)]
2-
#![feature(fmt_helpers_for_derive)]
3-
#![feature(min_specialization)]
4-
#![feature(never_type)]
5-
#![feature(rustc_attrs)]
6-
#![feature(unwrap_infallible)]
1+
#![cfg_attr(
2+
feature = "nightly",
3+
feature(
4+
associated_type_defaults,
5+
fmt_helpers_for_derive,
6+
min_specialization,
7+
never_type,
8+
rustc_attrs,
9+
unwrap_infallible
10+
)
11+
)]
712
#![deny(rustc::untranslatable_diagnostic)]
813
#![deny(rustc::diagnostic_outside_of_impl)]
9-
#![allow(internal_features)]
14+
#![cfg_attr(feature = "nightly", allow(internal_features))]
1015

1116
#[macro_use]
1217
extern crate bitflags;
18+
#[cfg(feature = "nightly")]
1319
#[macro_use]
1420
extern crate rustc_macros;
1521

22+
#[cfg(not(feature = "nightly"))]
23+
pub use index::*;
24+
#[cfg(feature = "nightly")]
25+
pub use index_nightly::*;
26+
#[cfg(feature = "nightly")]
1627
use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
28+
#[cfg(feature = "nightly")]
1729
use rustc_data_structures::unify::{EqUnifyValue, UnifyKey};
1830
use smallvec::SmallVec;
1931
use std::fmt;
2032
use std::fmt::Debug;
2133
use std::hash::Hash;
34+
#[cfg(feature = "nightly")]
2235
use std::mem::discriminant;
2336

37+
#[cfg(feature = "nightly")]
2438
pub mod codec;
2539
pub mod fold;
40+
#[cfg(not(feature = "nightly"))]
41+
mod index;
42+
#[cfg(feature = "nightly")]
43+
mod index_nightly;
2644
pub mod sty;
2745
pub mod ty_info;
2846
pub mod visit;
@@ -31,6 +49,7 @@ pub mod visit;
3149
mod macros;
3250
mod structural_impls;
3351

52+
#[cfg(feature = "nightly")]
3453
pub use codec::*;
3554
pub use structural_impls::{DebugWithInfcx, InferCtxtLike, OptWithInfcx};
3655
pub use sty::*;
@@ -302,53 +321,6 @@ bitflags! {
302321
}
303322
}
304323

305-
rustc_index::newtype_index! {
306-
/// A [De Bruijn index][dbi] is a standard means of representing
307-
/// regions (and perhaps later types) in a higher-ranked setting. In
308-
/// particular, imagine a type like this:
309-
/// ```ignore (illustrative)
310-
/// for<'a> fn(for<'b> fn(&'b isize, &'a isize), &'a char)
311-
/// // ^ ^ | | |
312-
/// // | | | | |
313-
/// // | +------------+ 0 | |
314-
/// // | | |
315-
/// // +----------------------------------+ 1 |
316-
/// // | |
317-
/// // +----------------------------------------------+ 0
318-
/// ```
319-
/// In this type, there are two binders (the outer fn and the inner
320-
/// fn). We need to be able to determine, for any given region, which
321-
/// fn type it is bound by, the inner or the outer one. There are
322-
/// various ways you can do this, but a De Bruijn index is one of the
323-
/// more convenient and has some nice properties. The basic idea is to
324-
/// count the number of binders, inside out. Some examples should help
325-
/// clarify what I mean.
326-
///
327-
/// Let's start with the reference type `&'b isize` that is the first
328-
/// argument to the inner function. This region `'b` is assigned a De
329-
/// Bruijn index of 0, meaning "the innermost binder" (in this case, a
330-
/// fn). The region `'a` that appears in the second argument type (`&'a
331-
/// isize`) would then be assigned a De Bruijn index of 1, meaning "the
332-
/// second-innermost binder". (These indices are written on the arrows
333-
/// in the diagram).
334-
///
335-
/// What is interesting is that De Bruijn index attached to a particular
336-
/// variable will vary depending on where it appears. For example,
337-
/// the final type `&'a char` also refers to the region `'a` declared on
338-
/// the outermost fn. But this time, this reference is not nested within
339-
/// any other binders (i.e., it is not an argument to the inner fn, but
340-
/// rather the outer one). Therefore, in this case, it is assigned a
341-
/// De Bruijn index of 0, because the innermost binder in that location
342-
/// is the outer fn.
343-
///
344-
/// [dbi]: https://en.wikipedia.org/wiki/De_Bruijn_index
345-
#[derive(HashStable_Generic)]
346-
#[debug_format = "DebruijnIndex({})"]
347-
pub struct DebruijnIndex {
348-
const INNERMOST = 0;
349-
}
350-
}
351-
352324
impl DebruijnIndex {
353325
/// Returns the resulting index when this value is moved into
354326
/// `amount` number of new binders. So, e.g., if you had
@@ -421,12 +393,12 @@ pub fn debug_bound_var<T: std::fmt::Write>(
421393
if debruijn == INNERMOST {
422394
write!(fmt, "^{var:?}")
423395
} else {
424-
write!(fmt, "^{}_{:?}", debruijn.index(), var)
396+
write!(fmt, "^{}_{:?}", debruijn.as_u32(), var)
425397
}
426398
}
427399

428400
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
429-
#[derive(Encodable, Decodable, HashStable_Generic)]
401+
#[cfg_attr(feature = "nightly", derive(Encodable, Decodable, HashStable_Generic))]
430402
pub enum IntTy {
431403
Isize,
432404
I8,
@@ -484,7 +456,7 @@ impl IntTy {
484456
}
485457

486458
#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Copy)]
487-
#[derive(Encodable, Decodable, HashStable_Generic)]
459+
#[cfg_attr(feature = "nightly", derive(Encodable, Decodable, HashStable_Generic))]
488460
pub enum UintTy {
489461
Usize,
490462
U8,
@@ -542,7 +514,7 @@ impl UintTy {
542514
}
543515

544516
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
545-
#[derive(Encodable, Decodable, HashStable_Generic)]
517+
#[cfg_attr(feature = "nightly", derive(Encodable, Decodable, HashStable_Generic))]
546518
pub enum FloatTy {
547519
F32,
548520
F64,
@@ -573,30 +545,13 @@ pub enum IntVarValue {
573545
#[derive(Clone, Copy, PartialEq, Eq)]
574546
pub struct FloatVarValue(pub FloatTy);
575547

576-
rustc_index::newtype_index! {
577-
/// A **ty**pe **v**ariable **ID**.
578-
#[debug_format = "?{}t"]
579-
pub struct TyVid {}
580-
}
581-
582-
rustc_index::newtype_index! {
583-
/// An **int**egral (`u32`, `i32`, `usize`, etc.) type **v**ariable **ID**.
584-
#[debug_format = "?{}i"]
585-
pub struct IntVid {}
586-
}
587-
588-
rustc_index::newtype_index! {
589-
/// A **float**ing-point (`f32` or `f64`) type **v**ariable **ID**.
590-
#[debug_format = "?{}f"]
591-
pub struct FloatVid {}
592-
}
593-
594548
/// A placeholder for a type that hasn't been inferred yet.
595549
///
596550
/// E.g., if we have an empty array (`[]`), then we create a fresh
597551
/// type variable for the element type since we won't know until it's
598552
/// used what the element type is supposed to be.
599-
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Encodable, Decodable)]
553+
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
554+
#[cfg_attr(feature = "nightly", derive(Encodable, Decodable))]
600555
pub enum InferTy {
601556
/// A type variable.
602557
TyVar(TyVid),
@@ -629,6 +584,7 @@ pub enum InferTy {
629584

630585
/// Raw `TyVid` are used as the unification key for `sub_relations`;
631586
/// they carry no values.
587+
#[cfg(feature = "nightly")]
632588
impl UnifyKey for TyVid {
633589
type Value = ();
634590
#[inline]
@@ -644,8 +600,10 @@ impl UnifyKey for TyVid {
644600
}
645601
}
646602

603+
#[cfg(feature = "nightly")]
647604
impl EqUnifyValue for IntVarValue {}
648605

606+
#[cfg(feature = "nightly")]
649607
impl UnifyKey for IntVid {
650608
type Value = Option<IntVarValue>;
651609
#[inline] // make this function eligible for inlining - it is quite hot.
@@ -661,8 +619,10 @@ impl UnifyKey for IntVid {
661619
}
662620
}
663621

622+
#[cfg(feature = "nightly")]
664623
impl EqUnifyValue for FloatVarValue {}
665624

625+
#[cfg(feature = "nightly")]
666626
impl UnifyKey for FloatVid {
667627
type Value = Option<FloatVarValue>;
668628
#[inline]
@@ -678,8 +638,9 @@ impl UnifyKey for FloatVid {
678638
}
679639
}
680640

681-
#[derive(Copy, Clone, PartialEq, Eq, Decodable, Encodable, Hash, HashStable_Generic)]
682-
#[rustc_pass_by_value]
641+
#[derive(Copy, Clone, PartialEq, Eq, Hash)]
642+
#[cfg_attr(feature = "nightly", derive(Encodable, Decodable, HashStable_Generic))]
643+
#[cfg_attr(feature = "nightly", rustc_pass_by_value)]
683644
pub enum Variance {
684645
Covariant, // T<A> <: T<B> iff A <: B -- e.g., function return type
685646
Invariant, // T<A> <: T<B> iff B == A -- e.g., type of mutable cell
@@ -747,6 +708,7 @@ impl Variance {
747708
}
748709
}
749710

711+
#[cfg(feature = "nightly")]
750712
impl<CTX> HashStable<CTX> for InferTy {
751713
fn hash_stable(&self, ctx: &mut CTX, hasher: &mut StableHasher) {
752714
use InferTy::*;
@@ -800,47 +762,6 @@ impl fmt::Display for InferTy {
800762
}
801763
}
802764

803-
rustc_index::newtype_index! {
804-
/// "Universes" are used during type- and trait-checking in the
805-
/// presence of `for<..>` binders to control what sets of names are
806-
/// visible. Universes are arranged into a tree: the root universe
807-
/// contains names that are always visible. Each child then adds a new
808-
/// set of names that are visible, in addition to those of its parent.
809-
/// We say that the child universe "extends" the parent universe with
810-
/// new names.
811-
///
812-
/// To make this more concrete, consider this program:
813-
///
814-
/// ```ignore (illustrative)
815-
/// struct Foo { }
816-
/// fn bar<T>(x: T) {
817-
/// let y: for<'a> fn(&'a u8, Foo) = ...;
818-
/// }
819-
/// ```
820-
///
821-
/// The struct name `Foo` is in the root universe U0. But the type
822-
/// parameter `T`, introduced on `bar`, is in an extended universe U1
823-
/// -- i.e., within `bar`, we can name both `T` and `Foo`, but outside
824-
/// of `bar`, we cannot name `T`. Then, within the type of `y`, the
825-
/// region `'a` is in a universe U2 that extends U1, because we can
826-
/// name it inside the fn type but not outside.
827-
///
828-
/// Universes are used to do type- and trait-checking around these
829-
/// "forall" binders (also called **universal quantification**). The
830-
/// idea is that when, in the body of `bar`, we refer to `T` as a
831-
/// type, we aren't referring to any type in particular, but rather a
832-
/// kind of "fresh" type that is distinct from all other types we have
833-
/// actually declared. This is called a **placeholder** type, and we
834-
/// use universes to talk about this. In other words, a type name in
835-
/// universe 0 always corresponds to some "ground" type that the user
836-
/// declared, but a type name in a non-zero universe is a placeholder
837-
/// type -- an idealized representative of "types in general" that we
838-
/// use for checking generic functions.
839-
#[derive(HashStable_Generic)]
840-
#[debug_format = "U{}"]
841-
pub struct UniverseIndex {}
842-
}
843-
844765
impl UniverseIndex {
845766
pub const ROOT: UniverseIndex = UniverseIndex::from_u32(0);
846767

@@ -858,20 +779,20 @@ impl UniverseIndex {
858779
/// name the region `'a`, but that region was not nameable from
859780
/// `U` because it was not in scope there.
860781
pub fn next_universe(self) -> UniverseIndex {
861-
UniverseIndex::from_u32(self.private.checked_add(1).unwrap())
782+
UniverseIndex::from_u32(self.as_u32().checked_add(1).unwrap())
862783
}
863784

864785
/// Returns `true` if `self` can name a name from `other` -- in other words,
865786
/// if the set of names in `self` is a superset of those in
866787
/// `other` (`self >= other`).
867788
pub fn can_name(self, other: UniverseIndex) -> bool {
868-
self.private >= other.private
789+
self.as_u32() >= other.as_u32()
869790
}
870791

871792
/// Returns `true` if `self` cannot name some names from `other` -- in other
872793
/// words, if the set of names in `self` is a strict subset of
873794
/// those in `other` (`self < other`).
874795
pub fn cannot_name(self, other: UniverseIndex) -> bool {
875-
self.private < other.private
796+
self.as_u32() < other.as_u32()
876797
}
877798
}

‎compiler/rustc_type_ir/src/structural_impls.rs‎

Lines changed: 37 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,13 @@
55
use crate::fold::{FallibleTypeFolder, TypeFoldable};
66
use crate::visit::{TypeVisitable, TypeVisitor};
77
use crate::{ConstKind, FloatTy, InferTy, IntTy, Interner, UintTy, UniverseIndex};
8+
#[cfg(feature = "nightly")]
89
use rustc_data_structures::functor::IdFunctor;
10+
#[cfg(feature = "nightly")]
911
use rustc_data_structures::sync::Lrc;
1012
use rustc_index::{Idx, IndexVec};
13+
#[cfg(not(feature = "nightly"))]
14+
use std::sync::Arc as Lrc;
1115

1216
use core::fmt;
1317
use std::marker::PhantomData;
@@ -107,36 +111,60 @@ impl<I: Interner, T: TypeVisitable<I>, E: TypeVisitable<I>> TypeVisitable<I> for
107111
}
108112
}
109113

114+
#[cfg(feature = "nightly")]
110115
impl<I: Interner, T: TypeFoldable<I>> TypeFoldable<I> for Lrc<T> {
111116
fn try_fold_with<F: FallibleTypeFolder<I>>(self, folder: &mut F) -> Result<Self, F::Error> {
112117
self.try_map_id(|value| value.try_fold_with(folder))
113118
}
114119
}
115120

121+
#[cfg(not(feature = "nightly"))]
122+
impl<I: Interner, T: TypeFoldable<I>> TypeFoldable<I> for Lrc<T> {
123+
fn try_fold_with<F: FallibleTypeFolder<I>>(self, folder: &mut F) -> Result<Self, F::Error> {
124+
Ok(Lrc::new((*self).clone().try_fold_with(folder)?))
125+
}
126+
}
127+
116128
impl<I: Interner, T: TypeVisitable<I>> TypeVisitable<I> for Lrc<T> {
117129
fn visit_with<V: TypeVisitor<I>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
118130
(**self).visit_with(visitor)
119131
}
120132
}
121133

134+
#[cfg(feature = "nightly")]
122135
impl<I: Interner, T: TypeFoldable<I>> TypeFoldable<I> for Box<T> {
123136
fn try_fold_with<F: FallibleTypeFolder<I>>(self, folder: &mut F) -> Result<Self, F::Error> {
124137
self.try_map_id(|value| value.try_fold_with(folder))
125138
}
126139
}
127140

141+
#[cfg(not(feature = "nightly"))]
142+
impl<I: Interner, T: TypeFoldable<I>> TypeFoldable<I> for Box<T> {
143+
fn try_fold_with<F: FallibleTypeFolder<I>>(self, folder: &mut F) -> Result<Self, F::Error> {
144+
Ok(Box::new((*self).try_fold_with(folder)?))
145+
}
146+
}
147+
128148
impl<I: Interner, T: TypeVisitable<I>> TypeVisitable<I> for Box<T> {
129149
fn visit_with<V: TypeVisitor<I>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
130150
(**self).visit_with(visitor)
131151
}
132152
}
133153

154+
#[cfg(feature = "nightly")]
134155
impl<I: Interner, T: TypeFoldable<I>> TypeFoldable<I> for Vec<T> {
135156
fn try_fold_with<F: FallibleTypeFolder<I>>(self, folder: &mut F) -> Result<Self, F::Error> {
136157
self.try_map_id(|t| t.try_fold_with(folder))
137158
}
138159
}
139160

161+
#[cfg(not(feature = "nightly"))]
162+
impl<I: Interner, T: TypeFoldable<I>> TypeFoldable<I> for Vec<T> {
163+
fn try_fold_with<F: FallibleTypeFolder<I>>(self, folder: &mut F) -> Result<Self, F::Error> {
164+
self.into_iter().map(|t| t.try_fold_with(folder)).collect()
165+
}
166+
}
167+
140168
impl<I: Interner, T: TypeVisitable<I>> TypeVisitable<I> for Vec<T> {
141169
fn visit_with<V: TypeVisitor<I>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
142170
self.iter().try_for_each(|t| t.visit_with(visitor))
@@ -159,12 +187,20 @@ impl<I: Interner, T: TypeVisitable<I>> TypeVisitable<I> for Box<[T]> {
159187
}
160188
}
161189

190+
#[cfg(feature = "nightly")]
162191
impl<I: Interner, T: TypeFoldable<I>, Ix: Idx> TypeFoldable<I> for IndexVec<Ix, T> {
163192
fn try_fold_with<F: FallibleTypeFolder<I>>(self, folder: &mut F) -> Result<Self, F::Error> {
164193
self.try_map_id(|x| x.try_fold_with(folder))
165194
}
166195
}
167196

197+
#[cfg(not(feature = "nightly"))]
198+
impl<I: Interner, T: TypeFoldable<I>, Ix: Idx> TypeFoldable<I> for IndexVec<Ix, T> {
199+
fn try_fold_with<F: FallibleTypeFolder<I>>(self, folder: &mut F) -> Result<Self, F::Error> {
200+
self.into_iter().map(|t| t.try_fold_with(folder)).collect()
201+
}
202+
}
203+
168204
impl<I: Interner, T: TypeVisitable<I>, Ix: Idx> TypeVisitable<I> for IndexVec<Ix, T> {
169205
fn visit_with<V: TypeVisitor<I>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
170206
self.iter().try_for_each(|t| t.visit_with(visitor))
@@ -321,7 +357,7 @@ impl<I: Interner<InferTy = InferTy>> DebugWithInfcx<I> for InferTy {
321357
match this.infcx.and_then(|infcx| infcx.universe_of_ty(*this.data)) {
322358
None => write!(f, "{:?}", this.data),
323359
Some(universe) => match *this.data {
324-
TyVar(ty_vid) => write!(f, "?{}_{}t", ty_vid.index(), universe.index()),
360+
TyVar(ty_vid) => write!(f, "?{}_{}t", ty_vid.as_u32(), universe.as_u32()),
325361
IntVar(_) | FloatVar(_) | FreshTy(_) | FreshIntTy(_) | FreshFloatTy(_) => {
326362
unreachable!()
327363
}

‎compiler/rustc_type_ir/src/sty.rs‎

Lines changed: 25 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -4,23 +4,28 @@ use std::cmp::Ordering;
44
use std::{fmt, hash};
55

66
use crate::FloatTy;
7+
#[cfg(feature = "nightly")]
78
use crate::HashStableContext;
89
use crate::IntTy;
910
use crate::Interner;
11+
#[cfg(feature = "nightly")]
1012
use crate::TyDecoder;
13+
#[cfg(feature = "nightly")]
1114
use crate::TyEncoder;
1215
use crate::UintTy;
1316
use crate::{DebruijnIndex, DebugWithInfcx, InferCtxtLike, OptWithInfcx};
1417

1518
use self::RegionKind::*;
1619
use self::TyKind::*;
1720

21+
#[cfg(feature = "nightly")]
1822
use rustc_data_structures::stable_hasher::HashStable;
23+
#[cfg(feature = "nightly")]
1924
use rustc_serialize::{Decodable, Decoder, Encodable};
2025

2126
/// Specifies how a trait object is represented.
2227
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
23-
#[derive(Encodable, Decodable, HashStable_Generic)]
28+
#[cfg_attr(feature = "nightly", derive(Encodable, Decodable, HashStable_Generic))]
2429
pub enum DynKind {
2530
/// An unsized `dyn Trait` object
2631
Dyn,
@@ -34,7 +39,7 @@ pub enum DynKind {
3439
}
3540

3641
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
37-
#[derive(Encodable, Decodable, HashStable_Generic)]
42+
#[cfg_attr(feature = "nightly", derive(Encodable, Decodable, HashStable_Generic))]
3843
pub enum AliasKind {
3944
/// A projection `<Type as Trait>::AssocType`.
4045
/// Can get normalized away if monomorphic enough.
@@ -54,7 +59,7 @@ pub enum AliasKind {
5459
///
5560
/// Types written by the user start out as `hir::TyKind` and get
5661
/// converted to this representation using `AstConv::ast_ty_to_ty`.
57-
#[rustc_diagnostic_item = "IrTyKind"]
62+
#[cfg_attr(feature = "nightly", rustc_diagnostic_item = "IrTyKind")]
5863
pub enum TyKind<I: Interner> {
5964
/// The primitive boolean type. Written as `bool`.
6065
Bool,
@@ -500,7 +505,7 @@ impl<I: Interner> DebugWithInfcx<I> for TyKind<I> {
500505

501506
write!(f, ">")
502507
}
503-
Foreign(d) => f.debug_tuple_field1_finish("Foreign", d),
508+
Foreign(d) => f.debug_tuple("Foreign").field(d).finish(),
504509
Str => write!(f, "str"),
505510
Array(t, c) => write!(f, "[{:?}; {:?}]", &this.wrap(t), &this.wrap(c)),
506511
Slice(t) => write!(f, "[{:?}]", &this.wrap(t)),
@@ -516,18 +521,20 @@ impl<I: Interner> DebugWithInfcx<I> for TyKind<I> {
516521
true => write!(f, "&{:?} mut {:?}", &this.wrap(r), &this.wrap(t)),
517522
false => write!(f, "&{:?} {:?}", &this.wrap(r), &this.wrap(t)),
518523
},
519-
FnDef(d, s) => f.debug_tuple_field2_finish("FnDef", d, &this.wrap(s)),
524+
FnDef(d, s) => f.debug_tuple("FnDef").field(d).field(&this.wrap(s)).finish(),
520525
FnPtr(s) => write!(f, "{:?}", &this.wrap(s)),
521526
Dynamic(p, r, repr) => match repr {
522527
DynKind::Dyn => write!(f, "dyn {:?} + {:?}", &this.wrap(p), &this.wrap(r)),
523528
DynKind::DynStar => {
524529
write!(f, "dyn* {:?} + {:?}", &this.wrap(p), &this.wrap(r))
525530
}
526531
},
527-
Closure(d, s) => f.debug_tuple_field2_finish("Closure", d, &this.wrap(s)),
528-
Generator(d, s, m) => f.debug_tuple_field3_finish("Generator", d, &this.wrap(s), m),
532+
Closure(d, s) => f.debug_tuple("Closure").field(d).field(&this.wrap(s)).finish(),
533+
Generator(d, s, m) => {
534+
f.debug_tuple("Generator").field(d).field(&this.wrap(s)).field(m).finish()
535+
}
529536
GeneratorWitness(d, s) => {
530-
f.debug_tuple_field2_finish("GeneratorWitness", d, &this.wrap(s))
537+
f.debug_tuple("GeneratorWitness").field(d).field(&this.wrap(s)).finish()
531538
}
532539
Never => write!(f, "!"),
533540
Tuple(t) => {
@@ -546,7 +553,7 @@ impl<I: Interner> DebugWithInfcx<I> for TyKind<I> {
546553
}
547554
write!(f, ")")
548555
}
549-
Alias(i, a) => f.debug_tuple_field2_finish("Alias", i, &this.wrap(a)),
556+
Alias(i, a) => f.debug_tuple("Alias").field(i).field(&this.wrap(a)).finish(),
550557
Param(p) => write!(f, "{p:?}"),
551558
Bound(d, b) => crate::debug_bound_var(f, *d, b),
552559
Placeholder(p) => write!(f, "{p:?}"),
@@ -562,6 +569,7 @@ impl<I: Interner> fmt::Debug for TyKind<I> {
562569
}
563570
}
564571

572+
#[cfg(feature = "nightly")]
565573
// This is manually implemented because a derive would require `I: Encodable`
566574
impl<I: Interner, E: TyEncoder> Encodable<E> for TyKind<I>
567575
where
@@ -677,6 +685,7 @@ where
677685
}
678686
}
679687

688+
#[cfg(feature = "nightly")]
680689
// This is manually implemented because a derive would require `I: Decodable`
681690
impl<I: Interner, D: TyDecoder<I = I>> Decodable<D> for TyKind<I>
682691
where
@@ -743,6 +752,7 @@ where
743752
}
744753

745754
// This is not a derived impl because a derive would require `I: HashStable`
755+
#[cfg(feature = "nightly")]
746756
#[allow(rustc::usage_of_ty_tykind)]
747757
impl<CTX: HashStableContext, I: Interner> HashStable<CTX> for TyKind<I>
748758
where
@@ -925,6 +935,7 @@ impl<I: Interner> hash::Hash for ConstKind<I> {
925935
}
926936
}
927937

938+
#[cfg(feature = "nightly")]
928939
impl<CTX: HashStableContext, I: Interner> HashStable<CTX> for ConstKind<I>
929940
where
930941
I::ParamConst: HashStable<CTX>,
@@ -958,6 +969,7 @@ where
958969
}
959970
}
960971

972+
#[cfg(feature = "nightly")]
961973
impl<I: Interner, D: TyDecoder<I = I>> Decodable<D> for ConstKind<I>
962974
where
963975
I::ParamConst: Decodable<D>,
@@ -990,6 +1002,7 @@ where
9901002
}
9911003
}
9921004

1005+
#[cfg(feature = "nightly")]
9931006
impl<I: Interner, E: TyEncoder<I = I>> Encodable<E> for ConstKind<I>
9941007
where
9951008
I::ParamConst: Encodable<E>,
@@ -1373,6 +1386,7 @@ impl<I: Interner> fmt::Debug for RegionKind<I> {
13731386
}
13741387
}
13751388

1389+
#[cfg(feature = "nightly")]
13761390
// This is manually implemented because a derive would require `I: Encodable`
13771391
impl<I: Interner, E: TyEncoder> Encodable<E> for RegionKind<I>
13781392
where
@@ -1408,6 +1422,7 @@ where
14081422
}
14091423
}
14101424

1425+
#[cfg(feature = "nightly")]
14111426
// This is manually implemented because a derive would require `I: Decodable`
14121427
impl<I: Interner, D: TyDecoder<I = I>> Decodable<D> for RegionKind<I>
14131428
where
@@ -1439,6 +1454,7 @@ where
14391454
}
14401455
}
14411456

1457+
#[cfg(feature = "nightly")]
14421458
// This is not a derived impl because a derive would require `I: HashStable`
14431459
impl<CTX: HashStableContext, I: Interner> HashStable<CTX> for RegionKind<I>
14441460
where

‎compiler/rustc_type_ir/src/ty_info.rs‎

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,8 @@
1-
use std::{
2-
cmp::Ordering,
3-
hash::{Hash, Hasher},
4-
ops::Deref,
5-
};
1+
#[cfg(feature = "nightly")]
2+
use std::hash::Hasher;
3+
use std::{cmp::Ordering, hash::Hash, ops::Deref};
64

5+
#[cfg(feature = "nightly")]
76
use rustc_data_structures::{
87
fingerprint::Fingerprint,
98
stable_hasher::{HashStable, StableHasher},
@@ -19,8 +18,11 @@ use crate::{DebruijnIndex, TypeFlags};
1918
/// This is useful if you have values that you intern but never (can?) use for stable
2019
/// hashing.
2120
#[derive(Copy, Clone)]
21+
#[cfg_attr(not(feature = "nightly"), derive(Hash))]
2222
pub struct WithCachedTypeInfo<T> {
2323
pub internee: T,
24+
25+
#[cfg(feature = "nightly")]
2426
pub stable_hash: Fingerprint,
2527

2628
/// This field provides fast access to information that is also contained
@@ -83,6 +85,7 @@ impl<T> Deref for WithCachedTypeInfo<T> {
8385
}
8486
}
8587

88+
#[cfg(feature = "nightly")]
8689
impl<T: Hash> Hash for WithCachedTypeInfo<T> {
8790
#[inline]
8891
fn hash<H: Hasher>(&self, s: &mut H) {
@@ -94,6 +97,7 @@ impl<T: Hash> Hash for WithCachedTypeInfo<T> {
9497
}
9598
}
9699

100+
#[cfg(feature = "nightly")]
97101
impl<T: HashStable<CTX>, CTX> HashStable<CTX> for WithCachedTypeInfo<T> {
98102
fn hash_stable(&self, hcx: &mut CTX, hasher: &mut StableHasher) {
99103
if self.stable_hash == Fingerprint::ZERO || cfg!(debug_assertions) {

‎compiler/rustc_type_ir/src/visit.rs‎

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,8 +79,12 @@ pub trait TypeSuperVisitable<I: Interner>: TypeVisitable<I> {
7979
/// method defined for every type of interest. Each such method has a default
8080
/// that recurses into the type's fields in a non-custom fashion.
8181
pub trait TypeVisitor<I: Interner>: Sized {
82+
#[cfg(feature = "nightly")]
8283
type BreakTy = !;
8384

85+
#[cfg(not(feature = "nightly"))]
86+
type BreakTy;
87+
8488
fn visit_binder<T: TypeVisitable<I>>(&mut self, t: &I::Binder<T>) -> ControlFlow<Self::BreakTy>
8589
where
8690
I::Binder<T>: TypeSuperVisitable<I>,

0 commit comments

Comments
 (0)
Please sign in to comment.