Skip to content

Commit

Permalink
Modify GenericArg and Term structs to use strict provenance rules
Browse files Browse the repository at this point in the history
  • Loading branch information
kamalesh0406 committed Jan 15, 2024
1 parent 8847bda commit cd90143
Show file tree
Hide file tree
Showing 2 changed files with 48 additions and 18 deletions.
41 changes: 31 additions & 10 deletions compiler/rustc_middle/src/ty/generic_args.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ use crate::ty::visit::{TypeVisitable, TypeVisitableExt, TypeVisitor};
use crate::ty::{self, Lift, List, ParamConst, Ty, TyCtxt};

use rustc_data_structures::intern::Interned;
use rustc_data_structures::sync::{DynSend, DynSync};
use rustc_errors::{DiagnosticArgValue, IntoDiagnosticArg};
use rustc_hir::def_id::DefId;
use rustc_macros::HashStable;
Expand All @@ -20,6 +21,7 @@ use std::marker::PhantomData;
use std::mem;
use std::num::NonZeroUsize;
use std::ops::{ControlFlow, Deref};
use std::ptr::NonNull;

/// An entity in the Rust type system, which can be one of
/// several kinds (types, lifetimes, and consts).
Expand All @@ -31,10 +33,27 @@ use std::ops::{ControlFlow, Deref};
/// `Region` and `Const` are all interned.
#[derive(Copy, Clone, PartialEq, Eq, Hash)]
pub struct GenericArg<'tcx> {
ptr: NonZeroUsize,
ptr: NonNull<()>,
marker: PhantomData<(Ty<'tcx>, ty::Region<'tcx>, ty::Const<'tcx>)>,
}

unsafe impl<'tcx> DynSend for GenericArg<'tcx> where
&'tcx (Ty<'tcx>, ty::Region<'tcx>, ty::Const<'tcx>): DynSend
{
}
unsafe impl<'tcx> DynSync for GenericArg<'tcx> where
&'tcx (Ty<'tcx>, ty::Region<'tcx>, ty::Const<'tcx>): DynSync
{
}
unsafe impl<'tcx> Send for GenericArg<'tcx> where
&'tcx (Ty<'tcx>, ty::Region<'tcx>, ty::Const<'tcx>): Send
{
}
unsafe impl<'tcx> Sync for GenericArg<'tcx> where
&'tcx (Ty<'tcx>, ty::Region<'tcx>, ty::Const<'tcx>): Sync
{
}

