Skip to content
Permalink
Browse files

Use a single CtxtInterners

  • Loading branch information...
Zoxc committed May 31, 2019
1 parent ef064d2 commit ec8c2e1ab9bd47c0184a0cbd77f35e9089c9dc0f
Showing with 28 additions and 136 deletions.
  1. +28 −136 src/librustc/ty/context.rs
@@ -1,5 +1,3 @@
// ignore-tidy-filelength

//! Type context book-keeping.

use crate::arena::Arena;
@@ -67,7 +65,6 @@ use std::ops::{Deref, Bound};
use std::iter;
use std::sync::mpsc;
use std::sync::Arc;
use std::marker::PhantomData;
use rustc_target::spec::abi;
use rustc_macros::HashStable;
use syntax::ast;
@@ -81,14 +78,12 @@ use crate::hir;

pub struct AllArenas {
pub interner: SyncDroplessArena,
pub local_interner: SyncDroplessArena,
}

impl AllArenas {
pub fn new() -> Self {
AllArenas {
interner: SyncDroplessArena::default(),
local_interner: SyncDroplessArena::default(),
}
}
}
@@ -136,57 +131,21 @@ impl<'tcx> CtxtInterners<'tcx> {

/// Intern a type
#[inline(never)]
fn intern_ty(
local: &CtxtInterners<'tcx>,
global: &CtxtInterners<'tcx>,
st: TyKind<'tcx>,
fn intern_ty(&self,
st: TyKind<'tcx>
) -> Ty<'tcx> {
let flags = super::flags::FlagComputation::for_sty(&st);

// HACK(eddyb) Depend on flags being accurate to
// determine that all contents are in the global tcx.
// See comments on Lift for why we can't use that.
if flags.flags.intersects(ty::TypeFlags::KEEP_IN_LOCAL_TCX) {
local.type_.borrow_mut().intern(st, |st| {
let ty_struct = TyS {
sty: st,
flags: flags.flags,
outer_exclusive_binder: flags.outer_exclusive_binder,
};
self.type_.borrow_mut().intern(st, |st| {
let flags = super::flags::FlagComputation::for_sty(&st);

// Make sure we don't end up with inference
// types/regions in the global interner
if ptr_eq(local, global) {
bug!("Attempted to intern `{:?}` which contains \
inference types/regions in the global type context",
&ty_struct);
}

// This is safe because all the types the ty_struct can point to
// already is in the local arena or the global arena
let ty_struct: TyS<'tcx> = unsafe {
mem::transmute(ty_struct)
};

Interned(local.arena.alloc(ty_struct))
}).0
} else {
global.type_.borrow_mut().intern(st, |st| {
let ty_struct = TyS {
sty: st,
flags: flags.flags,
outer_exclusive_binder: flags.outer_exclusive_binder,
};
let ty_struct = TyS {
sty: st,
flags: flags.flags,
outer_exclusive_binder: flags.outer_exclusive_binder,
};

// This is safe because all the types the ty_struct can point to
// already is in the global arena
let ty_struct: TyS<'tcx> = unsafe {
mem::transmute(ty_struct)
};

Interned(global.arena.alloc(ty_struct))
}).0
}
Interned(self.arena.alloc(ty_struct))
}).0
}
}

