about summary refs log tree commit diff
diff options
context:
space:
mode:
authorMichael Goulet <michael@errs.io>2023-10-24 00:16:14 +0000
committerMichael Goulet <michael@errs.io>2023-11-18 00:20:00 +0000
commit4506681e2f53e17df0d74cd230948dc40f7d0e8d (patch)
tree30f5887e9c39e750fd89e72b7007075a11c81be3
parent2831701757eb7b3105eda26a306c2f3a97e2664b (diff)
downloadrust-4506681e2f53e17df0d74cd230948dc40f7d0e8d.tar.gz
rust-4506681e2f53e17df0d74cd230948dc40f7d0e8d.zip
Begin nightly-ifying rustc_type_ir
-rw-r--r--Cargo.lock11
-rw-r--r--compiler/rustc_index/Cargo.toml3
-rw-r--r--compiler/rustc_index/src/lib.rs3
-rw-r--r--compiler/rustc_index/src/vec/tests.rs2
-rw-r--r--compiler/rustc_index_macros/Cargo.toml17
-rw-r--r--compiler/rustc_index_macros/src/lib.rs30
-rw-r--r--compiler/rustc_index_macros/src/newtype.rs (renamed from compiler/rustc_macros/src/newtype.rs)16
-rw-r--r--compiler/rustc_macros/src/lib.rs22
-rw-r--r--compiler/rustc_mir_transform/src/gvn.rs2
-rw-r--r--compiler/rustc_type_ir/Cargo.toml21
-rw-r--r--compiler/rustc_type_ir/src/canonical.rs9
-rw-r--r--compiler/rustc_type_ir/src/const_kind.rs12
-rw-r--r--compiler/rustc_type_ir/src/fold.rs34
-rw-r--r--compiler/rustc_type_ir/src/lib.rs33
-rw-r--r--compiler/rustc_type_ir/src/predicate_kind.rs17
-rw-r--r--compiler/rustc_type_ir/src/region_kind.rs11
-rw-r--r--compiler/rustc_type_ir/src/ty_info.rs12
-rw-r--r--compiler/rustc_type_ir/src/ty_kind.rs55
-rw-r--r--compiler/rustc_type_ir/src/visit.rs6
19 files changed, 214 insertions, 102 deletions
diff --git a/Cargo.lock b/Cargo.lock
index 92bac995bc6..4b445ef695a 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -4041,12 +4041,23 @@ name = "rustc_index"
 version = "0.0.0"
 dependencies = [
  "arrayvec",
+ "rustc_index_macros",
  "rustc_macros",
  "rustc_serialize",
  "smallvec",
 ]
 
 [[package]]