impl<'tcx> IntoDiagnosticArg for GenericArg<'tcx> {
fn into_diagnostic_arg(self) -> DiagnosticArgValue<'static> {
self.to_string().into_diagnostic_arg()
Expand All @@ -60,21 +79,21 @@ impl<'tcx> GenericArgKind<'tcx> {
GenericArgKind::Lifetime(lt) => {
// Ensure we can use the tag bits.
assert_eq!(mem::align_of_val(&*lt.0.0) & TAG_MASK, 0);
(REGION_TAG, lt.0.0 as *const ty::RegionKind<'tcx> as usize)
(REGION_TAG, NonNull::from(lt.0.0).cast())
}
GenericArgKind::Type(ty) => {
// Ensure we can use the tag bits.
assert_eq!(mem::align_of_val(&*ty.0.0) & TAG_MASK, 0);
(TYPE_TAG, ty.0.0 as *const WithCachedTypeInfo<ty::TyKind<'tcx>> as usize)
(TYPE_TAG, NonNull::from(ty.0.0).cast())
}
GenericArgKind::Const(ct) => {
// Ensure we can use the tag bits.
assert_eq!(mem::align_of_val(&*ct.0.0) & TAG_MASK, 0);
(CONST_TAG, ct.0.0 as *const WithCachedTypeInfo<ty::ConstData<'tcx>> as usize)
(CONST_TAG, NonNull::from(ct.0.0).cast())
}
};

GenericArg { ptr: unsafe { NonZeroUsize::new_unchecked(ptr | tag) }, marker: PhantomData }
GenericArg { ptr: ptr.map_addr(|addr| addr | tag), marker: PhantomData }
}
}

Expand Down Expand Up @@ -123,20 +142,22 @@ impl<'tcx> From<ty::Term<'tcx>> for GenericArg<'tcx> {
impl<'tcx> GenericArg<'tcx> {
#[inline]
pub fn unpack(self) -> GenericArgKind<'tcx> {
let ptr = self.ptr.get();
let ptr = unsafe {
self.ptr.map_addr(|addr| NonZeroUsize::new_unchecked(addr.get() & !TAG_MASK))
};
// SAFETY: use of `Interned::new_unchecked` here is ok because these
// pointers were originally created from `Interned` types in `pack()`,
// and this is just going in the other direction.
unsafe {
match ptr & TAG_MASK {
match self.ptr.addr().get() & TAG_MASK {
REGION_TAG => GenericArgKind::Lifetime(ty::Region(Interned::new_unchecked(
&*((ptr & !TAG_MASK) as *const ty::RegionKind<'tcx>),
ptr.cast::<ty::RegionKind<'tcx>>().as_ref(),
))),
TYPE_TAG => GenericArgKind::Type(Ty(Interned::new_unchecked(
&*((ptr & !TAG_MASK) as *const WithCachedTypeInfo<ty::TyKind<'tcx>>),
ptr.cast::<WithCachedTypeInfo<ty::TyKind<'tcx>>>().as_ref(),
))),
CONST_TAG => GenericArgKind::Const(ty::Const(Interned::new_unchecked(
&*((ptr & !TAG_MASK) as *const WithCachedTypeInfo<ty::ConstData<'tcx>>),
ptr.cast::<WithCachedTypeInfo<ty::ConstData<'tcx>>>().as_ref(),
))),
_ => intrinsics::unreachable(),
}
Expand Down
25 changes: 17 additions & 8 deletions compiler/rustc_middle/src/ty/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexMap, FxIndexSet};
use rustc_data_structures::intern::Interned;
use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
use rustc_data_structures::steal::Steal;
use rustc_data_structures::sync::{DynSend, DynSync};
use rustc_data_structures::tagged_ptr::CopyTaggedPtr;
use rustc_data_structures::unord::UnordMap;
use rustc_errors::{DiagnosticBuilder, ErrorGuaranteed, StashKey};
Expand All @@ -63,6 +64,7 @@ use std::marker::PhantomData;
use std::mem;
use std::num::NonZeroUsize;
use std::ops::ControlFlow;
use std::ptr::NonNull;
use std::{fmt, str};

pub use crate::ty::diagnostics::*;
Expand Down Expand Up @@ -848,10 +850,15 @@ pub type PolyCoercePredicate<'tcx> = ty::Binder<'tcx, CoercePredicate<'tcx>>;

#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct Term<'tcx> {
ptr: NonZeroUsize,
ptr: NonNull<()>,
marker: PhantomData<(Ty<'tcx>, Const<'tcx>)>,
}

unsafe impl<'tcx> DynSend for Term<'tcx> where &'tcx (Ty<'tcx>, Const<'tcx>): DynSend {}
unsafe impl<'tcx> DynSync for Term<'tcx> where &'tcx (Ty<'tcx>, Const<'tcx>): DynSync {}
unsafe impl<'tcx> Send for Term<'tcx> where &'tcx (Ty<'tcx>, Const<'tcx>): Send {}
unsafe impl<'tcx> Sync for Term<'tcx> where &'tcx (Ty<'tcx>, Const<'tcx>): Sync {}

impl Debug for Term<'_> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let data = if let Some(ty) = self.ty() {
Expand Down Expand Up @@ -914,17 +921,19 @@ impl<'tcx, D: TyDecoder<I = TyCtxt<'tcx>>> Decodable<D> for Term<'tcx> {
impl<'tcx> Term<'tcx> {
#[inline]
pub fn unpack(self) -> TermKind<'tcx> {
let ptr = self.ptr.get();
let ptr = unsafe {
self.ptr.map_addr(|addr| NonZeroUsize::new_unchecked(addr.get() & !TAG_MASK))
};
// SAFETY: use of `Interned::new_unchecked` here is ok because these
// pointers were originally created from `Interned` types in `pack()`,
// and this is just going in the other direction.
unsafe {
match ptr & TAG_MASK {
match self.ptr.addr().get() & TAG_MASK {
TYPE_TAG => TermKind::Ty(Ty(Interned::new_unchecked(
&*((ptr & !TAG_MASK) as *const WithCachedTypeInfo<ty::TyKind<'tcx>>),
ptr.cast::<WithCachedTypeInfo<ty::TyKind<'tcx>>>().as_ref(),
))),
CONST_TAG => TermKind::Const(ty::Const(Interned::new_unchecked(
&*((ptr & !TAG_MASK) as *const WithCachedTypeInfo<ty::ConstData<'tcx>>),
ptr.cast::<WithCachedTypeInfo<ty::ConstData<'tcx>>>().as_ref(),
))),
_ => core::intrinsics::unreachable(),
}
Expand Down Expand Up @@ -986,16 +995,16 @@ impl<'tcx> TermKind<'tcx> {
TermKind::Ty(ty) => {
// Ensure we can use the tag bits.
assert_eq!(mem::align_of_val(&*ty.0.0) & TAG_MASK, 0);
(TYPE_TAG, ty.0.0 as *const WithCachedTypeInfo<ty::TyKind<'tcx>> as usize)
(TYPE_TAG, NonNull::from(ty.0.0).cast())
}
TermKind::Const(ct) => {
// Ensure we can use the tag bits.
assert_eq!(mem::align_of_val(&*ct.0.0) & TAG_MASK, 0);
(CONST_TAG, ct.0.0 as *const WithCachedTypeInfo<ty::ConstData<'tcx>> as usize)
(CONST_TAG, NonNull::from(ct.0.0).cast())
}
};

Term { ptr: unsafe { NonZeroUsize::new_unchecked(ptr | tag) }, marker: PhantomData }
Term { ptr: ptr.map_addr(|addr| addr | tag), marker: PhantomData }
}
}

Expand Down

0 comments on commit cd90143

Please sign in to comment.