Begin nightly-ifying rustc_type_ir

This commit is contained in:
Michael Goulet 2023-10-24 00:16:14 +00:00
parent 2831701757
commit 4506681e2f
19 changed files with 214 additions and 102 deletions

View file

@ -4041,11 +4041,22 @@ name = "rustc_index"
version = "0.0.0" version = "0.0.0"
dependencies = [ dependencies = [
"arrayvec", "arrayvec",
"rustc_index_macros",
"rustc_macros", "rustc_macros",
"rustc_serialize", "rustc_serialize",
"smallvec", "smallvec",
] ]
[[package]]
name = "rustc_index_macros"
version = "0.0.0"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.29",
"synstructure",
]
[[package]] [[package]]
name = "rustc_infer" name = "rustc_infer"
version = "0.0.0" version = "0.0.0"

View file

@ -6,6 +6,7 @@ edition = "2021"
[dependencies] [dependencies]
# tidy-alphabetical-start # tidy-alphabetical-start
arrayvec = { version = "0.7", default-features = false } 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_macros = { path = "../rustc_macros", optional = true }
rustc_serialize = { path = "../rustc_serialize", optional = true } rustc_serialize = { path = "../rustc_serialize", optional = true }
smallvec = "1.8.1" smallvec = "1.8.1"
@ -14,5 +15,5 @@ smallvec = "1.8.1"
[features] [features]
# tidy-alphabetical-start # tidy-alphabetical-start
default = ["nightly"] default = ["nightly"]
nightly = ["rustc_serialize", "rustc_macros"] nightly = ["rustc_serialize", "rustc_macros", "rustc_index_macros/nightly"]
# tidy-alphabetical-end # tidy-alphabetical-end

View file

@ -25,8 +25,7 @@ mod vec;
pub use {idx::Idx, slice::IndexSlice, vec::IndexVec}; pub use {idx::Idx, slice::IndexSlice, vec::IndexVec};
#[cfg(feature = "rustc_macros")] pub use rustc_index_macros::newtype_index;
pub use rustc_macros::newtype_index;
/// Type size assertion. The first argument is a type and the second argument is its expected size. /// Type size assertion. The first argument is a type and the second argument is its expected size.
/// ///

View file

@ -1,7 +1,7 @@
// Allows the macro invocation below to work // Allows the macro invocation below to work
use crate as rustc_index; use crate as rustc_index;
rustc_macros::newtype_index! { crate::newtype_index! {
#[max = 0xFFFF_FFFA] #[max = 0xFFFF_FFFA]
struct MyIdx {} struct MyIdx {}
} }

View file

@ -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 = []

View file

@ -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)
}

View file