+name = "rustc_index_macros"
+version = "0.0.0"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn 2.0.29",
+ "synstructure",
+]
+
+[[package]]
 name = "rustc_infer"
 version = "0.0.0"
 dependencies = [
diff --git a/compiler/rustc_index/Cargo.toml b/compiler/rustc_index/Cargo.toml
index 856f8a67dd6..3a4c813b5d4 100644
--- a/compiler/rustc_index/Cargo.toml
+++ b/compiler/rustc_index/Cargo.toml
@@ -6,6 +6,7 @@ edition = "2021"
 [dependencies]
 # tidy-alphabetical-start
 arrayvec = { version = "0.7", default-features = false }
+rustc_index_macros = { path = "../rustc_index_macros", default-features = false }
 rustc_macros = { path = "../rustc_macros", optional = true }
 rustc_serialize = { path = "../rustc_serialize", optional = true }
 smallvec = "1.8.1"
@@ -14,5 +15,5 @@ smallvec = "1.8.1"
 [features]
 # tidy-alphabetical-start
 default = ["nightly"]
-nightly = ["rustc_serialize", "rustc_macros"]
+nightly = ["rustc_serialize", "rustc_macros", "rustc_index_macros/nightly"]
 # tidy-alphabetical-end
diff --git a/compiler/rustc_index/src/lib.rs b/compiler/rustc_index/src/lib.rs
index 061c55c0150..c5602392c53 100644
--- a/compiler/rustc_index/src/lib.rs
+++ b/compiler/rustc_index/src/lib.rs
@@ -25,8 +25,7 @@ mod vec;
 
 pub use {idx::Idx, slice::IndexSlice, vec::IndexVec};
 
-#[cfg(feature = "rustc_macros")]
-pub use rustc_macros::newtype_index;
+pub use rustc_index_macros::newtype_index;
 
 /// Type size assertion. The first argument is a type and the second argument is its expected size.
 ///
diff --git a/compiler/rustc_index/src/vec/tests.rs b/compiler/rustc_index/src/vec/tests.rs
index 7e5e41bd2d1..1959f4e07b7 100644
--- a/compiler/rustc_index/src/vec/tests.rs
+++ b/compiler/rustc_index/src/vec/tests.rs
@@ -1,7 +1,7 @@
 // Allows the macro invocation below to work
 use crate as rustc_index;
 
-rustc_macros::newtype_index! {
+crate::newtype_index! {
     #[max = 0xFFFF_FFFA]
     struct MyIdx {}
 }
diff --git a/compiler/rustc_index_macros/Cargo.toml b/compiler/rustc_index_macros/Cargo.toml
new file mode 100644
index 00000000000..c4ca29db3c2
--- /dev/null
+++ b/compiler/rustc_index_macros/Cargo.toml
@@ -0,0 +1,17 @@
+[package]
+name = "rustc_index_macros"
+version = "0.0.0"
+edition = "2021"
+
+[lib]
+proc-macro = true
+
+[dependencies]
+synstructure = "0.13.0"
+syn = { version = "2.0.9", features = ["full"] }
+proc-macro2 = "1"
+quote = "1"
+
+[features]
+default = ["nightly"]
+nightly = []
\ No newline at end of file
diff --git a/compiler/rustc_index_macros/src/lib.rs b/compiler/rustc_index_macros/src/lib.rs
new file mode 100644
index 00000000000..f6a6175374a
--- /dev/null
+++ b/compiler/rustc_index_macros/src/lib.rs
@@ -0,0 +1,30 @@
+#![cfg_attr(feature = "nightly", feature(allow_internal_unstable))]
+#![cfg_attr(feature = "nightly", allow(internal_features))]
+
+use proc_macro::TokenStream;
+
+mod newtype;
+
+/// Creates a struct type `S` that can be used as an index with
+/// `IndexVec` and so on.
+///
+/// There are two ways of interacting with these indices:
+///
+/// - The `From` impls are the preferred way. So you can do
+///   `S::from(v)` with a `usize` or `u32`. And you can convert back
+///   to an integer with `u32::from(s)`.
+///
+/// - Alternatively, you can use the methods `S::new(v)` and `s.index()`
+///   to create/return a value.
+///
+/// Internally, the index uses a u32, so the index must not exceed
+/// `u32::MAX`. You can also customize things like the `Debug` impl,
+/// what traits are derived, and so forth via the macro.
+#[proc_macro]
+#[cfg_attr(
+    feature = "nightly",
+    allow_internal_unstable(step_trait, rustc_attrs, trusted_step, spec_option_partial_eq)
+)]
+pub fn newtype_index(input: TokenStream) -> TokenStream {
+    newtype::newtype(input)
+}
diff --git a/compiler/rustc_macros/src/newtype.rs b/compiler/rustc_index_macros/src/newtype.rs
index 72b47de1abc..2a974fd2628 100644
--- a/compiler/rustc_macros/src/newtype.rs
+++ b/compiler/rustc_index_macros/src/newtype.rs
@@ -24,9 +24,16 @@ impl Parse for Newtype {
         let mut consts = Vec::new();
         let mut encodable = true;
         let mut ord = true;
+        let mut gate_rustc_only = quote! {};
+        let mut gate_rustc_only_cfg = quote! { all() };
 
         attrs.retain(|attr| match attr.path().get_ident() {
             Some(ident) => match &*ident.to_string() {
+                "gate_rustc_only" => {
+                    gate_rustc_only = quote! { #[cfg(feature = "nightly")] };
+                    gate_rustc_only_cfg = quote! { feature = "nightly" };
+                    false
+                }
                 "custom_encodable" => {
                     encodable = false;
                     false
@@ -88,11 +95,13 @@ impl Parse for Newtype {
 
         let encodable_impls = if encodable {
             quote! {
+                #gate_rustc_only
                 impl<D: ::rustc_serialize::Decoder> ::rustc_serialize::Decodable<D> for #name {
                     fn decode(d: &mut D) -> Self {
                         Self::from_u32(d.read_u32())
                     }
                 }
+                #gate_rustc_only
                 impl<E: ::rustc_serialize::Encoder> ::rustc_serialize::Encodable<E> for #name {
                     fn encode(&self, e: &mut E) {
                         e.emit_u32(self.private);
@@ -110,6 +119,7 @@ impl Parse for Newtype {
 
         let step = if ord {
             quote! {
+                #gate_rustc_only
                 impl ::std::iter::Step for #name {
                     #[inline]
                     fn steps_between(start: &Self, end: &Self) -> Option<usize> {
@@ -131,6 +141,7 @@ impl Parse for Newtype {
                 }
 
                 // Safety: The implementation of `Step` upholds all invariants.
+                #gate_rustc_only
                 unsafe impl ::std::iter::TrustedStep for #name {}
             }
         } else {
@@ -148,6 +159,7 @@ impl Parse for Newtype {
         let spec_partial_eq_impl = if let Lit::Int(max) = &max {
             if let Ok(max_val) = max.base10_parse::<u32>() {
                 quote! {
+                    #gate_rustc_only
                     impl core::option::SpecOptionPartialEq for #name {
                         #[inline]
                         fn eq(l: &Option<Self>, r: &Option<Self>) -> bool {
@@ -173,8 +185,8 @@ impl Parse for Newtype {
         Ok(Self(quote! {
             #(#attrs)*
             #[derive(Clone, Copy, PartialEq, Eq, Hash, #(#derive_paths),*)]
-            #[rustc_layout_scalar_valid_range_end(#max)]
-            #[rustc_pass_by_value]
+            #[cfg_attr(#gate_rustc_only_cfg, rustc_layout_scalar_valid_range_end(#max))]
+            #[cfg_attr(#gate_rustc_only_cfg, rustc_pass_by_value)]
             #vis struct #name {
                 private: u32,
             }
diff --git a/compiler/rustc_macros/src/lib.rs b/compiler/rustc_macros/src/lib.rs
index a6666636032..2775bd5f629 100644
--- a/compiler/rustc_macros/src/lib.rs
+++ b/compiler/rustc_macros/src/lib.rs
@@ -19,7 +19,6 @@ mod current_version;
 mod diagnostics;
 mod hash_stable;
 mod lift;
-mod newtype;
 mod query;
 mod serialize;
 mod symbols;
@@ -44,27 +43,6 @@ pub fn symbols(input: TokenStream) -> TokenStream {
     symbols::symbols(input.into()).into()
 }
 
-/// Creates a struct type `S` that can be used as an index with
-/// `IndexVec` and so on.
-///
-/// There are two ways of interacting with these indices:
-///
-/// - The `From` impls are the preferred way. So you can do
-///   `S::from(v)` with a `usize` or `u32`. And you can convert back
-///   to an integer with `u32::from(s)`.
-///
-/// - Alternatively, you can use the methods `S::new(v)` and `s.index()`
-///   to create/return a value.
-///
-/// Internally, the index uses a u32, so the index must not exceed
-/// `u32::MAX`. You can also customize things like the `Debug` impl,
-/// what traits are derived, and so forth via the macro.
-#[proc_macro]
-#[allow_internal_unstable(step_trait, rustc_attrs, trusted_step, spec_option_partial_eq)]
-pub fn newtype_index(input: TokenStream) -> TokenStream {
-    newtype::newtype(input)
-}
-
 decl_derive!([HashStable, attributes(stable_hasher)] => hash_stable::hash_stable_derive);
 decl_derive!(
     [HashStable_Generic, attributes(stable_hasher)] =>
diff --git a/compiler/rustc_mir_transform/src/gvn.rs b/compiler/rustc_mir_transform/src/gvn.rs
index 98a03618286..735960f31b3 100644
--- a/compiler/rustc_mir_transform/src/gvn.rs
+++ b/compiler/rustc_mir_transform/src/gvn.rs
@@ -88,8 +88,8 @@ use rustc_data_structures::fx::{FxHashMap, FxIndexSet};
 use rustc_data_structures::graph::dominators::Dominators;
 use rustc_hir::def::DefKind;
 use rustc_index::bit_set::BitSet;
+use rustc_index::newtype_index;
 use rustc_index::IndexVec;
-use rustc_macros::newtype_index;
 use rustc_middle::mir::interpret::GlobalAlloc;
 use rustc_middle::mir::visit::*;
 use rustc_middle::mir::*;
diff --git a/compiler/rustc_type_ir/Cargo.toml b/compiler/rustc_type_ir/Cargo.toml
index b39ba305913..3a08d89cc44 100644
--- a/compiler/rustc_type_ir/Cargo.toml
+++ b/compiler/rustc_type_ir/Cargo.toml
@@ -7,9 +7,20 @@ edition = "2021"
 # tidy-alphabetical-start
 bitflags = "1.2.1"
 derivative = "2.2.0"
-rustc_data_structures = { path = "../rustc_data_structures" }
-rustc_index = { path = "../rustc_index" }
-rustc_macros = { path = "../rustc_macros" }
-rustc_serialize = { path = "../rustc_serialize" }
-smallvec = { version = "1.8.1", features = ["union", "may_dangle"] }
+rustc_data_structures = { path = "../rustc_data_structures", optional = true }
+rustc_index = { path = "../rustc_index", default-features = false }
+rustc_macros = { path = "../rustc_macros", optional = true }
+rustc_serialize = { path = "../rustc_serialize", optional = true }
+smallvec = { version = "1.8.1" }
 # tidy-alphabetical-end
+
+[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/canonical.rs b/compiler/rustc_type_ir/src/canonical.rs
index ace9eade7f6..a0e4b4ecbfc 100644
--- a/compiler/rustc_type_ir/src/canonical.rs
+++ b/compiler/rustc_type_ir/src/canonical.rs
@@ -2,18 +2,19 @@ use std::fmt;
 use std::hash::Hash;
 use std::ops::ControlFlow;
 
+#[cfg(feature = "nightly")]
 use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
 
 use crate::fold::{FallibleTypeFolder, TypeFoldable};
 use crate::visit::{TypeVisitable, TypeVisitor};
-use crate::{HashStableContext, Interner, UniverseIndex};
+use crate::{Interner, UniverseIndex};
 
 /// A "canonicalized" type `V` is one where all free inference
 /// variables have been rewritten to "canonical vars". These are
 /// numbered starting from 0 in order of first appearance.
 #[derive(derivative::Derivative)]
 #[derivative(Clone(bound = "V: Clone"), Hash(bound = "V: Hash"))]
-#[derive(TyEncodable, TyDecodable)]
+#[cfg_attr(feature = "nightly", derive(TyEncodable, TyDecodable))]
 pub struct Canonical<I: Interner, V> {
     pub value: V,
     pub max_universe: UniverseIndex,
@@ -60,7 +61,9 @@ impl<I: Interner, V> Canonical<I, V> {
     }
 }
 
-impl<CTX: HashStableContext, I: Interner, V: HashStable<CTX>> HashStable<CTX> for Canonical<I, V>
+#[cfg(feature = "nightly")]
+impl<CTX: crate::HashStableContext, I: Interner, V: HashStable<CTX>> HashStable<CTX>
+    for Canonical<I, V>
 where
     I::CanonicalVars: HashStable<CTX>,
 {
diff --git a/compiler/rustc_type_ir/src/const_kind.rs b/compiler/rustc_type_ir/src/const_kind.rs
index 33782b13ca8..a014a4f38ca 100644
--- a/compiler/rustc_type_ir/src/const_kind.rs
+++ b/compiler/rustc_type_ir/src/const_kind.rs
@@ -1,8 +1,8 @@
-use rustc_data_structures::stable_hasher::HashStable;
-use rustc_data_structures::stable_hasher::StableHasher;
+#[cfg(feature = "nightly")]
+use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
 use std::fmt;
 
-use crate::{DebruijnIndex, DebugWithInfcx, HashStableContext, InferCtxtLike, Interner, WithInfcx};
+use crate::{DebruijnIndex, DebugWithInfcx, InferCtxtLike, Interner, WithInfcx};
 
 use self::ConstKind::*;
 
@@ -16,7 +16,7 @@ use self::ConstKind::*;
     Ord = "feature_allow_slow_enum",
     Hash(bound = "")
 )]
-#[derive(TyEncodable, TyDecodable)]
+#[cfg_attr(feature = "nightly", derive(TyEncodable, TyDecodable))]
 pub enum ConstKind<I: Interner> {
     /// A const generic parameter.
     Param(I::ParamConst),
@@ -47,6 +47,7 @@ pub enum ConstKind<I: Interner> {
     Expr(I::ExprConst),
 }
 
+#[cfg(feature = "nightly")]
 const fn const_kind_discriminant<I: Interner>(value: &ConstKind<I>) -> usize {
     match value {
         Param(_) => 0,
@@ -60,7 +61,8 @@ const fn const_kind_discriminant<I: Interner>(value: &ConstKind<I>) -> usize {
     }
 }
 
-impl<CTX: HashStableContext, I: Interner> HashStable<CTX> for ConstKind<I>
+#[cfg(feature = "nightly")]
+impl<CTX: crate::HashStableContext, I: Interner> HashStable<CTX> for ConstKind<I>
 where
     I::ParamConst: HashStable<CTX>,
     I::InferConst: HashStable<CTX>,
diff --git a/compiler/rustc_type_ir/src/fold.rs b/compiler/rustc_type_ir/src/fold.rs
index fc56400df16..8d402588398 100644
--- a/compiler/rustc_type_ir/src/fold.rs
+++ b/compiler/rustc_type_ir/src/fold.rs
@@ -45,12 +45,18 @@
 //! - u.fold_with(folder)
 //! ```
 
-use rustc_data_structures::sync::Lrc;
 use rustc_index::{Idx, IndexVec};
 use std::mem;
 
+use crate::Lrc;
 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.
 ///
@@ -79,7 +85,10 @@ pub trait TypeFoldable<I: Interner>: TypeVisitable<I> {
     /// folders. Do not override this method, to ensure coherence with
     /// `try_fold_with`.
     fn fold_with<F: TypeFolder<I>>(self, folder: &mut F) -> Self {
-        self.try_fold_with(folder).into_ok()
+        match self.try_fold_with(folder) {
+            Ok(t) => t,
+            Err(e) => match e {},
+        }
     }
 }
 
@@ -100,7 +109,10 @@ pub trait TypeSuperFoldable<I: Interner>: TypeFoldable<I> {
     /// infallible folders. Do not override this method, to ensure coherence
     /// with `try_super_fold_with`.
     fn super_fold_with<F: TypeFolder<I>>(self, folder: &mut F) -> Self {
-        self.try_super_fold_with(folder).into_ok()
+        match self.try_super_fold_with(folder) {
+            Ok(t) => t,
+            Err(e) => match e {},
+        }
     }
 }
 
@@ -113,7 +125,7 @@ pub trait TypeSuperFoldable<I: Interner>: TypeFoldable<I> {
 /// 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<I: Interner>: FallibleTypeFolder<I, Error = !> {
+pub trait TypeFolder<I: Interner>: FallibleTypeFolder<I, Error = Never> {
     fn interner(&self) -> I;
 
     fn fold_binder<T>(&mut self, t: I::Binder<T>) -> I::Binder<T>
@@ -208,13 +220,13 @@ impl<I: Interner, F> FallibleTypeFolder<I> for F
 where
     F: TypeFolder<I>,
 {
-    type Error = !;
+    type Error = Never;
 
     fn interner(&self) -> I {
         TypeFolder::interner(self)
     }
 
-    fn try_fold_binder<T>(&mut self, t: I::Binder<T>) -> Result<I::Binder<T>, !>
+    fn try_fold_binder<T>(&mut self, t: I::Binder<T>) -> Result<I::Binder<T>, Never>
     where
         T: TypeFoldable<I>,
         I::Binder<T>: TypeSuperFoldable<I>,
@@ -222,25 +234,25 @@ where
         Ok(self.fold_binder(t))
     }
 
-    fn try_fold_ty(&mut self, t: I::Ty) -> Result<I::Ty, !>
+    fn try_fold_ty(&mut self, t: I::Ty) -> Result<I::Ty, Never>
     where
         I::Ty: TypeSuperFoldable<I>,
     {
         Ok(self.fold_ty(t))
     }
 
-    fn try_fold_region(&mut self, r: I::Region) -> Result<I::Region, !> {
+    fn try_fold_region(&mut self, r: I::Region) -> Result<I::Region, Never> {
         Ok(self.fold_region(r))
     }
 
-    fn try_fold_const(&mut self, c: I::Const) -> Result<I::Const, !>
+    fn try_fold_const(&mut self, c: I::Const) -> Result<I::Const, Never>
     where
         I::Const: TypeSuperFoldable<I>,
     {
         Ok(self.fold_const(c))
     }
 
-    fn try_fold_predicate(&mut self, p: I::Predicate) -> Result<I::Predicate, !>
+    fn try_fold_predicate(&mut self, p: I::Predicate) -> Result<I::Predicate, Never>
     where
         I::Predicate: TypeSuperFoldable<I>,
     {
@@ -311,7 +323,7 @@ impl<I: Interner, T: TypeFoldable<I>> TypeFoldable<I> for Lrc<T> {
             // Call to `Lrc::make_mut` above guarantees that `unique` is the
             // sole reference to the contained value, so we can avoid doing
             // a checked `get_mut` here.
-            let slot = Lrc::get_mut_unchecked(&mut unique);
+            let slot = Lrc::get_mut(&mut unique).unwrap_unchecked();
 
             // Semantically move the contained type out from `unique`, fold
             // it, then move the folded value back into `unique`. Should
diff --git a/compiler/rustc_type_ir/src/lib.rs b/compiler/rustc_type_ir/src/lib.rs
index e8785fff2ef..ba558aa3418 100644
--- a/compiler/rustc_type_ir/src/lib.rs
+++ b/compiler/rustc_type_ir/src/lib.rs
@@ -1,25 +1,28 @@
-#![feature(associated_type_defaults)]
-#![feature(fmt_helpers_for_derive)]
-#![feature(get_mut_unchecked)]
-#![feature(min_specialization)]
-#![feature(never_type)]
-#![feature(new_uninit)]
-#![feature(rustc_attrs)]
-#![feature(unwrap_infallible)]
+#![cfg_attr(
+    feature = "nightly",
+    feature(associated_type_defaults, min_specialization, never_type, rustc_attrs)
+)]
 #![deny(rustc::untranslatable_diagnostic)]
 #![deny(rustc::diagnostic_outside_of_impl)]
-#![allow(internal_features)]
+#![cfg_attr(feature = "nightly", allow(internal_features))]
 
+#[cfg(feature = "nightly")]
 extern crate self as rustc_type_ir;
 
 #[macro_use]
 extern crate bitflags;
+#[cfg(feature = "nightly")]
 #[macro_use]
 extern crate rustc_macros;
 
+#[cfg(feature = "nightly")]
+use rustc_data_structures::sync::Lrc;
 use std::fmt;
 use std::hash::Hash;
+#[cfg(not(feature = "nightly"))]
+use std::sync::Arc as Lrc;
 
+#[cfg(feature = "nightly")]
 pub mod codec;
 pub mod fold;
 pub mod ty_info;
@@ -37,6 +40,7 @@ mod predicate_kind;
 mod region_kind;
 
 pub use canonical::*;
+#[cfg(feature = "nightly")]
 pub use codec::*;
 pub use const_kind::*;
 pub use debug::{DebugWithInfcx, InferCtxtLike, WithInfcx};
@@ -90,8 +94,9 @@ rustc_index::newtype_index! {
     /// is the outer fn.
     ///
     /// [dbi]: https://en.wikipedia.org/wiki/De_Bruijn_index
-    #[derive(HashStable_Generic)]
+    #[cfg_attr(feature = "nightly", derive(HashStable_Generic))]
     #[debug_format = "DebruijnIndex({})"]
+    #[gate_rustc_only]
     pub struct DebruijnIndex {
         const INNERMOST = 0;
     }
@@ -173,8 +178,9 @@ pub fn debug_bound_var<T: std::fmt::Write>(
     }
 }
 
-#[derive(Copy, Clone, PartialEq, Eq, Decodable, Encodable, Hash, HashStable_Generic)]
-#[rustc_pass_by_value]
+#[derive(Copy, Clone, PartialEq, Eq)]
+#[cfg_attr(feature = "nightly", derive(Decodable, Encodable, Hash, HashStable_Generic))]
+#[cfg_attr(feature = "nightly", rustc_pass_by_value)]
 pub enum Variance {
     Covariant,     // T<A> <: T<B> iff A <: B -- e.g., function return type
     Invariant,     // T<A> <: T<B> iff B == A -- e.g., type of mutable cell
@@ -289,8 +295,9 @@ rustc_index::newtype_index! {
     /// 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)]
+    #[cfg_attr(feature = "nightly", derive(HashStable_Generic))]
     #[debug_format = "U{}"]
+    #[gate_rustc_only]
     pub struct UniverseIndex {}
 }
 
diff --git a/compiler/rustc_type_ir/src/predicate_kind.rs b/compiler/rustc_type_ir/src/predicate_kind.rs
index 48662d42642..c2ba6afc8d0 100644
--- a/compiler/rustc_type_ir/src/predicate_kind.rs
+++ b/compiler/rustc_type_ir/src/predicate_kind.rs
@@ -1,16 +1,17 @@
+#[cfg(feature = "nightly")]
 use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
 use std::fmt;
 use std::ops::ControlFlow;
 
 use crate::fold::{FallibleTypeFolder, TypeFoldable};
 use crate::visit::{TypeVisitable, TypeVisitor};
-use crate::{HashStableContext, Interner};
+use crate::Interner;
 
 /// A clause is something that can appear in where bounds or be inferred
 /// by implied bounds.
 #[derive(derivative::Derivative)]
 #[derivative(Clone(bound = ""), Hash(bound = ""))]
-#[derive(TyEncodable, TyDecodable)]
+#[cfg_attr(feature = "nightly", derive(TyEncodable, TyDecodable))]
 pub enum ClauseKind<I: Interner> {
     /// Corresponds to `where Foo: Bar<A, B, C>`. `Foo` here would be
     /// the `Self` type of the trait reference and `A`, `B`, and `C`
@@ -67,6 +68,7 @@ impl<I: Interner> PartialEq for ClauseKind<I> {
 
 impl<I: Interner> Eq for ClauseKind<I> {}
 
+#[cfg(feature = "nightly")]
 fn clause_kind_discriminant<I: Interner>(value: &ClauseKind<I>) -> usize {
     match value {
         ClauseKind::Trait(_) => 0,
@@ -79,7 +81,8 @@ fn clause_kind_discriminant<I: Interner>(value: &ClauseKind<I>) -> usize {
     }
 }
 
-impl<CTX: HashStableContext, I: Interner> HashStable<CTX> for ClauseKind<I>
+#[cfg(feature = "nightly")]
+impl<CTX: crate::HashStableContext, I: Interner> HashStable<CTX> for ClauseKind<I>
 where
     I::Ty: HashStable<CTX>,
     I::Const: HashStable<CTX>,
@@ -161,7 +164,7 @@ where
 
 #[derive(derivative::Derivative)]
 #[derivative(Clone(bound = ""), Hash(bound = ""))]
-#[derive(TyEncodable, TyDecodable)]
+#[cfg_attr(feature = "nightly", derive(TyEncodable, TyDecodable))]
 pub enum PredicateKind<I: Interner> {
     /// Prove a clause
     Clause(ClauseKind<I>),
@@ -239,6 +242,7 @@ impl<I: Interner> PartialEq for PredicateKind<I> {
 
 impl<I: Interner> Eq for PredicateKind<I> {}
 
+#[cfg(feature = "nightly")]
 fn predicate_kind_discriminant<I: Interner>(value: &PredicateKind<I>) -> usize {
     match value {
         PredicateKind::Clause(_) => 0,
@@ -252,7 +256,8 @@ fn predicate_kind_discriminant<I: Interner>(value: &PredicateKind<I>) -> usize {
     }
 }
 
-impl<CTX: HashStableContext, I: Interner> HashStable<CTX> for PredicateKind<I>
+#[cfg(feature = "nightly")]
+impl<CTX: crate::HashStableContext, I: Interner> HashStable<CTX> for PredicateKind<I>
 where
     I::DefId: HashStable<CTX>,
     I::Const: HashStable<CTX>,
@@ -361,7 +366,7 @@ where
 }
 
 #[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, Copy)]
-#[derive(HashStable_Generic, Encodable, Decodable)]
+#[cfg_attr(feature = "nightly", derive(HashStable_Generic, Encodable, Decodable))]
 pub enum AliasRelationDirection {
     Equate,
     Subtype,
diff --git a/compiler/rustc_type_ir/src/region_kind.rs b/compiler/rustc_type_ir/src/region_kind.rs
index 5d3ce49bc8f..ddd10db1c6c 100644
--- a/compiler/rustc_type_ir/src/region_kind.rs
+++ b/compiler/rustc_type_ir/src/region_kind.rs
@@ -1,8 +1,8 @@
-use rustc_data_structures::stable_hasher::HashStable;
-use rustc_data_structures::stable_hasher::StableHasher;
+#[cfg(feature = "nightly")]
+use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
 use std::fmt;
 
-use crate::{DebruijnIndex, DebugWithInfcx, HashStableContext, InferCtxtLike, Interner, WithInfcx};
+use crate::{DebruijnIndex, DebugWithInfcx, InferCtxtLike, Interner, WithInfcx};
 
 use self::RegionKind::*;
 
@@ -121,7 +121,7 @@ use self::RegionKind::*;
     Ord = "feature_allow_slow_enum",
     Hash(bound = "")
 )]
-#[derive(TyEncodable, TyDecodable)]
+#[cfg_attr(feature = "nightly", derive(TyEncodable, TyDecodable))]
 pub enum RegionKind<I: Interner> {
     /// A region parameter; for example `'a` in `impl<'a> Trait for &'a ()`.
     ///
@@ -261,8 +261,9 @@ impl<I: Interner> fmt::Debug for RegionKind<I> {
     }
 }
 
+#[cfg(feature = "nightly")]
 // This is not a derived impl because a derive would require `I: HashStable`
-impl<CTX: HashStableContext, I: Interner> HashStable<CTX> for RegionKind<I>
+impl<CTX: crate::HashStableContext, I: Interner> HashStable<CTX> for RegionKind<I>
 where
     I::EarlyParamRegion: HashStable<CTX>,
     I::BoundRegion: HashStable<CTX>,
diff --git a/compiler/rustc_type_ir/src/ty_info.rs b/compiler/rustc_type_ir/src/ty_info.rs
index d986e310c32..0e4930552c2 100644
--- a/compiler/rustc_type_ir/src/ty_info.rs
+++ b/compiler/rustc_type_ir/src/ty_info.rs
@@ -1,4 +1,6 @@
+#[cfg(feature = "nightly")]
 use rustc_data_structures::fingerprint::Fingerprint;
+#[cfg(feature = "nightly")]
 use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
 use std::cmp::Ordering;
 use std::hash::{Hash, Hasher};
@@ -16,6 +18,8 @@ use crate::{DebruijnIndex, TypeFlags};
 #[derive(Copy, Clone)]
 pub struct WithCachedTypeInfo<T> {
     pub internee: T,
+
+    #[cfg(feature = "nightly")]
     pub stable_hash: Fingerprint,
 
     /// This field provides fast access to information that is also contained
@@ -81,14 +85,16 @@ impl<T> Deref for WithCachedTypeInfo<T> {
 impl<T: Hash> Hash for WithCachedTypeInfo<T> {
     #[inline]
     fn hash<H: Hasher>(&self, s: &mut H) {
+        #[cfg(feature = "nightly")]
         if self.stable_hash != Fingerprint::ZERO {
-            self.stable_hash.hash(s)
-        } else {
-            self.internee.hash(s)
+            return self.stable_hash.hash(s);
         }
+
+        self.internee.hash(s)
     }
 }
 
+#[cfg(feature = "nightly")]
 impl<T: HashStable<CTX>, CTX> HashStable<CTX> for WithCachedTypeInfo<T> {
     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/ty_kind.rs b/compiler/rustc_type_ir/src/ty_kind.rs
index 09a9a332269..f31c5069b15 100644
--- a/compiler/rustc_type_ir/src/ty_kind.rs
+++ b/compiler/rustc_type_ir/src/ty_kind.rs
@@ -1,11 +1,11 @@
 #![allow(rustc::usage_of_ty_tykind)]
 
+#[cfg(feature = "nightly")]
 use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
+#[cfg(feature = "nightly")]
 use rustc_data_structures::unify::{EqUnifyValue, UnifyKey};
 use std::fmt;
-use std::mem::discriminant;
 
-use crate::HashStableContext;
 use crate::Interner;
 use crate::{DebruijnIndex, DebugWithInfcx, InferCtxtLike, WithInfcx};
 
@@ -13,8 +13,8 @@ use self::TyKind::*;
 
 /// The movability of a coroutine / closure literal:
 /// whether a coroutine contains self-references, causing it to be `!Unpin`.
-#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Encodable, Decodable, Debug, Copy)]
-#[derive(HashStable_Generic)]
+#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, Copy)]
+#[cfg_attr(feature = "nightly", derive(Encodable, Decodable, HashStable_Generic))]
 pub enum Movability {
     /// May contain self-references, `!Unpin`.
     Static,
@@ -23,7 +23,7 @@ pub enum Movability {
 }
 
 #[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, Copy)]
-#[derive(HashStable_Generic, Encodable, Decodable)]
+#[cfg_attr(feature = "nightly", derive(Encodable, Decodable, HashStable_Generic))]
 pub enum Mutability {
     // N.B. Order is deliberate, so that Not < Mut
     Not,
@@ -75,7 +75,7 @@ impl Mutability {
 
 /// 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,
@@ -89,7 +89,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 `<Type as Trait>::AssocType`.
     /// Can get normalized away if monomorphic enough.
@@ -109,7 +109,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")]
 #[derive(derivative::Derivative)]
 #[derivative(
     Clone(bound = ""),
@@ -119,7 +119,7 @@ pub enum AliasKind {
     Ord = "feature_allow_slow_enum",
     Hash(bound = "")
 )]
-#[derive(TyEncodable, TyDecodable)]
+#[cfg_attr(feature = "nightly", derive(TyEncodable, TyDecodable))]
 pub enum TyKind<I: Interner> {
     /// The primitive boolean type. Written as `bool`.
     Bool,
@@ -407,7 +407,7 @@ impl<I: Interner> DebugWithInfcx<I> for TyKind<I> {
 
                 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)),
@@ -423,7 +423,7 @@ impl<I: Interner> DebugWithInfcx<I> for TyKind<I> {
                 Mutability::Mut => write!(f, "&{:?} mut {:?}", &this.wrap(r), &this.wrap(t)),
                 Mutability::Not => 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)),
@@ -431,10 +431,12 @@ impl<I: Interner> DebugWithInfcx<I> for TyKind<I> {
                     write!(f, "dyn* {:?} + {:?}", &this.wrap(p), &this.wrap(r))
                 }
             },
-            Closure(d, s) => f.debug_tuple_field2_finish("Closure", d, &this.wrap(s)),
-            Coroutine(d, s, m) => f.debug_tuple_field3_finish("Coroutine", d, &this.wrap(s), m),
+            Closure(d, s) => f.debug_tuple("Closure").field(d).field(&this.wrap(s)).finish(),
+            Coroutine(d, s, m) => {
+                f.debug_tuple("Coroutine").field(d).field(&this.wrap(s)).field(m).finish()
+            }
             CoroutineWitness(d, s) => {
-                f.debug_tuple_field2_finish("CoroutineWitness", d, &this.wrap(s))
+                f.debug_tuple("CoroutineWitness").field(d).field(&this.wrap(s)).finish()
             }
             Never => write!(f, "!"),
             Tuple(t) => {
@@ -453,7 +455,7 @@ impl<I: Interner> DebugWithInfcx<I> for TyKind<I> {
                 }
                 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:?}"),
@@ -471,8 +473,9 @@ impl<I: Interner> fmt::Debug for TyKind<I> {
 }
 
 // This is not a derived impl because a derive would require `I: HashStable`
+#[cfg(feature = "nightly")]
 #[allow(rustc::usage_of_ty_tykind)]
-impl<CTX: HashStableContext, I: Interner> HashStable<CTX> for TyKind<I>
+impl<CTX: crate::HashStableContext, I: Interner> HashStable<CTX> for TyKind<I>
 where
     I::AdtDef: HashStable<CTX>,
     I::DefId: HashStable<CTX>,
@@ -583,7 +586,7 @@ where
 }
 
 #[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,
@@ -641,7 +644,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,
@@ -699,7 +702,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,
@@ -733,18 +736,21 @@ pub struct FloatVarValue(pub FloatTy);
 rustc_index::newtype_index! {
     /// A **ty**pe **v**ariable **ID**.
     #[debug_format = "?{}t"]
+    #[gate_rustc_only]
     pub struct TyVid {}
 }
 
 rustc_index::newtype_index! {
     /// An **int**egral (`u32`, `i32`, `usize`, etc.) type **v**ariable **ID**.
     #[debug_format = "?{}i"]
+    #[gate_rustc_only]
     pub struct IntVid {}
 }
 
 rustc_index::newtype_index! {
     /// A **float**ing-point (`f32` or `f64`) type **v**ariable **ID**.
     #[debug_format = "?{}f"]
+    #[gate_rustc_only]
     pub struct FloatVid {}
 }
 
@@ -753,7 +759,8 @@ rustc_index::newtype_index! {
 /// 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),
@@ -786,6 +793,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]
@@ -801,8 +809,10 @@ impl UnifyKey for TyVid {
     }
 }
 
+#[cfg(feature = "nightly")]
 impl EqUnifyValue for IntVarValue {}
 
+#[cfg(feature = "nightly")]
 impl UnifyKey for IntVid {
     type Value = Option<IntVarValue>;
     #[inline] // make this function eligible for inlining - it is quite hot.
@@ -818,8 +828,10 @@ impl UnifyKey for IntVid {
     }
 }
 
+#[cfg(feature = "nightly")]
 impl EqUnifyValue for FloatVarValue {}
 
+#[cfg(feature = "nightly")]
 impl UnifyKey for FloatVid {
     type Value = Option<FloatVarValue>;
     #[inline]
@@ -835,10 +847,11 @@ impl UnifyKey for FloatVid {
     }
 }
 
+#[cfg(feature = "nightly")]
 impl<CTX> HashStable<CTX> for InferTy {
     fn hash_stable(&self, ctx: &mut CTX, hasher: &mut StableHasher) {
         use InferTy::*;
-        discriminant(self).hash_stable(ctx, hasher);
+        std::mem::discriminant(self).hash_stable(ctx, hasher);
         match self {
             TyVar(_) | IntVar(_) | FloatVar(_) => {
                 panic!("type variables should not be hashed: {self:?}")
diff --git a/compiler/rustc_type_ir/src/visit.rs b/compiler/rustc_type_ir/src/visit.rs
index 9c7b8156b04..7aa99004667 100644
--- a/compiler/rustc_type_ir/src/visit.rs
+++ b/compiler/rustc_type_ir/src/visit.rs
@@ -41,12 +41,12 @@
 //! - u.visit_with(visitor)
 //! ```
 
-use rustc_data_structures::sync::Lrc;
 use rustc_index::{Idx, IndexVec};
 use std::fmt;
 use std::ops::ControlFlow;
 
 use crate::Interner;
+use crate::Lrc;
 
 /// This trait is implemented for every type that can be visited,
 /// providing the skeleton of the traversal.
@@ -82,8 +82,12 @@ pub trait TypeSuperVisitable<I: Interner>: TypeVisitable<I> {
 /// 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<I: Interner>: Sized {
+    #[cfg(feature = "nightly")]
     type BreakTy = !;
 
+    #[cfg(not(feature = "nightly"))]
+    type BreakTy;
+
     fn visit_binder<T: TypeVisitable<I>>(&mut self, t: &I::Binder<T>) -> ControlFlow<Self::BreakTy>
     where
         I::Binder<T>: TypeSuperVisitable<I>,