Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Erase query result types #107937

Closed
wants to merge 7 commits into from
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