Skip to content

Commit 89d711d

Browse files
committed
Add a fast path for computing if a type should be in the local interner
1 parent 9bc15f8 commit 89d711d

File tree

2 files changed

+171
-2
lines changed

2 files changed

+171
-2
lines changed

src/librustc/ty/context.rs

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2267,17 +2267,23 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
22672267
}
22682268

22692269
pub fn mk_ty(&self, st: TypeVariants<'tcx>) -> Ty<'tcx> {
2270-
let flags = super::flags::FlagComputation::for_sty(&st);
2270+
let keep_in_local_tcx = super::flags::sty_in_local_arena(&st);
22712271

22722272
// HACK(eddyb) Depend on flags being accurate to
22732273
// determine that all contents are in the global tcx.
22742274
// See comments on Lift for why we can't use that.
2275-
if flags.flags.intersects(ty::TypeFlags::KEEP_IN_LOCAL_TCX) {
2275+
if keep_in_local_tcx {
22762276
let mut interner = self.interners.type_.borrow_mut();
22772277
if let Some(&Interned(ty)) = interner.get(&st) {
22782278
return ty;
22792279
}
22802280

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+
22812287
let ty_struct = TyS {
22822288
sty: st,
22832289
flags: flags.flags,
@@ -2302,6 +2308,12 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
23022308
return ty;
23032309
}
23042310

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+
23052317
let ty_struct = TyS {
23062318
sty: st,
23072319
flags: flags.flags,

src/librustc/ty/flags.rs

Lines changed: 157 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -250,3 +250,160 @@ 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+
region_in_local_arena(r)
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+
region_in_local_arena(r) ||
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+
fn region_in_local_arena(r: ty::Region) -> bool {
371+
match *r {
372+
ty::ReVar(..) | ty::ReSkolemized(..) => true,
373+
ty::ReLateBound(..) |
374+
ty::ReEarlyBound(..) |
375+
ty::ReEmpty |
376+
ty::ReStatic |
377+
ty::ReFree { .. } |
378+
ty::ReScope { .. } |
379+
ty::ReErased |
380+
ty::ReCanonical(..) |
381+
ty::ReClosureBound(..) => false
382+
}
383+
}
384+
385+
#[inline(always)]
386+
fn const_in_local_arena(constant: &ty::Const) -> bool {
387+
if ty_in_local_arena(constant.ty) {
388+
return true;
389+
}
390+
match constant.val {
391+
ConstVal::Value(_) => false,
392+
ConstVal::Unevaluated(_, substs) => substs_in_local_arena(substs),
393+
}
394+
}
395+
396+
fn substs_in_local_arena(substs: &Substs) -> bool {
397+
for ty in substs.types() {
398+
if ty_in_local_arena(ty) {
399+
return true;
400+
}
401+
}
402+
403+
for r in substs.regions() {
404+
if region_in_local_arena(r) {
405+
return true;
406+
}
407+
}
408+
false
409+
}

0 commit comments

Comments
 (0)