From 107e2904bffed4c2fb2af1ce92dadd1ad3752049 Mon Sep 17 00:00:00 2001 From: Mark Rousskov Date: Sun, 16 Aug 2020 11:08:55 -0400 Subject: [PATCH] Use CopyTaggedPtr for ParamEnv --- src/librustc_middle/ty/list.rs | 15 ++++++ src/librustc_middle/ty/mod.rs | 92 ++++++++++++---------------------- 2 files changed, 47 insertions(+), 60 deletions(-) diff --git a/src/librustc_middle/ty/list.rs b/src/librustc_middle/ty/list.rs index fe390adf89f..83a2bdf90f9 100644 --- a/src/librustc_middle/ty/list.rs +++ b/src/librustc_middle/ty/list.rs @@ -35,6 +35,21 @@ pub struct List { opaque: OpaqueListContents, } +unsafe impl<'a, T: 'a> rustc_data_structures::tagged_ptr::Pointer for &'a List { + const BITS: usize = std::mem::align_of::().trailing_zeros() as usize; + fn into_usize(self) -> usize { + self as *const List as usize + } + unsafe fn from_usize(ptr: usize) -> Self { + &*(ptr as *const List) + } + unsafe fn with_ref R>(ptr: usize, f: F) -> R { + // Self: Copy so this is fine + let ptr = Self::from_usize(ptr); + f(&ptr) + } +} + unsafe impl Sync for List {} impl List { diff --git a/src/librustc_middle/ty/mod.rs b/src/librustc_middle/ty/mod.rs index 02fd18ef968..4fa86a91254 100644 --- a/src/librustc_middle/ty/mod.rs +++ b/src/librustc_middle/ty/mod.rs @@ -27,6 +27,7 @@ use rustc_data_structures::fx::FxIndexMap; use rustc_data_structures::sorted_map::SortedIndexMultiMap; use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; use rustc_data_structures::sync::{self, par_iter, ParallelIterator}; +use rustc_data_structures::tagged_ptr::CopyTaggedPtr; use rustc_errors::ErrorReported; use rustc_hir as hir; use rustc_hir::def::{CtorKind, CtorOf, DefKind, Namespace, Res}; @@ -46,7 +47,6 @@ use std::cell::RefCell; use std::cmp::Ordering; use std::fmt; use std::hash::{Hash, Hasher}; -use std::marker::PhantomData; use std::ops::Range; use std::ptr; use std::str; @@ -1713,34 +1713,21 @@ impl WithOptConstParam { /// When type checking, we use the `ParamEnv` to track /// details about the set of where-clauses that are in scope at this /// particular point. -#[derive(Copy, Clone)] +#[derive(Copy, Clone, Hash, PartialEq, Eq)] pub struct ParamEnv<'tcx> { - // We pack the caller_bounds List pointer and a Reveal enum into this usize. - // Specifically, the low bit represents Reveal, with 0 meaning `UserFacing` - // and 1 meaning `All`. The rest is the pointer. - // - // This relies on the List> type having at least 2-byte - // alignment. Lists start with a usize and are repr(C) so this should be - // fine; there is a debug_assert in the constructor as well. - // - // Note that the choice of 0 for UserFacing is intentional -- since it is the - // first variant in Reveal this means that joining the pointer is a simple `or`. - packed_data: usize, - - /// `Obligation`s that the caller must satisfy. This is basically - /// the set of bounds on the in-scope type parameters, translated + /// This packs both caller bounds and the reveal enum into one pointer. + /// + /// Caller bounds are `Obligation`s that the caller must satisfy. This is + /// basically the set of bounds on the in-scope type parameters, translated /// into `Obligation`s, and elaborated and normalized. /// - /// Note: This is packed into the `packed_data` usize above, use the - /// `caller_bounds()` method to access it. - caller_bounds: PhantomData<&'tcx List>>, - + /// Use the `caller_bounds()` method to access. + /// /// Typically, this is `Reveal::UserFacing`, but during codegen we /// want `Reveal::All`. /// - /// Note: This is packed into the caller_bounds usize above, use the reveal() - /// method to access it. - reveal: PhantomData, + /// Note: This is packed, use the reveal() method to access it. + packed: CopyTaggedPtr<&'tcx List>, traits::Reveal, true>, /// If this `ParamEnv` comes from a call to `tcx.param_env(def_id)`, /// register that `def_id` (useful for transitioning to the chalk trait @@ -1748,6 +1735,23 @@ pub struct ParamEnv<'tcx> { pub def_id: Option, } +unsafe impl rustc_data_structures::tagged_ptr::Tag for traits::Reveal { + const BITS: usize = 1; + fn into_usize(self) -> usize { + match self { + traits::Reveal::UserFacing => 0, + traits::Reveal::All => 1, + } + } + unsafe fn from_usize(ptr: usize) -> Self { + match ptr { + 0 => traits::Reveal::UserFacing, + 1 => traits::Reveal::All, + _ => std::hint::unreachable_unchecked(), + } + } +} + impl<'tcx> fmt::Debug for ParamEnv<'tcx> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.debug_struct("ParamEnv") @@ -1758,24 +1762,6 @@ impl<'tcx> fmt::Debug for ParamEnv<'tcx> { } } -impl<'tcx> Hash for ParamEnv<'tcx> { - fn hash(&self, state: &mut H) { - // List hashes as the raw pointer, so we can skip splitting into the - // pointer and the enum. - self.packed_data.hash(state); - self.def_id.hash(state); - } -} - -impl<'tcx> PartialEq for ParamEnv<'tcx> { - fn eq(&self, other: &Self) -> bool { - self.caller_bounds() == other.caller_bounds() - && self.reveal() == other.reveal() - && self.def_id == other.def_id - } -} -impl<'tcx> Eq for ParamEnv<'tcx> {} - impl<'a, 'tcx> HashStable> for ParamEnv<'tcx> { fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) { self.caller_bounds().hash_stable(hcx, hasher); @@ -1812,13 +1798,12 @@ impl<'tcx> ParamEnv<'tcx> { #[inline] pub fn caller_bounds(self) -> &'tcx List> { - // mask out bottom bit - unsafe { &*((self.packed_data & (!1)) as *const _) } + self.packed.pointer() } #[inline] pub fn reveal(self) -> traits::Reveal { - if self.packed_data & 1 == 0 { traits::Reveal::UserFacing } else { traits::Reveal::All } + self.packed.tag() } /// Construct a trait environment with no where-clauses in scope @@ -1840,24 +1825,11 @@ impl<'tcx> ParamEnv<'tcx> { reveal: Reveal, def_id: Option, ) -> Self { - let packed_data = caller_bounds as *const _ as usize; - // Check that we can pack the reveal data into the pointer. - debug_assert!(packed_data & 1 == 0); - ty::ParamEnv { - packed_data: packed_data - | match reveal { - Reveal::UserFacing => 0, - Reveal::All => 1, - }, - caller_bounds: PhantomData, - reveal: PhantomData, - def_id, - } + ty::ParamEnv { packed: CopyTaggedPtr::new(caller_bounds, reveal), def_id } } pub fn with_user_facing(mut self) -> Self { - // clear bottom bit - self.packed_data &= !1; + self.packed.set_tag(Reveal::UserFacing); self } @@ -1871,7 +1843,7 @@ impl<'tcx> ParamEnv<'tcx> { /// will be normalized to their underlying types. /// See PR #65989 and issue #65918 for more details pub fn with_reveal_all_normalized(self, tcx: TyCtxt<'tcx>) -> Self { - if self.packed_data & 1 == 1 { + if self.packed.tag() == traits::Reveal::All { return self; }