From 6f43680edfaa752f07822e0798f414ff4b7e0126 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Tue, 17 Oct 2023 00:33:48 +0000 Subject: [PATCH] Begin to abstract rustc_type_ir for rust-analyzer --- compiler/rustc_type_ir/Cargo.toml | 21 ++- compiler/rustc_type_ir/src/fold.rs | 30 +++- compiler/rustc_type_ir/src/index.rs | 76 ++++++++ compiler/rustc_type_ir/src/index_nightly.rs | 105 +++++++++++ compiler/rustc_type_ir/src/lib.rs | 167 +++++------------- .../rustc_type_ir/src/structural_impls.rs | 38 +++- compiler/rustc_type_ir/src/sty.rs | 34 +++- compiler/rustc_type_ir/src/ty_info.rs | 14 +- compiler/rustc_type_ir/src/visit.rs | 4 + 9 files changed, 337 insertions(+), 152 deletions(-) create mode 100644 compiler/rustc_type_ir/src/index.rs create mode 100644 compiler/rustc_type_ir/src/index_nightly.rs diff --git a/compiler/rustc_type_ir/Cargo.toml b/compiler/rustc_type_ir/Cargo.toml index c4008e9b61296..33be42bd7c4a3 100644 --- a/compiler/rustc_type_ir/Cargo.toml +++ b/compiler/rustc_type_ir/Cargo.toml @@ -7,8 +7,19 @@ edition = "2021" [dependencies] bitflags = "1.2.1" -rustc_index = { path = "../rustc_index" } -rustc_serialize = { path = "../rustc_serialize" } -rustc_data_structures = { path = "../rustc_data_structures" } -rustc_macros = { path = "../rustc_macros" } -smallvec = { version = "1.8.1", features = ["union", "may_dangle"] } +rustc_index = { path = "../rustc_index", default-features = false } +rustc_serialize = { path = "../rustc_serialize", optional = true } +rustc_data_structures = { path = "../rustc_data_structures", optional = true } +rustc_macros = { path = "../rustc_macros", optional = true } +smallvec = { version = "1.8.1" } + +[features] +default = ["nightly"] +nightly = [ + "smallvec/may_dangle", + "smallvec/union", + "rustc_index/nightly", + "rustc_serialize", + "rustc_data_structures", + "rustc_macros" +] diff --git a/compiler/rustc_type_ir/src/fold.rs b/compiler/rustc_type_ir/src/fold.rs index e7a6831f5ee35..870984b701724 100644 --- a/compiler/rustc_type_ir/src/fold.rs +++ b/compiler/rustc_type_ir/src/fold.rs @@ -46,6 +46,12 @@ //! ``` use crate::{visit::TypeVisitable, Interner}; +#[cfg(feature = "nightly")] +type Never = !; + +#[cfg(not(feature = "nightly"))] +type Never = std::convert::Infallible; + /// This trait is implemented for every type that can be folded, /// providing the skeleton of the traversal. /// @@ -74,7 +80,10 @@ pub trait TypeFoldable: TypeVisitable { /// folders. Do not override this method, to ensure coherence with /// `try_fold_with`. fn fold_with>(self, folder: &mut F) -> Self { - self.try_fold_with(folder).into_ok() + match self.try_fold_with(folder) { + Ok(t) => t, + Err(_) => unreachable!(), + } } } @@ -95,7 +104,10 @@ pub trait TypeSuperFoldable: TypeFoldable { /// infallible folders. Do not override this method, to ensure coherence /// with `try_super_fold_with`. fn super_fold_with>(self, folder: &mut F) -> Self { - self.try_super_fold_with(folder).into_ok() + match self.try_super_fold_with(folder) { + Ok(t) => t, + Err(_) => unreachable!(), + } } } @@ -108,7 +120,7 @@ pub trait TypeSuperFoldable: TypeFoldable { /// A blanket implementation of [`FallibleTypeFolder`] will defer to /// the infallible methods of this trait to ensure that the two APIs /// are coherent. -pub trait TypeFolder: FallibleTypeFolder { +pub trait TypeFolder: FallibleTypeFolder { fn interner(&self) -> I; fn fold_binder(&mut self, t: I::Binder) -> I::Binder @@ -203,13 +215,13 @@ impl FallibleTypeFolder for F where F: TypeFolder, { - type Error = !; + type Error = Never; fn interner(&self) -> I { TypeFolder::interner(self) } - fn try_fold_binder(&mut self, t: I::Binder) -> Result, !> + fn try_fold_binder(&mut self, t: I::Binder) -> Result, Never> where T: TypeFoldable, I::Binder: TypeSuperFoldable, @@ -217,25 +229,25 @@ where Ok(self.fold_binder(t)) } - fn try_fold_ty(&mut self, t: I::Ty) -> Result + fn try_fold_ty(&mut self, t: I::Ty) -> Result where I::Ty: TypeSuperFoldable, { Ok(self.fold_ty(t)) } - fn try_fold_region(&mut self, r: I::Region) -> Result { + fn try_fold_region(&mut self, r: I::Region) -> Result { Ok(self.fold_region(r)) } - fn try_fold_const(&mut self, c: I::Const) -> Result + fn try_fold_const(&mut self, c: I::Const) -> Result where I::Const: TypeSuperFoldable, { Ok(self.fold_const(c)) } - fn try_fold_predicate(&mut self, p: I::Predicate) -> Result + fn try_fold_predicate(&mut self, p: I::Predicate) -> Result where I::Predicate: TypeSuperFoldable, { diff --git a/compiler/rustc_type_ir/src/index.rs b/compiler/rustc_type_ir/src/index.rs new file mode 100644 index 0000000000000..cada9aa52deb3 --- /dev/null +++ b/compiler/rustc_type_ir/src/index.rs @@ -0,0 +1,76 @@ +#[derive(Copy, Clone, Hash, Eq, PartialEq, Ord, PartialOrd, Debug)] +pub struct DebruijnIndex { + pub(crate) private: u32, +} + +impl DebruijnIndex { + pub const fn from_u32(u: u32) -> Self { + Self { private: u } + } + + pub const fn as_u32(self) -> u32 { + self.private + } +} + +pub const INNERMOST: DebruijnIndex = DebruijnIndex { private: 0 }; + +#[derive(Copy, Clone, Hash, Eq, PartialEq, Ord, PartialOrd, Debug)] +pub struct UniverseIndex { + pub(crate) private: u32, +} + +impl UniverseIndex { + pub const fn from_u32(u: u32) -> Self { + Self { private: u } + } + + pub const fn as_u32(self) -> u32 { + self.private + } +} + +#[derive(Copy, Clone, Hash, Eq, PartialEq, Ord, PartialOrd, Debug)] +pub struct TyVid { + pub(crate) private: u32, +} + +impl TyVid { + pub const fn from_u32(u: u32) -> Self { + Self { private: u } + } + + pub const fn as_u32(self) -> u32 { + self.private + } +} + +#[derive(Copy, Clone, Hash, Eq, PartialEq, Ord, PartialOrd, Debug)] +pub struct FloatVid { + pub(crate) private: u32, +} + +impl FloatVid { + pub const fn from_u32(u: u32) -> Self { + Self { private: u } + } + + pub const fn as_u32(self) -> u32 { + self.private + } +} + +#[derive(Copy, Clone, Hash, Eq, PartialEq, Ord, PartialOrd, Debug)] +pub struct IntVid { + pub(crate) private: u32, +} + +impl IntVid { + pub const fn from_u32(u: u32) -> Self { + Self { private: u } + } + + pub const fn as_u32(self) -> u32 { + self.private + } +} diff --git a/compiler/rustc_type_ir/src/index_nightly.rs b/compiler/rustc_type_ir/src/index_nightly.rs new file mode 100644 index 0000000000000..5659f41daf2bb --- /dev/null +++ b/compiler/rustc_type_ir/src/index_nightly.rs @@ -0,0 +1,105 @@ +rustc_index::newtype_index! { + /// A [De Bruijn index][dbi] is a standard means of representing + /// regions (and perhaps later types) in a higher-ranked setting. In + /// particular, imagine a type like this: + /// ```ignore (illustrative) + /// for<'a> fn(for<'b> fn(&'b isize, &'a isize), &'a char) + /// // ^ ^ | | | + /// // | | | | | + /// // | +------------+ 0 | | + /// // | | | + /// // +----------------------------------+ 1 | + /// // | | + /// // +----------------------------------------------+ 0 + /// ``` + /// In this type, there are two binders (the outer fn and the inner + /// fn). We need to be able to determine, for any given region, which + /// fn type it is bound by, the inner or the outer one. There are + /// various ways you can do this, but a De Bruijn index is one of the + /// more convenient and has some nice properties. The basic idea is to + /// count the number of binders, inside out. Some examples should help + /// clarify what I mean. + /// + /// Let's start with the reference type `&'b isize` that is the first + /// argument to the inner function. This region `'b` is assigned a De + /// Bruijn index of 0, meaning "the innermost binder" (in this case, a + /// fn). The region `'a` that appears in the second argument type (`&'a + /// isize`) would then be assigned a De Bruijn index of 1, meaning "the + /// second-innermost binder". (These indices are written on the arrows + /// in the diagram). + /// + /// What is interesting is that De Bruijn index attached to a particular + /// variable will vary depending on where it appears. For example, + /// the final type `&'a char` also refers to the region `'a` declared on + /// the outermost fn. But this time, this reference is not nested within + /// any other binders (i.e., it is not an argument to the inner fn, but + /// rather the outer one). Therefore, in this case, it is assigned a + /// De Bruijn index of 0, because the innermost binder in that location + /// is the outer fn. + /// + /// [dbi]: https://en.wikipedia.org/wiki/De_Bruijn_index + #[derive(HashStable_Generic)] + #[debug_format = "DebruijnIndex({})"] + pub struct DebruijnIndex { + const INNERMOST = 0; + } +} + +rustc_index::newtype_index! { + /// A **ty**pe **v**ariable **ID**. + #[debug_format = "?{}t"] + pub struct TyVid {} +} + +rustc_index::newtype_index! { + /// An **int**egral (`u32`, `i32`, `usize`, etc.) type **v**ariable **ID**. + #[debug_format = "?{}i"] + pub struct IntVid {} +} + +rustc_index::newtype_index! { + /// A **float**ing-point (`f32` or `f64`) type **v**ariable **ID**. + #[debug_format = "?{}f"] + pub struct FloatVid {} +} + +rustc_index::newtype_index! { + /// "Universes" are used during type- and trait-checking in the + /// presence of `for<..>` binders to control what sets of names are + /// visible. Universes are arranged into a tree: the root universe + /// contains names that are always visible. Each child then adds a new + /// set of names that are visible, in addition to those of its parent. + /// We say that the child universe "extends" the parent universe with + /// new names. + /// + /// To make this more concrete, consider this program: + /// + /// ```ignore (illustrative) + /// struct Foo { } + /// fn bar(x: T) { + /// let y: for<'a> fn(&'a u8, Foo) = ...; + /// } + /// ``` + /// + /// The struct name `Foo` is in the root universe U0. But the type + /// parameter `T`, introduced on `bar`, is in an extended universe U1 + /// -- i.e., within `bar`, we can name both `T` and `Foo`, but outside + /// of `bar`, we cannot name `T`. Then, within the type of `y`, the + /// region `'a` is in a universe U2 that extends U1, because we can + /// name it inside the fn type but not outside. + /// + /// Universes are used to do type- and trait-checking around these + /// "forall" binders (also called **universal quantification**). The + /// idea is that when, in the body of `bar`, we refer to `T` as a + /// type, we aren't referring to any type in particular, but rather a + /// kind of "fresh" type that is distinct from all other types we have + /// actually declared. This is called a **placeholder** type, and we + /// use universes to talk about this. In other words, a type name in + /// universe 0 always corresponds to some "ground" type that the user + /// declared, but a type name in a non-zero universe is a placeholder + /// type -- an idealized representative of "types in general" that we + /// use for checking generic functions. + #[derive(HashStable_Generic)] + #[debug_format = "U{}"] + pub struct UniverseIndex {} +} diff --git a/compiler/rustc_type_ir/src/lib.rs b/compiler/rustc_type_ir/src/lib.rs index 5df068de1f849..639820a266977 100644 --- a/compiler/rustc_type_ir/src/lib.rs +++ b/compiler/rustc_type_ir/src/lib.rs @@ -1,28 +1,46 @@ -#![feature(associated_type_defaults)] -#![feature(fmt_helpers_for_derive)] -#![feature(min_specialization)] -#![feature(never_type)] -#![feature(rustc_attrs)] -#![feature(unwrap_infallible)] +#![cfg_attr( + feature = "nightly", + feature( + associated_type_defaults, + fmt_helpers_for_derive, + min_specialization, + never_type, + rustc_attrs, + unwrap_infallible + ) +)] #![deny(rustc::untranslatable_diagnostic)] #![deny(rustc::diagnostic_outside_of_impl)] -#![allow(internal_features)] +#![cfg_attr(feature = "nightly", allow(internal_features))] #[macro_use] extern crate bitflags; +#[cfg(feature = "nightly")] #[macro_use] extern crate rustc_macros; +#[cfg(not(feature = "nightly"))] +pub use index::*; +#[cfg(feature = "nightly")] +pub use index_nightly::*; +#[cfg(feature = "nightly")] use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; +#[cfg(feature = "nightly")] use rustc_data_structures::unify::{EqUnifyValue, UnifyKey}; use smallvec::SmallVec; use std::fmt; use std::fmt::Debug; use std::hash::Hash; +#[cfg(feature = "nightly")] use std::mem::discriminant; +#[cfg(feature = "nightly")] pub mod codec; pub mod fold; +#[cfg(not(feature = "nightly"))] +mod index; +#[cfg(feature = "nightly")] +mod index_nightly; pub mod sty; pub mod ty_info; pub mod visit; @@ -31,6 +49,7 @@ pub mod visit; mod macros; mod structural_impls; +#[cfg(feature = "nightly")] pub use codec::*; pub use structural_impls::{DebugWithInfcx, InferCtxtLike, OptWithInfcx}; pub use sty::*; @@ -302,53 +321,6 @@ bitflags! { } } -rustc_index::newtype_index! { - /// A [De Bruijn index][dbi] is a standard means of representing - /// regions (and perhaps later types) in a higher-ranked setting. In - /// particular, imagine a type like this: - /// ```ignore (illustrative) - /// for<'a> fn(for<'b> fn(&'b isize, &'a isize), &'a char) - /// // ^ ^ | | | - /// // | | | | | - /// // | +------------+ 0 | | - /// // | | | - /// // +----------------------------------+ 1 | - /// // | | - /// // +----------------------------------------------+ 0 - /// ``` - /// In this type, there are two binders (the outer fn and the inner - /// fn). We need to be able to determine, for any given region, which - /// fn type it is bound by, the inner or the outer one. There are - /// various ways you can do this, but a De Bruijn index is one of the - /// more convenient and has some nice properties. The basic idea is to - /// count the number of binders, inside out. Some examples should help - /// clarify what I mean. - /// - /// Let's start with the reference type `&'b isize` that is the first - /// argument to the inner function. This region `'b` is assigned a De - /// Bruijn index of 0, meaning "the innermost binder" (in this case, a - /// fn). The region `'a` that appears in the second argument type (`&'a - /// isize`) would then be assigned a De Bruijn index of 1, meaning "the - /// second-innermost binder". (These indices are written on the arrows - /// in the diagram). - /// - /// What is interesting is that De Bruijn index attached to a particular - /// variable will vary depending on where it appears. For example, - /// the final type `&'a char` also refers to the region `'a` declared on - /// the outermost fn. But this time, this reference is not nested within - /// any other binders (i.e., it is not an argument to the inner fn, but - /// rather the outer one). Therefore, in this case, it is assigned a - /// De Bruijn index of 0, because the innermost binder in that location - /// is the outer fn. - /// - /// [dbi]: https://en.wikipedia.org/wiki/De_Bruijn_index - #[derive(HashStable_Generic)] - #[debug_format = "DebruijnIndex({})"] - pub struct DebruijnIndex { - const INNERMOST = 0; - } -} - impl DebruijnIndex { /// Returns the resulting index when this value is moved into /// `amount` number of new binders. So, e.g., if you had @@ -421,12 +393,12 @@ pub fn debug_bound_var( if debruijn == INNERMOST { write!(fmt, "^{var:?}") } else { - write!(fmt, "^{}_{:?}", debruijn.index(), var) + write!(fmt, "^{}_{:?}", debruijn.as_u32(), var) } } #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] -#[derive(Encodable, Decodable, HashStable_Generic)] +#[cfg_attr(feature = "nightly", derive(Encodable, Decodable, HashStable_Generic))] pub enum IntTy { Isize, I8, @@ -484,7 +456,7 @@ impl IntTy { } #[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Copy)] -#[derive(Encodable, Decodable, HashStable_Generic)] +#[cfg_attr(feature = "nightly", derive(Encodable, Decodable, HashStable_Generic))] pub enum UintTy { Usize, U8, @@ -542,7 +514,7 @@ impl UintTy { } #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] -#[derive(Encodable, Decodable, HashStable_Generic)] +#[cfg_attr(feature = "nightly", derive(Encodable, Decodable, HashStable_Generic))] pub enum FloatTy { F32, F64, @@ -573,30 +545,13 @@ pub enum IntVarValue { #[derive(Clone, Copy, PartialEq, Eq)] pub struct FloatVarValue(pub FloatTy); -rustc_index::newtype_index! { - /// A **ty**pe **v**ariable **ID**. - #[debug_format = "?{}t"] - pub struct TyVid {} -} - -rustc_index::newtype_index! { - /// An **int**egral (`u32`, `i32`, `usize`, etc.) type **v**ariable **ID**. - #[debug_format = "?{}i"] - pub struct IntVid {} -} - -rustc_index::newtype_index! { - /// A **float**ing-point (`f32` or `f64`) type **v**ariable **ID**. - #[debug_format = "?{}f"] - pub struct FloatVid {} -} - /// A placeholder for a type that hasn't been inferred yet. /// /// E.g., if we have an empty array (`[]`), then we create a fresh /// type variable for the element type since we won't know until it's /// used what the element type is supposed to be. -#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Encodable, Decodable)] +#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] +#[cfg_attr(feature = "nightly", derive(Encodable, Decodable))] pub enum InferTy { /// A type variable. TyVar(TyVid), @@ -629,6 +584,7 @@ pub enum InferTy { /// Raw `TyVid` are used as the unification key for `sub_relations`; /// they carry no values. +#[cfg(feature = "nightly")] impl UnifyKey for TyVid { type Value = (); #[inline] @@ -644,8 +600,10 @@ impl UnifyKey for TyVid { } } +#[cfg(feature = "nightly")] impl EqUnifyValue for IntVarValue {} +#[cfg(feature = "nightly")] impl UnifyKey for IntVid { type Value = Option; #[inline] // make this function eligible for inlining - it is quite hot. @@ -661,8 +619,10 @@ impl UnifyKey for IntVid { } } +#[cfg(feature = "nightly")] impl EqUnifyValue for FloatVarValue {} +#[cfg(feature = "nightly")] impl UnifyKey for FloatVid { type Value = Option; #[inline] @@ -678,8 +638,9 @@ impl UnifyKey for FloatVid { } } -#[derive(Copy, Clone, PartialEq, Eq, Decodable, Encodable, Hash, HashStable_Generic)] -#[rustc_pass_by_value] +#[derive(Copy, Clone, PartialEq, Eq, Hash)] +#[cfg_attr(feature = "nightly", derive(Encodable, Decodable, HashStable_Generic))] +#[cfg_attr(feature = "nightly", rustc_pass_by_value)] pub enum Variance { Covariant, // T <: T iff A <: B -- e.g., function return type Invariant, // T <: T iff B == A -- e.g., type of mutable cell @@ -747,6 +708,7 @@ impl Variance { } } +#[cfg(feature = "nightly")] impl HashStable for InferTy { fn hash_stable(&self, ctx: &mut CTX, hasher: &mut StableHasher) { use InferTy::*; @@ -800,47 +762,6 @@ impl fmt::Display for InferTy { } } -rustc_index::newtype_index! { - /// "Universes" are used during type- and trait-checking in the - /// presence of `for<..>` binders to control what sets of names are - /// visible. Universes are arranged into a tree: the root universe - /// contains names that are always visible. Each child then adds a new - /// set of names that are visible, in addition to those of its parent. - /// We say that the child universe "extends" the parent universe with - /// new names. - /// - /// To make this more concrete, consider this program: - /// - /// ```ignore (illustrative) - /// struct Foo { } - /// fn bar(x: T) { - /// let y: for<'a> fn(&'a u8, Foo) = ...; - /// } - /// ``` - /// - /// The struct name `Foo` is in the root universe U0. But the type - /// parameter `T`, introduced on `bar`, is in an extended universe U1 - /// -- i.e., within `bar`, we can name both `T` and `Foo`, but outside - /// of `bar`, we cannot name `T`. Then, within the type of `y`, the - /// region `'a` is in a universe U2 that extends U1, because we can - /// name it inside the fn type but not outside. - /// - /// Universes are used to do type- and trait-checking around these - /// "forall" binders (also called **universal quantification**). The - /// idea is that when, in the body of `bar`, we refer to `T` as a - /// type, we aren't referring to any type in particular, but rather a - /// kind of "fresh" type that is distinct from all other types we have - /// actually declared. This is called a **placeholder** type, and we - /// use universes to talk about this. In other words, a type name in - /// universe 0 always corresponds to some "ground" type that the user - /// declared, but a type name in a non-zero universe is a placeholder - /// type -- an idealized representative of "types in general" that we - /// use for checking generic functions. - #[derive(HashStable_Generic)] - #[debug_format = "U{}"] - pub struct UniverseIndex {} -} - impl UniverseIndex { pub const ROOT: UniverseIndex = UniverseIndex::from_u32(0); @@ -858,20 +779,20 @@ impl UniverseIndex { /// name the region `'a`, but that region was not nameable from /// `U` because it was not in scope there. pub fn next_universe(self) -> UniverseIndex { - UniverseIndex::from_u32(self.private.checked_add(1).unwrap()) + UniverseIndex::from_u32(self.as_u32().checked_add(1).unwrap()) } /// Returns `true` if `self` can name a name from `other` -- in other words, /// if the set of names in `self` is a superset of those in /// `other` (`self >= other`). pub fn can_name(self, other: UniverseIndex) -> bool { - self.private >= other.private + self.as_u32() >= other.as_u32() } /// Returns `true` if `self` cannot name some names from `other` -- in other /// words, if the set of names in `self` is a strict subset of /// those in `other` (`self < other`). pub fn cannot_name(self, other: UniverseIndex) -> bool { - self.private < other.private + self.as_u32() < other.as_u32() } } diff --git a/compiler/rustc_type_ir/src/structural_impls.rs b/compiler/rustc_type_ir/src/structural_impls.rs index f1037fe0bafa5..707fa15e27c6a 100644 --- a/compiler/rustc_type_ir/src/structural_impls.rs +++ b/compiler/rustc_type_ir/src/structural_impls.rs @@ -5,9 +5,13 @@ use crate::fold::{FallibleTypeFolder, TypeFoldable}; use crate::visit::{TypeVisitable, TypeVisitor}; use crate::{ConstKind, FloatTy, InferTy, IntTy, Interner, UintTy, UniverseIndex}; +#[cfg(feature = "nightly")] use rustc_data_structures::functor::IdFunctor; +#[cfg(feature = "nightly")] use rustc_data_structures::sync::Lrc; use rustc_index::{Idx, IndexVec}; +#[cfg(not(feature = "nightly"))] +use std::sync::Arc as Lrc; use core::fmt; use std::marker::PhantomData; @@ -107,36 +111,60 @@ impl, E: TypeVisitable> TypeVisitable for } } +#[cfg(feature = "nightly")] impl> TypeFoldable for Lrc { fn try_fold_with>(self, folder: &mut F) -> Result { self.try_map_id(|value| value.try_fold_with(folder)) } } +#[cfg(not(feature = "nightly"))] +impl> TypeFoldable for Lrc { + fn try_fold_with>(self, folder: &mut F) -> Result { + Ok(Lrc::new((*self).clone().try_fold_with(folder)?)) + } +} + impl> TypeVisitable for Lrc { fn visit_with>(&self, visitor: &mut V) -> ControlFlow { (**self).visit_with(visitor) } } +#[cfg(feature = "nightly")] impl> TypeFoldable for Box { fn try_fold_with>(self, folder: &mut F) -> Result { self.try_map_id(|value| value.try_fold_with(folder)) } } +#[cfg(not(feature = "nightly"))] +impl> TypeFoldable for Box { + fn try_fold_with>(self, folder: &mut F) -> Result { + Ok(Box::new((*self).try_fold_with(folder)?)) + } +} + impl> TypeVisitable for Box { fn visit_with>(&self, visitor: &mut V) -> ControlFlow { (**self).visit_with(visitor) } } +#[cfg(feature = "nightly")] impl> TypeFoldable for Vec { fn try_fold_with>(self, folder: &mut F) -> Result { self.try_map_id(|t| t.try_fold_with(folder)) } } +#[cfg(not(feature = "nightly"))] +impl> TypeFoldable for Vec { + fn try_fold_with>(self, folder: &mut F) -> Result { + self.into_iter().map(|t| t.try_fold_with(folder)).collect() + } +} + impl> TypeVisitable for Vec { fn visit_with>(&self, visitor: &mut V) -> ControlFlow { self.iter().try_for_each(|t| t.visit_with(visitor)) @@ -159,12 +187,20 @@ impl> TypeVisitable for Box<[T]> { } } +#[cfg(feature = "nightly")] impl, Ix: Idx> TypeFoldable for IndexVec { fn try_fold_with>(self, folder: &mut F) -> Result { self.try_map_id(|x| x.try_fold_with(folder)) } } +#[cfg(not(feature = "nightly"))] +impl, Ix: Idx> TypeFoldable for IndexVec { + fn try_fold_with>(self, folder: &mut F) -> Result { + self.into_iter().map(|t| t.try_fold_with(folder)).collect() + } +} + impl, Ix: Idx> TypeVisitable for IndexVec { fn visit_with>(&self, visitor: &mut V) -> ControlFlow { self.iter().try_for_each(|t| t.visit_with(visitor)) @@ -321,7 +357,7 @@ impl> DebugWithInfcx for InferTy { match this.infcx.and_then(|infcx| infcx.universe_of_ty(*this.data)) { None => write!(f, "{:?}", this.data), Some(universe) => match *this.data { - TyVar(ty_vid) => write!(f, "?{}_{}t", ty_vid.index(), universe.index()), + TyVar(ty_vid) => write!(f, "?{}_{}t", ty_vid.as_u32(), universe.as_u32()), IntVar(_) | FloatVar(_) | FreshTy(_) | FreshIntTy(_) | FreshFloatTy(_) => { unreachable!() } diff --git a/compiler/rustc_type_ir/src/sty.rs b/compiler/rustc_type_ir/src/sty.rs index 091b51440a6e1..5d1474fd8ade2 100644 --- a/compiler/rustc_type_ir/src/sty.rs +++ b/compiler/rustc_type_ir/src/sty.rs @@ -4,10 +4,13 @@ use std::cmp::Ordering; use std::{fmt, hash}; use crate::FloatTy; +#[cfg(feature = "nightly")] use crate::HashStableContext; use crate::IntTy; use crate::Interner; +#[cfg(feature = "nightly")] use crate::TyDecoder; +#[cfg(feature = "nightly")] use crate::TyEncoder; use crate::UintTy; use crate::{DebruijnIndex, DebugWithInfcx, InferCtxtLike, OptWithInfcx}; @@ -15,12 +18,14 @@ use crate::{DebruijnIndex, DebugWithInfcx, InferCtxtLike, OptWithInfcx}; use self::RegionKind::*; use self::TyKind::*; +#[cfg(feature = "nightly")] use rustc_data_structures::stable_hasher::HashStable; +#[cfg(feature = "nightly")] use rustc_serialize::{Decodable, Decoder, Encodable}; /// Specifies how a trait object is represented. #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)] -#[derive(Encodable, Decodable, HashStable_Generic)] +#[cfg_attr(feature = "nightly", derive(Encodable, Decodable, HashStable_Generic))] pub enum DynKind { /// An unsized `dyn Trait` object Dyn, @@ -34,7 +39,7 @@ pub enum DynKind { } #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)] -#[derive(Encodable, Decodable, HashStable_Generic)] +#[cfg_attr(feature = "nightly", derive(Encodable, Decodable, HashStable_Generic))] pub enum AliasKind { /// A projection `::AssocType`. /// Can get normalized away if monomorphic enough. @@ -54,7 +59,7 @@ pub enum AliasKind { /// /// Types written by the user start out as `hir::TyKind` and get /// converted to this representation using `AstConv::ast_ty_to_ty`. -#[rustc_diagnostic_item = "IrTyKind"] +#[cfg_attr(feature = "nightly", rustc_diagnostic_item = "IrTyKind")] pub enum TyKind { /// The primitive boolean type. Written as `bool`. Bool, @@ -500,7 +505,7 @@ impl DebugWithInfcx for TyKind { write!(f, ">") } - Foreign(d) => f.debug_tuple_field1_finish("Foreign", d), + Foreign(d) => f.debug_tuple("Foreign").field(d).finish(), Str => write!(f, "str"), Array(t, c) => write!(f, "[{:?}; {:?}]", &this.wrap(t), &this.wrap(c)), Slice(t) => write!(f, "[{:?}]", &this.wrap(t)), @@ -516,7 +521,7 @@ impl DebugWithInfcx for TyKind { true => write!(f, "&{:?} mut {:?}", &this.wrap(r), &this.wrap(t)), false => write!(f, "&{:?} {:?}", &this.wrap(r), &this.wrap(t)), }, - FnDef(d, s) => f.debug_tuple_field2_finish("FnDef", d, &this.wrap(s)), + FnDef(d, s) => f.debug_tuple("FnDef").field(d).field(&this.wrap(s)).finish(), FnPtr(s) => write!(f, "{:?}", &this.wrap(s)), Dynamic(p, r, repr) => match repr { DynKind::Dyn => write!(f, "dyn {:?} + {:?}", &this.wrap(p), &this.wrap(r)), @@ -524,10 +529,12 @@ impl DebugWithInfcx for TyKind { write!(f, "dyn* {:?} + {:?}", &this.wrap(p), &this.wrap(r)) } }, - Closure(d, s) => f.debug_tuple_field2_finish("Closure", d, &this.wrap(s)), - Generator(d, s, m) => f.debug_tuple_field3_finish("Generator", d, &this.wrap(s), m), + Closure(d, s) => f.debug_tuple("Closure").field(d).field(&this.wrap(s)).finish(), + Generator(d, s, m) => { + f.debug_tuple("Generator").field(d).field(&this.wrap(s)).field(m).finish() + } GeneratorWitness(d, s) => { - f.debug_tuple_field2_finish("GeneratorWitness", d, &this.wrap(s)) + f.debug_tuple("GeneratorWitness").field(d).field(&this.wrap(s)).finish() } Never => write!(f, "!"), Tuple(t) => { @@ -546,7 +553,7 @@ impl DebugWithInfcx for TyKind { } write!(f, ")") } - Alias(i, a) => f.debug_tuple_field2_finish("Alias", i, &this.wrap(a)), + Alias(i, a) => f.debug_tuple("Alias").field(i).field(&this.wrap(a)).finish(), Param(p) => write!(f, "{p:?}"), Bound(d, b) => crate::debug_bound_var(f, *d, b), Placeholder(p) => write!(f, "{p:?}"), @@ -562,6 +569,7 @@ impl fmt::Debug for TyKind { } } +#[cfg(feature = "nightly")] // This is manually implemented because a derive would require `I: Encodable` impl Encodable for TyKind where @@ -677,6 +685,7 @@ where } } +#[cfg(feature = "nightly")] // This is manually implemented because a derive would require `I: Decodable` impl> Decodable for TyKind where @@ -743,6 +752,7 @@ where } // This is not a derived impl because a derive would require `I: HashStable` +#[cfg(feature = "nightly")] #[allow(rustc::usage_of_ty_tykind)] impl HashStable for TyKind where @@ -925,6 +935,7 @@ impl hash::Hash for ConstKind { } } +#[cfg(feature = "nightly")] impl HashStable for ConstKind where I::ParamConst: HashStable, @@ -958,6 +969,7 @@ where } } +#[cfg(feature = "nightly")] impl> Decodable for ConstKind where I::ParamConst: Decodable, @@ -990,6 +1002,7 @@ where } } +#[cfg(feature = "nightly")] impl> Encodable for ConstKind where I::ParamConst: Encodable, @@ -1373,6 +1386,7 @@ impl fmt::Debug for RegionKind { } } +#[cfg(feature = "nightly")] // This is manually implemented because a derive would require `I: Encodable` impl Encodable for RegionKind where @@ -1408,6 +1422,7 @@ where } } +#[cfg(feature = "nightly")] // This is manually implemented because a derive would require `I: Decodable` impl> Decodable for RegionKind where @@ -1439,6 +1454,7 @@ where } } +#[cfg(feature = "nightly")] // This is not a derived impl because a derive would require `I: HashStable` impl HashStable for RegionKind where diff --git a/compiler/rustc_type_ir/src/ty_info.rs b/compiler/rustc_type_ir/src/ty_info.rs index 4e5d424886ad8..a4f518a58168f 100644 --- a/compiler/rustc_type_ir/src/ty_info.rs +++ b/compiler/rustc_type_ir/src/ty_info.rs @@ -1,9 +1,8 @@ -use std::{ - cmp::Ordering, - hash::{Hash, Hasher}, - ops::Deref, -}; +#[cfg(feature = "nightly")] +use std::hash::Hasher; +use std::{cmp::Ordering, hash::Hash, ops::Deref}; +#[cfg(feature = "nightly")] use rustc_data_structures::{ fingerprint::Fingerprint, stable_hasher::{HashStable, StableHasher}, @@ -19,8 +18,11 @@ use crate::{DebruijnIndex, TypeFlags}; /// This is useful if you have values that you intern but never (can?) use for stable /// hashing. #[derive(Copy, Clone)] +#[cfg_attr(not(feature = "nightly"), derive(Hash))] pub struct WithCachedTypeInfo { pub internee: T, + + #[cfg(feature = "nightly")] pub stable_hash: Fingerprint, /// This field provides fast access to information that is also contained @@ -83,6 +85,7 @@ impl Deref for WithCachedTypeInfo { } } +#[cfg(feature = "nightly")] impl Hash for WithCachedTypeInfo { #[inline] fn hash(&self, s: &mut H) { @@ -94,6 +97,7 @@ impl Hash for WithCachedTypeInfo { } } +#[cfg(feature = "nightly")] impl, CTX> HashStable for WithCachedTypeInfo { fn hash_stable(&self, hcx: &mut CTX, hasher: &mut StableHasher) { if self.stable_hash == Fingerprint::ZERO || cfg!(debug_assertions) { diff --git a/compiler/rustc_type_ir/src/visit.rs b/compiler/rustc_type_ir/src/visit.rs index 891a4dda22fef..cb473c650cc6e 100644 --- a/compiler/rustc_type_ir/src/visit.rs +++ b/compiler/rustc_type_ir/src/visit.rs @@ -79,8 +79,12 @@ pub trait TypeSuperVisitable: TypeVisitable { /// method defined for every type of interest. Each such method has a default /// that recurses into the type's fields in a non-custom fashion. pub trait TypeVisitor: Sized { + #[cfg(feature = "nightly")] type BreakTy = !; + #[cfg(not(feature = "nightly"))] + type BreakTy; + fn visit_binder>(&mut self, t: &I::Binder) -> ControlFlow where I::Binder: TypeSuperVisitable,