Skip to content

Commit 116cf1c

Browse files
committed
Auto merge of #50332 - Zoxc:interner-split, r=<try>
[WIP] Only lookup types in one interner
2 parents 6a87289 + d452c3e commit 116cf1c

File tree

3 files changed

+225
-13
lines changed

3 files changed

+225
-13
lines changed

src/librustc/ty/context.rs

+64-8
Original file line numberDiff line numberDiff line change
@@ -2266,15 +2266,71 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
22662266
self.mk_fn_ptr(converted_sig)
22672267
}
22682268

2269-
// Interns a type/name combination, stores the resulting box in cx.interners,
2270-
// and returns the box as cast to an unsafe ptr (see comments for Ty above).
2271-
pub fn mk_ty(self, st: TypeVariants<'tcx>) -> Ty<'tcx> {
2272-
let global_interners = if !self.is_global() {
2273-
Some(&self.global_interners)
2269+
pub fn mk_ty(&self, st: TypeVariants<'tcx>) -> Ty<'tcx> {
2270+
let keep_in_local_tcx = super::flags::sty_in_local_arena(&st);
2271+
2272+
// HACK(eddyb) Depend on flags being accurate to
2273+
// determine that all contents are in the global tcx.
2274+
// See comments on Lift for why we can't use that.
2275+
if keep_in_local_tcx {
2276+
let mut interner = self.interners.type_.borrow_mut();
2277+
if let Some(&Interned(ty)) = interner.get(&st) {
2278+
return ty;
2279+
}
2280+
2281+
let flags = super::flags::FlagComputation::for_sty(&st);
2282+
2283+
assert_eq!(
2284+
flags.flags.intersects(ty::TypeFlags::KEEP_IN_LOCAL_TCX),
2285+
true);
2286+
2287+
let ty_struct = TyS {
2288+
sty: st,
2289+
flags: flags.flags,
2290+
region_depth: flags.depth,
2291+
};
2292+
2293+
// Make sure we don't end up with inference
2294+
// types/regions in the global tcx.
2295+
if self.is_global() {
2296+
bug!("Attempted to intern `{:?}` which contains \
2297+
inference types/regions in the global type context",
2298+
&ty_struct);
2299+
}
2300+
2301+
// Don't be &mut TyS.
2302+
let ty: Ty<'tcx> = self.interners.arena.alloc(ty_struct);
2303+
interner.insert(Interned(ty));
2304+
ty
22742305
} else {
2275-
None
2276-
};
2277-
self.interners.intern_ty(st, global_interners)
2306+
let mut interner = self.global_interners.type_.borrow_mut();
2307+
if let Some(&Interned(ty)) = interner.get(&st) {
2308+
return ty;
2309+
}
2310+
2311+
let flags = super::flags::FlagComputation::for_sty(&st);
2312+
2313+
assert_eq!(
2314+
flags.flags.intersects(ty::TypeFlags::KEEP_IN_LOCAL_TCX),
2315+
false);
2316+
2317+
let ty_struct = TyS {
2318+
sty: st,
2319+
flags: flags.flags,
2320+
region_depth: flags.depth,
2321+
};
2322+
2323+
// This is safe because all the types the ty_struct can point to
2324+
// already is in the global arena
2325+
let ty_struct: TyS<'gcx> = unsafe {
2326+
mem::transmute(ty_struct)
2327+
};
2328+
2329+
// Don't be &mut TyS.
2330+
let ty: Ty<'gcx> = self.global_interners.arena.alloc(ty_struct);
2331+
interner.insert(Interned(ty));
2332+
ty
2333+
}
22782334
}
22792335

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

src/librustc/ty/flags.rs

+142
Original file line numberDiff line numberDiff line change
@@ -250,3 +250,145 @@ impl FlagComputation {
250250
}
251251
}
252252
}
253+
254+
pub(crate) fn sty_in_local_arena(st: &ty::TypeVariants) -> bool {
255+
match *st {
256+
ty::TyBool |
257+
ty::TyChar |
258+
ty::TyInt(_) |
259+
ty::TyFloat(_) |
260+
ty::TyUint(_) |
261+
ty::TyNever |
262+
ty::TyStr |
263+
ty::TyForeign(..) |
264+
ty::TyError |
265+
ty::TyParam(..) => false,
266+
267+
ty::TyGenerator(_, ref substs, ref interior) => {
268+
substs_in_local_arena(&substs.substs) ||
269+
ty_in_local_arena(interior.witness)
270+
}
271+
272+
ty::TyGeneratorWitness(ref ts) => {
273+
tys_in_local_arena(&ts.skip_binder()[..])
274+
}
275+
276+
ty::TyClosure(_, ref substs) => {
277+
substs_in_local_arena(&substs.substs)
278+
}
279+
280+
ty::TyInfer(infer) => {
281+
match infer {
282+
ty::FreshTy(_) |
283+
ty::FreshIntTy(_) |
284+
ty::FreshFloatTy(_) |
285+
ty::CanonicalTy(_) => false,
286+
ty::TyVar(_) |
287+
ty::IntVar(_) |
288+
ty::FloatVar(_) => true
289+
}
290+
}
291+
292+
ty::TyAdt(_, substs) => {
293+
substs_in_local_arena(substs)
294+
}
295+
296+
ty::TyProjection(ref data) => {
297+
substs_in_local_arena(data.substs)
298+
}
299+
300+
ty::TyAnon(_, substs) => {
301+
substs_in_local_arena(substs)
302+
}
303+
304+
ty::TyDynamic(ref obj, r) => {
305+
for predicate in obj.skip_binder().iter() {
306+
match *predicate {
307+
ty::ExistentialPredicate::Trait(tr) => {
308+
if substs_in_local_arena(tr.substs) {
309+
return true;
310+
}
311+
}
312+
ty::ExistentialPredicate::Projection(p) => {
313+
if substs_in_local_arena(p.substs) || ty_in_local_arena(p.ty) {
314+
return true;
315+
}
316+
}
317+
ty::ExistentialPredicate::AutoTrait(_) => {}
318+
}
319+
}
320+
r.keep_in_local_tcx()
321+
}
322+
323+
ty::TyArray(tt, len) => {
324+
ty_in_local_arena(tt) ||
325+
const_in_local_arena(len)
326+
}
327+
328+
ty::TySlice(tt) => {
329+
ty_in_local_arena(tt)
330+
}
331+
332+
ty::TyRawPtr(ref m) => {
333+
ty_in_local_arena(m.ty)
334+
}
335+
336+
ty::TyRef(r, ref m) => {
337+
r.keep_in_local_tcx() ||
338+
ty_in_local_arena(m.ty)
339+
}
340+
341+
ty::TyTuple(ref ts) => {
342+
tys_in_local_arena(&ts[..])
343+
}
344+
345+
ty::TyFnDef(_, substs) => {
346+
substs_in_local_arena(substs)
347+
}
348+
349+
ty::TyFnPtr(f) => {
350+
tys_in_local_arena(f.skip_binder().inputs()) ||
351+
ty_in_local_arena(f.skip_binder().output())
352+
}
353+
}
354+
}
355+
356+
#[inline(always)]
357+
fn ty_in_local_arena(ty: Ty) -> bool {
358+
ty.flags.intersects(ty::TypeFlags::KEEP_IN_LOCAL_TCX)
359+
}
360+
361+
fn tys_in_local_arena(tys: &[Ty]) -> bool {
362+
for &ty in tys {
363+
if ty_in_local_arena(ty) {
364+
return true;
365+
}
366+
}
367+
false
368+
}
369+
370+
#[inline(always)]
371+
fn const_in_local_arena(constant: &ty::Const) -> bool {
372+
if ty_in_local_arena(constant.ty) {
373+
return true;
374+
}
375+
match constant.val {
376+
ConstVal::Value(_) => false,
377+
ConstVal::Unevaluated(_, substs) => substs_in_local_arena(substs),
378+
}
379+
}
380+
381+
fn substs_in_local_arena(substs: &Substs) -> bool {
382+
for ty in substs.types() {
383+
if ty_in_local_arena(ty) {
384+
return true;
385+
}
386+
}
387+
388+
for r in substs.regions() {
389+
if r.keep_in_local_tcx() {
390+
return true;
391+
}
392+
}
393+
false
394+
}

