Skip to content
Closed
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions Cargo.lock
Original file line number Diff line number Diff line change
Expand Up @@ -3983,6 +3983,10 @@ dependencies = [
"winapi",
]

[[package]]
name = "rustc_erase"
version = "0.0.0"

[[package]]
name = "rustc_error_codes"
version = "0.0.0"
Expand Down Expand Up @@ -4373,6 +4377,7 @@ dependencies = [
"rustc_ast",
"rustc_attr",
"rustc_data_structures",
"rustc_erase",
"rustc_error_messages",
"rustc_errors",
"rustc_feature",
Expand Down Expand Up @@ -4571,6 +4576,7 @@ dependencies = [
"rustc-rayon-core",
"rustc_ast",
"rustc_data_structures",
"rustc_erase",
"rustc_errors",
"rustc_hir",
"rustc_index",
Expand Down
1 change: 1 addition & 0 deletions compiler/rustc_data_structures/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@ pub mod stable_hasher;
mod atomic_ref;
pub mod fingerprint;
pub mod profiling;
pub mod remap;
pub mod sharded;
pub mod stack;
pub mod sync;
Expand Down
28 changes: 28 additions & 0 deletions compiler/rustc_data_structures/src/remap.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
/// Remaps the type with a different lifetime for 'tcx if applicable.
pub trait Remap {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is rustc_middle::ty::parametrized::ParameterizedOverTcx that does the same thing.

type Remap<'a>;
}

impl Remap for u32 {
type Remap<'a> = u32;
}

impl<T: Remap> Remap for Option<T> {
type Remap<'a> = Option<T::Remap<'a>>;
}

impl Remap for () {
type Remap<'a> = ();
}

impl<T0: Remap, T1: Remap> Remap for (T0, T1) {
type Remap<'a> = (T0::Remap<'a>, T1::Remap<'a>);
}

impl<T0: Remap, T1: Remap, T2: Remap> Remap for (T0, T1, T2) {
type Remap<'a> = (T0::Remap<'a>, T1::Remap<'a>, T2::Remap<'a>);
}

impl<T0: Remap, T1: Remap, T2: Remap, T3: Remap> Remap for (T0, T1, T2, T3) {
type Remap<'a> = (T0::Remap<'a>, T1::Remap<'a>, T2::Remap<'a>, T3::Remap<'a>);
}
6 changes: 6 additions & 0 deletions compiler/rustc_erase/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
[package]
name = "rustc_erase"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is this inside a new crate and not just in rustc_data_structures? Creating a crate for 47 lines seems pointless, even if the code is very unsafe and self-contained

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

// This is a separate crate so that we can `allow(incomplete_features)` for just `generic_const_exprs`

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, didn't see that.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note that generic_const_exprs will cause ICEs in other crates than the one using the feature if any of it is used in public APIs

version = "0.0.0"
edition = "2021"

[lib]
46 changes: 46 additions & 0 deletions compiler/rustc_erase/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
// This is a separate crate so that we can `allow(incomplete_features)` for just `generic_const_exprs`
#![feature(generic_const_exprs)]
Copy link
Member

@BoxyUwU BoxyUwU Feb 12, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please do not use generic_const_exprs, its incredibly incomplete/broken and also its unsound and will have changes made to it that breaks code that works currently in order to get closer to an actually functioning feature. I do not want to have to deal with cfg(bootstrap) pain and working around generic_const_expr bugs from usage of the feature inside of rustc whenever this feature gets worked on ^^'

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess to explicitly answer

for an option on how stable feature(generic_const_exprs) is.

extremely very not stable 😅

#![allow(incomplete_features)]

#[cfg(debug_assertions)]
use std::intrinsics::type_name;
use std::{
fmt,
mem::{size_of, transmute_copy, MaybeUninit},
};

#[derive(Copy, Clone)]
pub struct Erased<const N: usize> {
data: MaybeUninit<[u8; N]>,
#[cfg(debug_assertions)]
type_id: &'static str,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we prefer std::any::TypeId?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That requires 'static.

}

impl<const N: usize> fmt::Debug for Erased<N> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "Erased<{}>", N)
}
}

pub type Erase<T> = Erased<{ size_of::<T>() }>;