@ -24,9 +24,16 @@ impl Parse for Newtype {
let mut consts = Vec::new(); let mut consts = Vec::new();
let mut encodable = true; let mut encodable = true;
let mut ord = 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() { attrs.retain(|attr| match attr.path().get_ident() {
Some(ident) => match &*ident.to_string() { 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" => { "custom_encodable" => {
encodable = false; encodable = false;
false false
@ -88,11 +95,13 @@ impl Parse for Newtype {
let encodable_impls = if encodable { let encodable_impls = if encodable {
quote! { quote! {
#gate_rustc_only
impl<D: ::rustc_serialize::Decoder> ::rustc_serialize::Decodable<D> for #name { impl<D: ::rustc_serialize::Decoder> ::rustc_serialize::Decodable<D> for #name {
fn decode(d: &mut D) -> Self { fn decode(d: &mut D) -> Self {
Self::from_u32(d.read_u32()) Self::from_u32(d.read_u32())
} }
} }
#gate_rustc_only
impl<E: ::rustc_serialize::Encoder> ::rustc_serialize::Encodable<E> for #name { impl<E: ::rustc_serialize::Encoder> ::rustc_serialize::Encodable<E> for #name {
fn encode(&self, e: &mut E) { fn encode(&self, e: &mut E) {
e.emit_u32(self.private); e.emit_u32(self.private);
@ -110,6 +119,7 @@ impl Parse for Newtype {
let step = if ord { let step = if ord {
quote! { quote! {
#gate_rustc_only
impl ::std::iter::Step for #name { impl ::std::iter::Step for #name {
#[inline] #[inline]
fn steps_between(start: &Self, end: &Self) -> Option<usize> { 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. // Safety: The implementation of `Step` upholds all invariants.
#gate_rustc_only
unsafe impl ::std::iter::TrustedStep for #name {} unsafe impl ::std::iter::TrustedStep for #name {}
} }
} else { } else {
@ -148,6 +159,7 @@ impl Parse for Newtype {
let spec_partial_eq_impl = if let Lit::Int(max) = &max { let spec_partial_eq_impl = if let Lit::Int(max) = &max {
if let Ok(max_val) = max.base10_parse::<u32>() { if let Ok(max_val) = max.base10_parse::<u32>() {
quote! { quote! {
#gate_rustc_only
impl core::option::SpecOptionPartialEq for #name { impl core::option::SpecOptionPartialEq for #name {
#[inline] #[inline]
fn eq(l: &Option<Self>, r: &Option<Self>) -> bool { fn eq(l: &Option<Self>, r: &Option<Self>) -> bool {
@ -173,8 +185,8 @@ impl Parse for Newtype {
Ok(Self(quote! { Ok(Self(quote! {
#(#attrs)* #(#attrs)*
#[derive(Clone, Copy, PartialEq, Eq, Hash, #(#derive_paths),*)] #[derive(Clone, Copy, PartialEq, Eq, Hash, #(#derive_paths),*)]
#[rustc_layout_scalar_valid_range_end(#max)] #[cfg_attr(#gate_rustc_only_cfg, rustc_layout_scalar_valid_range_end(#max))]
#[rustc_pass_by_value] #[cfg_attr(#gate_rustc_only_cfg, rustc_pass_by_value)]
#vis struct #name { #vis struct #name {
private: u32, private: u32,
} }

View file

@ -19,7 +19,6 @@ mod current_version;
mod diagnostics; mod diagnostics;
mod hash_stable; mod hash_stable;
mod lift; mod lift;
mod newtype;
mod query; mod query;
mod serialize; mod serialize;
mod symbols; mod symbols;
@ -44,27 +43,6 @@ pub fn symbols(input: TokenStream) -> TokenStream {
symbols::symbols(input.into()).into() 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, attributes(stable_hasher)] => hash_stable::hash_stable_derive);
decl_derive!( decl_derive!(
[HashStable_Generic, attributes(stable_hasher)] => [HashStable_Generic, attributes(stable_hasher)] =>

View file

@ -88,8 +88,8 @@ use rustc_data_structures::fx::{FxHashMap, FxIndexSet};
use rustc_data_structures::graph::dominators::Dominators; use rustc_data_structures::graph::dominators::Dominators;
use rustc_hir::def::DefKind; use rustc_hir::def::DefKind;
use rustc_index::bit_set::BitSet; use rustc_index::bit_set::BitSet;
use rustc_index::newtype_index;
use rustc_index::IndexVec; use rustc_index::IndexVec;
use rustc_macros::newtype_index;
use rustc_middle::mir::interpret::GlobalAlloc; use rustc_middle::mir::interpret::GlobalAlloc;
use rustc_middle::mir::visit::*; use rustc_middle::mir::visit::*;
use rustc_middle::mir::*; use rustc_middle::mir::*;

View file

@ -7,9 +7,20 @@ edition = "2021"
# tidy-alphabetical-start # tidy-alphabetical-start
bitflags = "1.2.1" bitflags = "1.2.1"
derivative = "2.2.0" derivative = "2.2.0"
rustc_data_structures = { path = "../rustc_data_structures" } rustc_data_structures = { path = "../rustc_data_structures", optional = true }
rustc_index = { path = "../rustc_index" } rustc_index = { path = "../rustc_index", default-features = false }
rustc_macros = { path = "../rustc_macros" } rustc_macros = { path = "../rustc_macros", optional = true }
rustc_serialize = { path = "../rustc_serialize" } rustc_serialize = { path = "../rustc_serialize", optional = true }
smallvec = { version = "1.8.1", features = ["union", "may_dangle"] } smallvec = { version = "1.8.1" }
# tidy-alphabetical-end # tidy-alphabetical-end
[features]
default = ["nightly"]
nightly = [
"smallvec/may_dangle",
"smallvec/union",
"rustc_index/nightly",
"rustc_serialize",
"rustc_data_structures",
"rustc_macros",
]

View file

@ -2,18 +2,19 @@ use std::fmt;
use std::hash::Hash; use std::hash::Hash;
use std::ops::ControlFlow; use std::ops::ControlFlow;
#[cfg(feature = "nightly")]
use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
use crate::fold::{FallibleTypeFolder, TypeFoldable}; use crate::fold::{FallibleTypeFolder, TypeFoldable};
use crate::visit::{TypeVisitable, TypeVisitor}; use crate::visit::{TypeVisitable, TypeVisitor};
use crate::{HashStableContext, Interner, UniverseIndex}; use crate::{Interner, UniverseIndex};
/// A "canonicalized" type `V` is one where all free inference /// A "canonicalized" type `V` is one where all free inference
/// variables have been rewritten to "canonical vars". These are /// variables have been rewritten to "canonical vars". These are
/// numbered starting from 0 in order of first appearance. /// numbered starting from 0 in order of first appearance.
#[derive(derivative::Derivative)] #[derive(derivative::Derivative)]
#[derivative(Clone(bound = "V: Clone"), Hash(bound = "V: Hash"))] #[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 struct Canonical<I: Interner, V> {
pub value: V, pub value: V,
pub max_universe: UniverseIndex, 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 where
I::CanonicalVars: HashStable<CTX>, I::CanonicalVars: HashStable<CTX>,
{ {

View file

@ -1,8 +1,8 @@
use rustc_data_structures::stable_hasher::HashStable; #[cfg(feature = "nightly")]
use rustc_data_structures::stable_hasher::StableHasher; use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
use std::fmt; use std::fmt;
use crate::{DebruijnIndex, DebugWithInfcx, HashStableContext, InferCtxtLike, Interner, WithInfcx}; use crate::{DebruijnIndex, DebugWithInfcx, InferCtxtLike, Interner, WithInfcx};
use self::ConstKind::*; use self::ConstKind::*;
@ -16,7 +16,7 @@ use self::ConstKind::*;
Ord = "feature_allow_slow_enum", Ord = "feature_allow_slow_enum",
Hash(bound = "") Hash(bound = "")
)] )]
#[derive(TyEncodable, TyDecodable)] #[cfg_attr(feature = "nightly", derive(TyEncodable, TyDecodable))]
pub enum ConstKind<I: Interner> { pub enum ConstKind<I: Interner> {
/// A const generic parameter. /// A const generic parameter.
Param(I::ParamConst), Param(I::ParamConst),
@ -47,6 +47,7 @@ pub enum ConstKind<I: Interner> {
Expr(I::ExprConst), Expr(I::ExprConst),
} }
#[cfg(feature = "nightly")]
const fn const_kind_discriminant<I: Interner>(value: &ConstKind<I>) -> usize { const fn const_kind_discriminant<I: Interner>(value: &ConstKind<I>) -> usize {
match value { match value {
Param(_) => 0, 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 where
I::ParamConst: HashStable<CTX>, I::ParamConst: HashStable<CTX>,
I::InferConst: HashStable<CTX>, I::InferConst: HashStable<CTX>,

View file

@ -45,12 +45,18 @@
//! - u.fold_with(folder) //! - u.fold_with(folder)
//! ``` //! ```
use rustc_data_structures::sync::Lrc;
use rustc_index::{Idx, IndexVec}; use rustc_index::{Idx, IndexVec};
use std::mem; use std::mem;
use crate::Lrc;
use crate::{visit::TypeVisitable, Interner}; 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, /// This trait is implemented for every type that can be folded,
/// providing the skeleton of the traversal. /// 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 /// folders. Do not override this method, to ensure coherence with
/// `try_fold_with`. /// `try_fold_with`.
fn fold_with<F: TypeFolder<I>>(self, folder: &mut F) -> Self { 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 /// infallible folders. Do not override this method, to ensure coherence
/// with `try_super_fold_with`. /// with `try_super_fold_with`.
fn super_fold_with<F: TypeFolder<I>>(self, folder: &mut F) -> Self { 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 /// A blanket implementation of [`FallibleTypeFolder`] will defer to
/// the infallible methods of this trait to ensure that the two APIs /// the infallible methods of this trait to ensure that the two APIs
/// are coherent. /// are coherent.
pub trait TypeFolder<I: Interner>: FallibleTypeFolder<I, Error = !> { pub trait TypeFolder<I: Interner>: FallibleTypeFolder<I, Error = Never> {
fn interner(&self) -> I; fn interner(&self) -> I;
fn fold_binder<T>(&mut self, t: I::Binder<T>) -> I::Binder<T> 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 where
F: TypeFolder<I>, F: TypeFolder<I>,
{ {
type Error = !; type Error = Never;
fn interner(&self) -> I { fn interner(&self) -> I {
TypeFolder::interner(self) 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 where
T: TypeFoldable<I>, T: TypeFoldable<I>,
I::Binder<T>: TypeSuperFoldable<I>, I::Binder<T>: TypeSuperFoldable<I>,
@ -222,25 +234,25 @@ where
Ok(self.fold_binder(t)) 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 where
I::Ty: TypeSuperFoldable<I>, I::Ty: TypeSuperFoldable<I>,
{ {
Ok(self.fold_ty(t)) 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)) 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 where
I::Const: TypeSuperFoldable<I>, I::Const: TypeSuperFoldable<I>,
{ {
Ok(self.fold_const(c)) 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 where
I::Predicate: TypeSuperFoldable<I>, 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 // Call to `Lrc::make_mut` above guarantees that `unique` is the
// sole reference to the contained value, so we can avoid doing // sole reference to the contained value, so we can avoid doing
// a checked `get_mut` here. // 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 // Semantically move the contained type out from `unique`, fold
// it, then move the folded value back into `unique`. Should // it, then move the folded value back into `unique`. Should

View file

@ -1,25 +1,28 @@
#![feature(associated_type_defaults)] #![cfg_attr(
#![feature(fmt_helpers_for_derive)] feature = "nightly",
#![feature(get_mut_unchecked)] feature(associated_type_defaults, min_specialization, never_type, rustc_attrs)
#![feature(min_specialization)] )]
#![feature(never_type)]
#![feature(new_uninit)]
#![feature(rustc_attrs)]
#![feature(unwrap_infallible)]
#![deny(rustc::untranslatable_diagnostic)] #![deny(rustc::untranslatable_diagnostic)]
#![deny(rustc::diagnostic_outside_of_impl)] #![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; extern crate self as rustc_type_ir;
#[macro_use] #[macro_use]
extern crate bitflags; extern crate bitflags;
#[cfg(feature = "nightly")]
#[macro_use] #[macro_use]
extern crate rustc_macros; extern crate rustc_macros;
#[cfg(feature = "nightly")]
use rustc_data_structures::sync::Lrc;
use std::fmt; use std::fmt;
use std::hash::Hash; use std::hash::Hash;
#[cfg(not(feature = "nightly"))]
use std::sync::Arc as Lrc;
#[cfg(feature = "nightly")]
pub mod codec; pub mod codec;
pub mod fold; pub mod fold;
pub mod ty_info; pub mod ty_info;
@ -37,6 +40,7 @@ mod predicate_kind;
mod region_kind; mod region_kind;
pub use canonical::*; pub use canonical::*;
#[cfg(feature = "nightly")]
pub use codec::*; pub use codec::*;
pub use const_kind::*; pub use const_kind::*;
pub use debug::{DebugWithInfcx, InferCtxtLike, WithInfcx}; pub use debug::{DebugWithInfcx, InferCtxtLike, WithInfcx};
@ -90,8 +94,9 @@ rustc_index::newtype_index! {
/// is the outer fn. /// is the outer fn.
/// ///
/// [dbi]: https://en.wikipedia.org/wiki/De_Bruijn_index /// [dbi]: https://en.wikipedia.org/wiki/De_Bruijn_index
#[derive(HashStable_Generic)] #[cfg_attr(feature = "nightly", derive(HashStable_Generic))]
#[debug_format = "DebruijnIndex({})"] #[debug_format = "DebruijnIndex({})"]
#[gate_rustc_only]
pub struct DebruijnIndex { pub struct DebruijnIndex {
const INNERMOST = 0; 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)] #[derive(Copy, Clone, PartialEq, Eq)]
#[rustc_pass_by_value] #[cfg_attr(feature = "nightly", derive(Decodable, Encodable, Hash, HashStable_Generic))]
#[cfg_attr(feature = "nightly", rustc_pass_by_value)]
pub enum Variance { pub enum Variance {
Covariant, // T<A> <: T<B> iff A <: B -- e.g., function return type 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 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 /// declared, but a type name in a non-zero universe is a placeholder
/// type -- an idealized representative of "types in general" that we /// type -- an idealized representative of "types in general" that we
/// use for checking generic functions. /// use for checking generic functions.
#[derive(HashStable_Generic)] #[cfg_attr(feature = "nightly", derive(HashStable_Generic))]
#[debug_format = "U{}"] #[debug_format = "U{}"]
#[gate_rustc_only]
pub struct UniverseIndex {} pub struct UniverseIndex {}
} }

View file

@ -1,16 +1,17 @@
#[cfg(feature = "nightly")]
use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
use std::fmt; use std::fmt;
use std::ops::ControlFlow; use std::ops::ControlFlow;
use crate::fold::{FallibleTypeFolder, TypeFoldable}; use crate::fold::{FallibleTypeFolder, TypeFoldable};
use crate::visit::{TypeVisitable, TypeVisitor}; 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 /// A clause is something that can appear in where bounds or be inferred
/// by implied bounds. /// by implied bounds.
#[derive(derivative::Derivative)] #[derive(derivative::Derivative)]
#[derivative(Clone(bound = ""), Hash(bound = ""))] #[derivative(Clone(bound = ""), Hash(bound = ""))]
#[derive(TyEncodable, TyDecodable)] #[cfg_attr(feature = "nightly", derive(TyEncodable, TyDecodable))]
pub enum ClauseKind<I: Interner> { pub enum ClauseKind<I: Interner> {
/// Corresponds to `where Foo: Bar<A, B, C>`. `Foo` here would be /// Corresponds to `where Foo: Bar<A, B, C>`. `Foo` here would be
/// the `Self` type of the trait reference and `A`, `B`, and `C` /// 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> {} impl<I: Interner> Eq for ClauseKind<I> {}
#[cfg(feature = "nightly")]
fn clause_kind_discriminant<I: Interner>(value: &ClauseKind<I>) -> usize { fn clause_kind_discriminant<I: Interner>(value: &ClauseKind<I>) -> usize {
match value { match value {
ClauseKind::Trait(_) => 0, 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 where
I::Ty: HashStable<CTX>, I::Ty: HashStable<CTX>,
I::Const: HashStable<CTX>, I::Const: HashStable<CTX>,
@ -161,7 +164,7 @@ where
#[derive(derivative::Derivative)] #[derive(derivative::Derivative)]
#[derivative(Clone(bound = ""), Hash(bound = ""))] #[derivative(Clone(bound = ""), Hash(bound = ""))]
#[derive(TyEncodable, TyDecodable)] #[cfg_attr(feature = "nightly", derive(TyEncodable, TyDecodable))]
pub enum PredicateKind<I: Interner> { pub enum PredicateKind<I: Interner> {
/// Prove a clause /// Prove a clause
Clause(ClauseKind<I>), Clause(ClauseKind<I>),
@ -239,6 +242,7 @@ impl<I: Interner> PartialEq for PredicateKind<I> {
impl<I: Interner> Eq for PredicateKind<I> {} impl<I: Interner> Eq for PredicateKind<I> {}
#[cfg(feature = "nightly")]
fn predicate_kind_discriminant<I: Interner>(value: &PredicateKind<I>) -> usize { fn predicate_kind_discriminant<I: Interner>(value: &PredicateKind<I>) -> usize {
match value { match value {
PredicateKind::Clause(_) => 0, 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 where
I::DefId: HashStable<CTX>, I::DefId: HashStable<CTX>,
I::Const: HashStable<CTX>, I::Const: HashStable<CTX>,
@ -361,7 +366,7 @@ where
} }
#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, Copy)] #[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 { pub enum AliasRelationDirection {
Equate, Equate,
Subtype, Subtype,

View file

@ -1,8 +1,8 @@
use rustc_data_structures::stable_hasher::HashStable; #[cfg(feature = "nightly")]
use rustc_data_structures::stable_hasher::StableHasher; use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
use std::fmt; use std::fmt;
use crate::{DebruijnIndex, DebugWithInfcx, HashStableContext, InferCtxtLike, Interner, WithInfcx}; use crate::{DebruijnIndex, DebugWithInfcx, InferCtxtLike, Interner, WithInfcx};
use self::RegionKind::*; use self::RegionKind::*;
@ -121,7 +121,7 @@ use self::RegionKind::*;
Ord = "feature_allow_slow_enum", Ord = "feature_allow_slow_enum",
Hash(bound = "") Hash(bound = "")
)] )]
#[derive(TyEncodable, TyDecodable)] #[cfg_attr(feature = "nightly", derive(TyEncodable, TyDecodable))]
pub enum RegionKind<I: Interner> { pub enum RegionKind<I: Interner> {
/// A region parameter; for example `'a` in `impl<'a> Trait for &'a ()`. /// 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` // 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 where
I::EarlyParamRegion: HashStable<CTX>, I::EarlyParamRegion: HashStable<CTX>,
I::BoundRegion: HashStable<CTX>, I::BoundRegion: HashStable<CTX>,

View file

@ -1,4 +1,6 @@
#[cfg(feature = "nightly")]
use rustc_data_structures::fingerprint::Fingerprint; use rustc_data_structures::fingerprint::Fingerprint;
#[cfg(feature = "nightly")]
use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
use std::cmp::Ordering; use std::cmp::Ordering;
use std::hash::{Hash, Hasher}; use std::hash::{Hash, Hasher};
@ -16,6 +18,8 @@ use crate::{DebruijnIndex, TypeFlags};
#[derive(Copy, Clone)] #[derive(Copy, Clone)]
pub struct WithCachedTypeInfo<T> { pub struct WithCachedTypeInfo<T> {
pub internee: T, pub internee: T,
#[cfg(feature = "nightly")]
pub stable_hash: Fingerprint, pub stable_hash: Fingerprint,
/// This field provides fast access to information that is also contained /// 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> { impl<T: Hash> Hash for WithCachedTypeInfo<T> {
#[inline] #[inline]
fn hash<H: Hasher>(&self, s: &mut H) { fn hash<H: Hasher>(&self, s: &mut H) {
#[cfg(feature = "nightly")]
if self.stable_hash != Fingerprint::ZERO { if self.stable_hash != Fingerprint::ZERO {
self.stable_hash.hash(s) return self.stable_hash.hash(s);
} else {
self.internee.hash(s)
} }
self.internee.hash(s)
} }
} }
#[cfg(feature = "nightly")]
impl<T: HashStable<CTX>, CTX> HashStable<CTX> for WithCachedTypeInfo<T> { impl<T: HashStable<CTX>, CTX> HashStable<CTX> for WithCachedTypeInfo<T> {
fn hash_stable(&self, hcx: &mut CTX, hasher: &mut StableHasher) { fn hash_stable(&self, hcx: &mut CTX, hasher: &mut StableHasher) {
if self.stable_hash == Fingerprint::ZERO || cfg!(debug_assertions) { if self.stable_hash == Fingerprint::ZERO || cfg!(debug_assertions) {

View file

@ -1,11 +1,11 @@
#![allow(rustc::usage_of_ty_tykind)] #![allow(rustc::usage_of_ty_tykind)]
#[cfg(feature = "nightly")]
use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
#[cfg(feature = "nightly")]
use rustc_data_structures::unify::{EqUnifyValue, UnifyKey}; use rustc_data_structures::unify::{EqUnifyValue, UnifyKey};
use std::fmt; use std::fmt;
use std::mem::discriminant;
use crate::HashStableContext;
use crate::Interner; use crate::Interner;
use crate::{DebruijnIndex, DebugWithInfcx, InferCtxtLike, WithInfcx}; use crate::{DebruijnIndex, DebugWithInfcx, InferCtxtLike, WithInfcx};
@ -13,8 +13,8 @@ use self::TyKind::*;
/// The movability of a coroutine / closure literal: /// The movability of a coroutine / closure literal:
/// whether a coroutine contains self-references, causing it to be `!Unpin`. /// whether a coroutine contains self-references, causing it to be `!Unpin`.
#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Encodable, Decodable, Debug, Copy)] #[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, Copy)]
#[derive(HashStable_Generic)] #[cfg_attr(feature = "nightly", derive(Encodable, Decodable, HashStable_Generic))]
pub enum Movability { pub enum Movability {
/// May contain self-references, `!Unpin`. /// May contain self-references, `!Unpin`.
Static, Static,
@ -23,7 +23,7 @@ pub enum Movability {
} }
#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, Copy)] #[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 { pub enum Mutability {
// N.B. Order is deliberate, so that Not < Mut // N.B. Order is deliberate, so that Not < Mut
Not, Not,
@ -75,7 +75,7 @@ impl Mutability {
/// Specifies how a trait object is represented. /// Specifies how a trait object is represented.
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)] #[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 { pub enum DynKind {
/// An unsized `dyn Trait` object /// An unsized `dyn Trait` object
Dyn, Dyn,
@ -89,7 +89,7 @@ pub enum DynKind {
} }
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)] #[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 { pub enum AliasKind {
/// A projection `<Type as Trait>::AssocType`. /// A projection `<Type as Trait>::AssocType`.
/// Can get normalized away if monomorphic enough. /// 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 /// Types written by the user start out as `hir::TyKind` and get
/// converted to this representation using `AstConv::ast_ty_to_ty`. /// 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)] #[derive(derivative::Derivative)]
#[derivative( #[derivative(
Clone(bound = ""), Clone(bound = ""),
@ -119,7 +119,7 @@ pub enum AliasKind {
Ord = "feature_allow_slow_enum", Ord = "feature_allow_slow_enum",
Hash(bound = "") Hash(bound = "")
)] )]
#[derive(TyEncodable, TyDecodable)] #[cfg_attr(feature = "nightly", derive(TyEncodable, TyDecodable))]
pub enum TyKind<I: Interner> { pub enum TyKind<I: Interner> {
/// The primitive boolean type. Written as `bool`. /// The primitive boolean type. Written as `bool`.
Bool, Bool,
@ -407,7 +407,7 @@ impl<I: Interner> DebugWithInfcx<I> for TyKind<I> {
write!(f, ">") write!(f, ">")
} }
Foreign(d) => f.debug_tuple_field1_finish("Foreign", d), Foreign(d) => f.debug_tuple("Foreign").field(d).finish(),
Str => write!(f, "str"), Str => write!(f, "str"),
Array(t, c) => write!(f, "[{:?}; {:?}]", &this.wrap(t), &this.wrap(c)), Array(t, c) => write!(f, "[{:?}; {:?}]", &this.wrap(t), &this.wrap(c)),
Slice(t) => write!(f, "[{:?}]", &this.wrap(t)), 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::Mut => write!(f, "&{:?} mut {:?}", &this.wrap(r), &this.wrap(t)),
Mutability::Not => write!(f, "&{:?} {:?}", &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)), FnPtr(s) => write!(f, "{:?}", &this.wrap(s)),
Dynamic(p, r, repr) => match repr { Dynamic(p, r, repr) => match repr {
DynKind::Dyn => write!(f, "dyn {:?} + {:?}", &this.wrap(p), &this.wrap(r)), 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)) write!(f, "dyn* {:?} + {:?}", &this.wrap(p), &this.wrap(r))
} }
}, },
Closure(d, s) => f.debug_tuple_field2_finish("Closure", d, &this.wrap(s)), Closure(d, s) => f.debug_tuple("Closure").field(d).field(&this.wrap(s)).finish(),
Coroutine(d, s, m) => f.debug_tuple_field3_finish("Coroutine", d, &this.wrap(s), m), Coroutine(d, s, m) => {
f.debug_tuple("Coroutine").field(d).field(&this.wrap(s)).field(m).finish()
}
CoroutineWitness(d, s) => { 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, "!"), Never => write!(f, "!"),
Tuple(t) => { Tuple(t) => {
@ -453,7 +455,7 @@ impl<I: Interner> DebugWithInfcx<I> for TyKind<I> {
} }
write!(f, ")") 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:?}"), Param(p) => write!(f, "{p:?}"),
Bound(d, b) => crate::debug_bound_var(f, *d, b), Bound(d, b) => crate::debug_bound_var(f, *d, b),
Placeholder(p) => write!(f, "{p:?}"), 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` // This is not a derived impl because a derive would require `I: HashStable`
#[cfg(feature = "nightly")]
#[allow(rustc::usage_of_ty_tykind)] #[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 where
I::AdtDef: HashStable<CTX>, I::AdtDef: HashStable<CTX>,
I::DefId: HashStable<CTX>, I::DefId: HashStable<CTX>,
@ -583,7 +586,7 @@ where
} }
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] #[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 { pub enum IntTy {
Isize, Isize,
I8, I8,
@ -641,7 +644,7 @@ impl IntTy {
} }
#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Copy)] #[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 { pub enum UintTy {
Usize, Usize,
U8, U8,
@ -699,7 +702,7 @@ impl UintTy {
} }
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] #[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 { pub enum FloatTy {
F32, F32,
F64, F64,
@ -733,18 +736,21 @@ pub struct FloatVarValue(pub FloatTy);
rustc_index::newtype_index! { rustc_index::newtype_index! {
/// A **ty**pe **v**ariable **ID**. /// A **ty**pe **v**ariable **ID**.
#[debug_format = "?{}t"] #[debug_format = "?{}t"]
#[gate_rustc_only]
pub struct TyVid {} pub struct TyVid {}
} }
rustc_index::newtype_index! { rustc_index::newtype_index! {
/// An **int**egral (`u32`, `i32`, `usize`, etc.) type **v**ariable **ID**. /// An **int**egral (`u32`, `i32`, `usize`, etc.) type **v**ariable **ID**.
#[debug_format = "?{}i"] #[debug_format = "?{}i"]
#[gate_rustc_only]
pub struct IntVid {} pub struct IntVid {}
} }
rustc_index::newtype_index! { rustc_index::newtype_index! {
/// A **float**ing-point (`f32` or `f64`) type **v**ariable **ID**. /// A **float**ing-point (`f32` or `f64`) type **v**ariable **ID**.
#[debug_format = "?{}f"] #[debug_format = "?{}f"]
#[gate_rustc_only]
pub struct FloatVid {} pub struct FloatVid {}
} }
@ -753,7 +759,8 @@ rustc_index::newtype_index! {
/// E.g., if we have an empty array (`[]`), then we create a fresh /// 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 /// type variable for the element type since we won't know until it's
/// used what the element type is supposed to be. /// 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 { pub enum InferTy {
/// A type variable. /// A type variable.
TyVar(TyVid), TyVar(TyVid),
@ -786,6 +793,7 @@ pub enum InferTy {
/// Raw `TyVid` are used as the unification key for `sub_relations`; /// Raw `TyVid` are used as the unification key for `sub_relations`;
/// they carry no values. /// they carry no values.
#[cfg(feature = "nightly")]
impl UnifyKey for TyVid { impl UnifyKey for TyVid {
type Value = (); type Value = ();
#[inline] #[inline]
@ -801,8 +809,10 @@ impl UnifyKey for TyVid {
} }
} }
#[cfg(feature = "nightly")]
impl EqUnifyValue for IntVarValue {} impl EqUnifyValue for IntVarValue {}
#[cfg(feature = "nightly")]
impl UnifyKey for IntVid { impl UnifyKey for IntVid {
type Value = Option<IntVarValue>; type Value = Option<IntVarValue>;
#[inline] // make this function eligible for inlining - it is quite hot. #[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 {} impl EqUnifyValue for FloatVarValue {}
#[cfg(feature = "nightly")]
impl UnifyKey for FloatVid { impl UnifyKey for FloatVid {
type Value = Option<FloatVarValue>; type Value = Option<FloatVarValue>;
#[inline] #[inline]
@ -835,10 +847,11 @@ impl UnifyKey for FloatVid {
} }
} }
#[cfg(feature = "nightly")]
impl<CTX> HashStable<CTX> for InferTy { impl<CTX> HashStable<CTX> for InferTy {
fn hash_stable(&self, ctx: &mut CTX, hasher: &mut StableHasher) { fn hash_stable(&self, ctx: &mut CTX, hasher: &mut StableHasher) {
use InferTy::*; use InferTy::*;
discriminant(self).hash_stable(ctx, hasher); std::mem::discriminant(self).hash_stable(ctx, hasher);
match self { match self {
TyVar(_) | IntVar(_) | FloatVar(_) => { TyVar(_) | IntVar(_) | FloatVar(_) => {
panic!("type variables should not be hashed: {self:?}") panic!("type variables should not be hashed: {self:?}")

View file

@ -41,12 +41,12 @@
//! - u.visit_with(visitor) //! - u.visit_with(visitor)
//! ``` //! ```
use rustc_data_structures::sync::Lrc;
use rustc_index::{Idx, IndexVec}; use rustc_index::{Idx, IndexVec};
use std::fmt; use std::fmt;
use std::ops::ControlFlow; use std::ops::ControlFlow;
use crate::Interner; use crate::Interner;
use crate::Lrc;
/// This trait is implemented for every type that can be visited, /// This trait is implemented for every type that can be visited,
/// providing the skeleton of the traversal. /// 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 /// 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. /// that recurses into the type's fields in a non-custom fashion.
pub trait TypeVisitor<I: Interner>: Sized { pub trait TypeVisitor<I: Interner>: Sized {
#[cfg(feature = "nightly")]
type BreakTy = !; type BreakTy = !;
#[cfg(not(feature = "nightly"))]
type BreakTy;
fn visit_binder<T: TypeVisitable<I>>(&mut self, t: &I::Binder<T>) -> ControlFlow<Self::BreakTy> fn visit_binder<T: TypeVisitable<I>>(&mut self, t: &I::Binder<T>) -> ControlFlow<Self::BreakTy>
where where
I::Binder<T>: TypeSuperVisitable<I>, I::Binder<T>: TypeSuperVisitable<I>,