Skip to content

Commit 107e290

Browse files
Use CopyTaggedPtr for ParamEnv
1 parent c8fe232 commit 107e290

File tree

2 files changed

+47
-60
lines changed

2 files changed

+47
-60
lines changed

src/librustc_middle/ty/list.rs

+15
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,21 @@ pub struct List<T> {
3535
opaque: OpaqueListContents,
3636
}
3737

38+
unsafe impl<'a, T: 'a> rustc_data_structures::tagged_ptr::Pointer for &'a List<T> {
39+
const BITS: usize = std::mem::align_of::<usize>().trailing_zeros() as usize;
40+
fn into_usize(self) -> usize {
41+
self as *const List<T> as usize
42+
}
43+
unsafe fn from_usize(ptr: usize) -> Self {
44+
&*(ptr as *const List<T>)
45+
}
46+
unsafe fn with_ref<R, F: FnOnce(&Self) -> R>(ptr: usize, f: F) -> R {
47+
// Self: Copy so this is fine
48+
let ptr = Self::from_usize(ptr);
49+
f(&ptr)
50+
}
51+
}
52+
3853
unsafe impl<T: Sync> Sync for List<T> {}
3954

4055
impl<T: Copy> List<T> {

src/librustc_middle/ty/mod.rs

+32-60
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ use rustc_data_structures::fx::FxIndexMap;
2727
use rustc_data_structures::sorted_map::SortedIndexMultiMap;
2828
use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
2929
use rustc_data_structures::sync::{self, par_iter, ParallelIterator};
30+
use rustc_data_structures::tagged_ptr::CopyTaggedPtr;
3031
use rustc_errors::ErrorReported;
3132
use rustc_hir as hir;
3233
use rustc_hir::def::{CtorKind, CtorOf, DefKind, Namespace, Res};
@@ -46,7 +47,6 @@ use std::cell::RefCell;
4647
use std::cmp::Ordering;
4748
use std::fmt;
4849
use std::hash::{Hash, Hasher};
49-
use std::marker::PhantomData;
5050
use std::ops::Range;
5151
use std::ptr;
5252
use std::str;
@@ -1713,41 +1713,45 @@ impl WithOptConstParam<DefId> {
17131713
/// When type checking, we use the `ParamEnv` to track
17141714
/// details about the set of where-clauses that are in scope at this
17151715
/// particular point.
1716-
#[derive(Copy, Clone)]
1716+
#[derive(Copy, Clone, Hash, PartialEq, Eq)]
17171717
pub struct ParamEnv<'tcx> {
1718-
// We pack the caller_bounds List pointer and a Reveal enum into this usize.
1719-
// Specifically, the low bit represents Reveal, with 0 meaning `UserFacing`
1720-
// and 1 meaning `All`. The rest is the pointer.
1721-
//
1722-
// This relies on the List<Predicate<'tcx>> type having at least 2-byte
1723-
// alignment. Lists start with a usize and are repr(C) so this should be
1724-
// fine; there is a debug_assert in the constructor as well.
1725-
//
1726-
// Note that the choice of 0 for UserFacing is intentional -- since it is the
1727-
// first variant in Reveal this means that joining the pointer is a simple `or`.
1728-
packed_data: usize,
1729-
1730-
/// `Obligation`s that the caller must satisfy. This is basically
1731-
/// the set of bounds on the in-scope type parameters, translated
1718+
/// This packs both caller bounds and the reveal enum into one pointer.
1719+
///
1720+
/// Caller bounds are `Obligation`s that the caller must satisfy. This is
1721+
/// basically the set of bounds on the in-scope type parameters, translated
17321722
/// into `Obligation`s, and elaborated and normalized.
17331723
///
1734-
/// Note: This is packed into the `packed_data` usize above, use the
1735-
/// `caller_bounds()` method to access it.
1736-
caller_bounds: PhantomData<&'tcx List<Predicate<'tcx>>>,
1737-
1724+
/// Use the `caller_bounds()` method to access.
1725+
///
17381726
/// Typically, this is `Reveal::UserFacing`, but during codegen we
17391727
/// want `Reveal::All`.
17401728
///
1741-
/// Note: This is packed into the caller_bounds usize above, use the reveal()
1742-
/// method to access it.
1743-
reveal: PhantomData<traits::Reveal>,
1729+
/// Note: This is packed, use the reveal() method to access it.
1730+
packed: CopyTaggedPtr<&'tcx List<Predicate<'tcx>>, traits::Reveal, true>,
17441731

17451732
/// If this `ParamEnv` comes from a call to `tcx.param_env(def_id)`,
17461733
/// register that `def_id` (useful for transitioning to the chalk trait
17471734
/// solver).
17481735
pub def_id: Option<DefId>,
17491736
}
17501737

1738+
unsafe impl rustc_data_structures::tagged_ptr::Tag for traits::Reveal {
1739+
const BITS: usize = 1;
1740+
fn into_usize(self) -> usize {
1741+
match self {
1742+
traits::Reveal::UserFacing => 0,
1743+
traits::Reveal::All => 1,
1744+
}
1745+
}
1746+
unsafe fn from_usize(ptr: usize) -> Self {
1747+
match ptr {
1748+
0 => traits::Reveal::UserFacing,
1749+
1 => traits::Reveal::All,
1750+
_ => std::hint::unreachable_unchecked(),
1751+
}
1752+
}
1753+
}
1754+
17511755
impl<'tcx> fmt::Debug for ParamEnv<'tcx> {
17521756
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
17531757
f.debug_struct("ParamEnv")
@@ -1758,24 +1762,6 @@ impl<'tcx> fmt::Debug for ParamEnv<'tcx> {
17581762
}
17591763
}
17601764

1761-
impl<'tcx> Hash for ParamEnv<'tcx> {
1762-
fn hash<H: Hasher>(&self, state: &mut H) {
1763-
// List hashes as the raw pointer, so we can skip splitting into the
1764-
// pointer and the enum.
1765-
self.packed_data.hash(state);
1766-
self.def_id.hash(state);
1767-
}
1768-
}
1769-
1770-
impl<'tcx> PartialEq for ParamEnv<'tcx> {
1771-
fn eq(&self, other: &Self) -> bool {
1772-
self.caller_bounds() == other.caller_bounds()
1773-
&& self.reveal() == other.reveal()
1774-
&& self.def_id == other.def_id
1775-
}
1776-
}
1777-
impl<'tcx> Eq for ParamEnv<'tcx> {}
1778-
17791765
impl<'a, 'tcx> HashStable<StableHashingContext<'a>> for ParamEnv<'tcx> {
17801766
fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) {
17811767
self.caller_bounds().hash_stable(hcx, hasher);
@@ -1812,13 +1798,12 @@ impl<'tcx> ParamEnv<'tcx> {
18121798

18131799
#[inline]
18141800
pub fn caller_bounds(self) -> &'tcx List<Predicate<'tcx>> {
1815-
// mask out bottom bit
1816-
unsafe { &*((self.packed_data & (!1)) as *const _) }
1801+
self.packed.pointer()
18171802
}
18181803

18191804
#[inline]
18201805
pub fn reveal(self) -> traits::Reveal {
1821-
if self.packed_data & 1 == 0 { traits::Reveal::UserFacing } else { traits::Reveal::All }
1806+
self.packed.tag()
18221807
}
18231808

18241809
/// Construct a trait environment with no where-clauses in scope
@@ -1840,24 +1825,11 @@ impl<'tcx> ParamEnv<'tcx> {
18401825
reveal: Reveal,
18411826
def_id: Option<DefId>,
18421827
) -> Self {
1843-
let packed_data = caller_bounds as *const _ as usize;
1844-
// Check that we can pack the reveal data into the pointer.
1845-
debug_assert!(packed_data & 1 == 0);
1846-
ty::ParamEnv {
1847-
packed_data: packed_data
1848-
| match reveal {
1849-
Reveal::UserFacing => 0,
1850-
Reveal::All => 1,
1851-
},
1852-
caller_bounds: PhantomData,
1853-
reveal: PhantomData,
1854-
def_id,
1855-
}
1828+
ty::ParamEnv { packed: CopyTaggedPtr::new(caller_bounds, reveal), def_id }
18561829
}
18571830

18581831
pub fn with_user_facing(mut self) -> Self {
1859-
// clear bottom bit
1860-
self.packed_data &= !1;
1832+
self.packed.set_tag(Reveal::UserFacing);
18611833
self
18621834
}
18631835

@@ -1871,7 +1843,7 @@ impl<'tcx> ParamEnv<'tcx> {
18711843
/// will be normalized to their underlying types.
18721844
/// See PR #65989 and issue #65918 for more details
18731845
pub fn with_reveal_all_normalized(self, tcx: TyCtxt<'tcx>) -> Self {
1874-
if self.packed_data & 1 == 1 {
1846+
if self.packed.tag() == traits::Reveal::All {
18751847
return self;
18761848
}
18771849

0 commit comments

Comments
 (0)