#[inline(always)]
pub fn erase<T: Copy>(src: T) -> Erased<{ size_of::<T>() }> {
Erased {
// SAFETY:: Is it safe to transmute to MaybeUninit
data: unsafe { transmute_copy(&src) },
#[cfg(debug_assertions)]
type_id: type_name::<T>(),
}
}

/// Restores an erased value.
///
/// This is only safe if `value` is a valid instance of `T`.
/// For example if `T` was erased with `erase` previously.
#[inline(always)]
pub unsafe fn restore<T: Copy>(value: Erased<{ size_of::<T>() }>) -> T {
#[cfg(debug_assertions)]
assert_eq!(value.type_id, type_name::<T>());
unsafe { transmute_copy(&value.data) }
}
13 changes: 12 additions & 1 deletion compiler/rustc_hir/src/hir_id.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
use crate::def_id::{DefId, DefIndex, LocalDefId, CRATE_DEF_ID};
use rustc_data_structures::stable_hasher::{HashStable, StableHasher, StableOrd, ToStableHashKey};
use rustc_data_structures::{
remap::Remap,
stable_hasher::{HashStable, StableHasher, StableOrd, ToStableHashKey},
};
use rustc_span::{def_id::DefPathHash, HashStableContext};
use std::fmt::{self, Debug};

Expand All @@ -9,6 +12,10 @@ pub struct OwnerId {
pub def_id: LocalDefId,
}

impl Remap for OwnerId {
type Remap<'a> = OwnerId;
}