@@ -933,7 +892,7 @@ EnumLiftImpl! {

impl<'tcx> CommonTypes<'tcx> {
fn new(interners: &CtxtInterners<'tcx>) -> CommonTypes<'tcx> {
let mk = |sty| CtxtInterners::intern_ty(interners, interners, sty);
let mk = |sty| interners.intern_ty(sty);

CommonTypes {
unit: mk(Tuple(List::empty())),
@@ -1015,8 +974,6 @@ pub struct FreeRegionInfo {
#[derive(Copy, Clone)]
pub struct TyCtxt<'tcx> {
gcx: &'tcx GlobalCtxt<'tcx>,
interners: &'tcx CtxtInterners<'tcx>,
dummy: PhantomData<&'tcx ()>,
}

impl<'tcx> Deref for TyCtxt<'tcx> {
@@ -1030,8 +987,7 @@ impl<'tcx> Deref for TyCtxt<'tcx> {
pub struct GlobalCtxt<'tcx> {
pub arena: WorkerLocal<Arena<'tcx>>,

global_interners: CtxtInterners<'tcx>,
local_interners: CtxtInterners<'tcx>,
interners: CtxtInterners<'tcx>,

cstore: &'tcx CrateStoreDyn,

@@ -1122,8 +1078,6 @@ impl<'tcx> TyCtxt<'tcx> {
pub fn global_tcx(self) -> TyCtxt<'tcx> {
TyCtxt {
gcx: self.gcx,
interners: &self.gcx.global_interners,
dummy: PhantomData,
}
}

@@ -1203,11 +1157,6 @@ impl<'tcx> TyCtxt<'tcx> {
value.lift_to_tcx(self.global_tcx())
}

/// Returns `true` if self is the same as self.global_tcx().
fn is_global(self) -> bool {
ptr_eq(self.interners, &self.global_interners)
}

/// Creates a type context and call the closure with a `TyCtxt` reference
/// to the context. The closure enforces that the type context and any interned
/// value (types, substs, etc.) can only be used while `ty::tls` has a valid
@@ -1229,7 +1178,6 @@ impl<'tcx> TyCtxt<'tcx> {
s.fatal(&err);
});
let interners = CtxtInterners::new(&arenas.interner);
let local_interners = CtxtInterners::new(&arenas.local_interner);
let common = Common {
empty_predicates: ty::GenericPredicates {
parent: None,
@@ -1287,8 +1235,7 @@ impl<'tcx> TyCtxt<'tcx> {
sess: s,
cstore,
arena: WorkerLocal::new(|_| Arena::default()),
global_interners: interners,
local_interners: local_interners,
interners,
dep_graph,
common,
types: common_types,
@@ -1682,8 +1629,6 @@ impl<'tcx> GlobalCtxt<'tcx> {
{
let tcx = TyCtxt {
gcx: self,
interners: &self.local_interners,
dummy: PhantomData,
};
ty::tls::with_related_context(tcx.global_tcx(), |icx| {
let new_icx = ty::tls::ImplicitCtxt {
@@ -1729,11 +1674,7 @@ macro_rules! nop_lift {
type Lifted = $lifted;
fn lift_to_tcx(&self, tcx: TyCtxt<'tcx>) -> Option<Self::Lifted> {
if tcx.interners.arena.in_arena(*self as *const _) {
return Some(unsafe { mem::transmute(*self) });
}
// Also try in the global tcx if we're not that.
if !tcx.is_global() {
self.lift_to_tcx(tcx.global_tcx())
Some(unsafe { mem::transmute(*self) })
} else {
None
}
@@ -1751,11 +1692,7 @@ macro_rules! nop_list_lift {
return Some(List::empty());
}
if tcx.interners.arena.in_arena(*self as *const _) {
return Some(unsafe { mem::transmute(*self) });
}
// Also try in the global tcx if we're not that.
if !tcx.is_global() {
self.lift_to_tcx(tcx.global_tcx())
Some(unsafe { mem::transmute(*self) })
} else {
None
}
@@ -1785,7 +1722,6 @@ pub mod tls {

use std::fmt;
use std::mem;
use std::marker::PhantomData;
use syntax_pos;
use crate::ty::query;
use errors::{Diagnostic, TRACK_DIAGNOSTICS};
@@ -1949,8 +1885,6 @@ pub mod tls {

let tcx = TyCtxt {
gcx,
interners: &gcx.global_interners,
dummy: PhantomData,
};
let icx = ImplicitCtxt {
tcx,
@@ -1981,8 +1915,6 @@ pub mod tls {
let gcx = &*(gcx as *const GlobalCtxt<'_>);
let tcx = TyCtxt {
gcx,
interners: &gcx.global_interners,
dummy: PhantomData,
};
let icx = ImplicitCtxt {
query: None,
@@ -2041,26 +1973,6 @@ pub mod tls {
})
}

/// Allows access to the current ImplicitCtxt whose tcx field has the same global
/// interner and local interner as the tcx argument passed in. This means the closure
/// is given an ImplicitCtxt with the same 'tcx and 'tcx lifetimes as the TyCtxt passed in.
/// This will panic if you pass it a TyCtxt which has a different global interner or
/// a different local interner from the current ImplicitCtxt's tcx field.
#[inline]
pub fn with_fully_related_context<'tcx, F, R>(tcx: TyCtxt<'tcx>, f: F) -> R
where
F: for<'b> FnOnce(&ImplicitCtxt<'b, 'tcx>) -> R,
{
with_context(|context| {
unsafe {
assert!(ptr_eq(context.tcx.gcx, tcx.gcx));
assert!(ptr_eq(context.tcx.interners, tcx.interners));
let context: &ImplicitCtxt<'_, '_> = mem::transmute(context);
f(context)
}
})
}

/// Allows access to the TyCtxt in the current ImplicitCtxt.
/// Panics if there is no ImplicitCtxt available
#[inline]
@@ -2288,39 +2200,22 @@ impl<'tcx> Borrow<[Goal<'tcx>]> for Interned<'tcx, List<Goal<'tcx>>> {
macro_rules! intern_method {
($lt_tcx:tt, $name:ident: $method:ident($alloc:ty,
$alloc_method:expr,
$alloc_to_key:expr,
$keep_in_local_tcx:expr) -> $ty:ty) => {
$alloc_to_key:expr) -> $ty:ty) => {
impl<$lt_tcx> TyCtxt<$lt_tcx> {
pub fn $method(self, v: $alloc) -> &$lt_tcx $ty {
let key = ($alloc_to_key)(&v);

// HACK(eddyb) Depend on flags being accurate to
// determine that all contents are in the global tcx.
// See comments on Lift for why we can't use that.
if ($keep_in_local_tcx)(&v) {
self.interners.$name.borrow_mut().intern_ref(key, || {
// Make sure we don't end up with inference
// types/regions in the global tcx.
if self.is_global() {
bug!("Attempted to intern `{:?}` which contains \
inference types/regions in the global type context",
v);
}
self.interners.$name.borrow_mut().intern_ref(key, || {
Interned($alloc_method(&self.interners.arena, v))

Interned($alloc_method(&self.interners.arena, v))
}).0
} else {
self.global_interners.$name.borrow_mut().intern_ref(key, || {
Interned($alloc_method(&self.global_interners.arena, v))
}).0
}
}).0
}
}
}
}

macro_rules! direct_interners {
($lt_tcx:tt, $($name:ident: $method:ident($keep_in_local_tcx:expr) -> $ty:ty),+) => {
($lt_tcx:tt, $($name:ident: $method:ident($ty:ty)),+) => {
$(impl<$lt_tcx> PartialEq for Interned<$lt_tcx, $ty> {
fn eq(&self, other: &Self) -> bool {
self.0 == other.0
@@ -2339,8 +2234,7 @@ macro_rules! direct_interners {
$lt_tcx,
$name: $method($ty,
|a: &$lt_tcx SyncDroplessArena, v| -> &$lt_tcx $ty { a.alloc(v) },
|x| x,
$keep_in_local_tcx) -> $ty);)+
|x| x) -> $ty);)+
}
}

@@ -2349,18 +2243,17 @@ pub fn keep_local<'tcx, T: ty::TypeFoldable<'tcx>>(x: &T) -> bool {
}

direct_interners!('tcx,
region: mk_region(|r: &RegionKind| r.keep_in_local_tcx()) -> RegionKind,
goal: mk_goal(|c: &GoalKind<'_>| keep_local(c)) -> GoalKind<'tcx>,
const_: mk_const(|c: &Const<'_>| keep_local(&c)) -> Const<'tcx>
region: mk_region(RegionKind),
goal: mk_goal(GoalKind<'tcx>),
const_: mk_const(Const<'tcx>)
);

macro_rules! slice_interners {
($($field:ident: $method:ident($ty:ty)),+) => (
$(intern_method!( 'tcx, $field: $method(
&[$ty],
|a, v| List::from_arena(a, v),
Deref::deref,
|xs: &[$ty]| xs.iter().any(keep_local)) -> List<$ty>);)+
Deref::deref) -> List<$ty>);)+
);
}

@@ -2384,8 +2277,7 @@ intern_method! {
canonical_var_infos: _intern_canonical_var_infos(
&[CanonicalVarInfo],
|a, v| List::from_arena(a, v),
Deref::deref,
|_xs: &[CanonicalVarInfo]| -> bool { false }
Deref::deref
) -> List<CanonicalVarInfo>
}

@@ -2431,7 +2323,7 @@ impl<'tcx> TyCtxt<'tcx> {

#[inline]
pub fn mk_ty(&self, st: TyKind<'tcx>) -> Ty<'tcx> {
CtxtInterners::intern_ty(&self.interners, &self.global_interners, st)
self.interners.intern_ty(st)
}

pub fn mk_mach_int(self, tm: ast::IntTy) -> Ty<'tcx> {

0 comments on commit ec8c2e1

Please sign in to comment.
You can’t perform that action at this time.