src/librustc/ty/sty.rs

+19-5
Original file line numberDiff line numberDiff line change
@@ -77,10 +77,9 @@ impl BoundRegion {
7777
}
7878
}
7979

80-
/// NB: If you change this, you'll probably want to change the corresponding
81-
/// AST structure in libsyntax/ast.rs as well.
82-
#[derive(Clone, PartialEq, Eq, Hash, Debug, RustcEncodable, RustcDecodable)]
83-
pub enum TypeVariants<'tcx> {
80+
macro_rules! type_variants {
81+
([$($t:tt)*][$($p:tt)*]) => {
82+
$($t)*(
8483
/// The primitive boolean type. Written as `bool`.
8584
TyBool,
8685

@@ -169,9 +168,24 @@ pub enum TypeVariants<'tcx> {
169168

170169
/// A placeholder for a type which could not be computed; this is
171170
/// propagated to avoid useless error messages.
172-
TyError,
171+
TyError,)$($p)*
172+
}
173173
}
174174

175+
macro_rules! declare_type_variants {
176+
($($t:tt)*) => {
177+
/// NB: If you change this, you'll probably want to change the corresponding
178+
/// AST structure in libsyntax/ast.rs as well.
179+
#[derive(Clone, PartialEq, Eq, Hash, Debug, RustcEncodable, RustcDecodable)]
180+
pub enum TypeVariants<'tcx> {
181+
$($t)*
182+
}
183+
}
184+
}
185+
186+
type_variants!([declare_type_variants!][;]);
187+
188+
175189
/// A closure can be modeled as a struct that looks like:
176190
///
177191
/// struct Closure<'l0...'li, T0...Tj, CK, CS, U0...Uk> {

0 commit comments

Comments
 (0)