impl Debug for OwnerId {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
// Example: DefId(0:1 ~ aa[7697]::{use#0})
Expand Down Expand Up @@ -75,6 +82,10 @@ pub struct HirId {
pub local_id: ItemLocalId,
}

impl Remap for HirId {
type Remap<'a> = HirId;
}

impl Debug for HirId {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
// Example: HirId(DefId(0:1 ~ aa[7697]::{use#0}).10)
Expand Down
1 change: 1 addition & 0 deletions compiler/rustc_middle/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ rustc_arena = { path = "../rustc_arena" }
rustc_ast = { path = "../rustc_ast" }
rustc_attr = { path = "../rustc_attr" }
rustc_data_structures = { path = "../rustc_data_structures" }
rustc_erase = { path = "../rustc_erase" }
rustc_errors = { path = "../rustc_errors" }
# Used for intra-doc links
rustc_error_messages = { path = "../rustc_error_messages" }
Expand Down
136 changes: 134 additions & 2 deletions compiler/rustc_middle/src/query/keys.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,18 +3,21 @@
use crate::infer::canonical::Canonical;
use crate::mir;
use crate::traits;
use crate::traits::ChalkEnvironmentAndGoal;
use crate::ty::fast_reject::SimplifiedType;
use crate::ty::subst::{GenericArg, SubstsRef};
use crate::ty::{self, layout::TyAndLayout, Ty, TyCtxt};
use rustc_data_structures::remap::Remap;
use rustc_hir::def_id::{CrateNum, DefId, LocalDefId, LOCAL_CRATE};
use rustc_hir::hir_id::{HirId, OwnerId};
pub use rustc_middle::traits::query::type_op;
use rustc_query_system::query::{DefaultCacheSelector, VecCacheSelector};
use rustc_span::symbol::{Ident, Symbol};
use rustc_span::{Span, DUMMY_SP};

/// The `Key` trait controls what types can legally be used as the key
/// for a query.
pub trait Key: Sized {
pub trait Key: Sized + Remap {
// N.B. Most of the keys down below have `type CacheSelector = DefaultCacheSelector<Self>;`,
// it would be reasonable to use associated type defaults, to remove the duplication...
//
Expand Down Expand Up @@ -588,7 +591,7 @@ impl Key for Option<Symbol> {

/// Canonical query goals correspond to abstract trait operations that
/// are not tied to any crate in particular.
impl<'tcx, T> Key for Canonical<'tcx, T> {
impl<'tcx, T: Remap> Key for Canonical<'tcx, T> {
type CacheSelector = DefaultCacheSelector<Self>;

#[inline(always)]
Expand Down Expand Up @@ -696,3 +699,132 @@ impl Key for HirId {
None
}
}

// Remap implementations

impl<'tcx, T: Remap> Remap for ty::ParamEnvAnd<'tcx, T> {
type Remap<'a> = ty::ParamEnvAnd<'a, T::Remap<'a>>;
}

impl<'tcx, T: Remap> Remap for ty::Binder<'tcx, T> {
type Remap<'a> = ty::Binder<'a, T::Remap<'a>>;
}

impl<'tcx, T: Remap> Remap for Canonical<'tcx, T> {
type Remap<'a> = Canonical<'a, T::Remap<'a>>;
}

impl<T: Remap> Remap for type_op::Normalize<T> {
type Remap<'a> = type_op::Normalize<T::Remap<'a>>;
}

impl<'tcx> Remap for type_op::AscribeUserType<'tcx> {
type Remap<'a> = type_op::AscribeUserType<'a>;
}

impl<'tcx> Remap for type_op::Subtype<'tcx> {
type Remap<'a> = type_op::Subtype<'a>;
}

impl<'tcx> Remap for type_op::Eq<'tcx> {
type Remap<'a> = type_op::Eq<'a>;
}

impl<'tcx> Remap for type_op::ProvePredicate<'tcx> {
type Remap<'a> = type_op::ProvePredicate<'a>;
}

impl<'tcx> Remap for ty::FnSig<'tcx> {
type Remap<'a> = ty::FnSig<'a>;
}

impl<'tcx> Remap for ty::AliasTy<'tcx> {
type Remap<'a> = ty::AliasTy<'a>;
}

impl<'tcx> Remap for Ty<'tcx> {
type Remap<'a> = Ty<'a>;
}

impl<'tcx> Remap for ty::Predicate<'tcx> {
type Remap<'a> = ty::Predicate<'a>;
}

impl<'tcx> Remap for ChalkEnvironmentAndGoal<'tcx> {
type Remap<'a> = ChalkEnvironmentAndGoal<'a>;
}

impl<'tcx> Remap for ty::Instance<'tcx> {
type Remap<'a> = ty::Instance<'a>;
}

impl<'tcx> Remap for ty::InstanceDef<'tcx> {
type Remap<'a> = ty::InstanceDef<'a>;
}

impl<T: Remap> Remap for ty::WithOptConstParam<T> {
type Remap<'a> = ty::WithOptConstParam<T::Remap<'a>>;
}

impl Remap for SimplifiedType {
type Remap<'a> = SimplifiedType;
}

impl<'tcx> Remap for mir::interpret::GlobalId<'tcx> {
type Remap<'a> = mir::interpret::GlobalId<'a>;
}

impl<'tcx> Remap for mir::interpret::LitToConstInput<'tcx> {
type Remap<'a> = mir::interpret::LitToConstInput<'a>;
}

impl<'tcx> Remap for mir::interpret::ConstAlloc<'tcx> {
type Remap<'a> = mir::interpret::ConstAlloc<'a>;
}

impl<'tcx> Remap for mir::ConstantKind<'tcx> {
type Remap<'a> = mir::ConstantKind<'a>;
}

impl Remap for mir::Field {
type Remap<'a> = mir::Field;
}

impl<'tcx> Remap for ty::ValTree<'tcx> {
type Remap<'a> = ty::ValTree<'a>;
}

impl<'tcx> Remap for ty::ParamEnv<'tcx> {
type Remap<'a> = ty::ParamEnv<'a>;
}

impl<'tcx> Remap for ty::GenericArg<'tcx> {
type Remap<'a> = ty::GenericArg<'a>;
}

impl<'tcx, T: Remap> Remap for &'tcx ty::List<T>
where
for<'a> <T as Remap>::Remap<'a>: 'a,
{
type Remap<'a> = &'a ty::List<T::Remap<'a>>;
}

impl<'tcx> Remap for ty::ExistentialTraitRef<'tcx> {
type Remap<'a> = ty::ExistentialTraitRef<'a>;
}

impl<'tcx> Remap for ty::Const<'tcx> {
type Remap<'a> = ty::Const<'a>;
}

impl<'tcx> Remap for ty::TraitRef<'tcx> {
type Remap<'a> = ty::TraitRef<'a>;
}

impl<'tcx> Remap for ty::UnevaluatedConst<'tcx> {
type Remap<'a> = ty::UnevaluatedConst<'a>;
}

impl Remap for traits::WellFormedLoc {
type Remap<'a> = traits::WellFormedLoc;
}
Loading