Skip to content

Commit a1c170f

Browse files
committed
rustc: Split local type contexts interners from the global one.
1 parent 31a07b0 commit a1c170f

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

65 files changed

+1142
-700
lines changed

src/librustc/infer/mod.rs

+190-57
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ use middle::free_region::FreeRegionMap;
2424
use middle::mem_categorization as mc;
2525
use middle::mem_categorization::McResult;
2626
use middle::region::CodeExtent;
27+
use mir::tcx::LvalueTy;
2728
use ty::subst;
2829
use ty::subst::Substs;
2930
use ty::subst::Subst;
@@ -35,7 +36,7 @@ use ty::fold::TypeFoldable;
3536
use ty::relate::{Relate, RelateResult, TypeRelation};
3637
use traits::{self, PredicateObligations, ProjectionMode};
3738
use rustc_data_structures::unify::{self, UnificationTable};
38-
use std::cell::{Cell, RefCell, Ref};
39+
use std::cell::{Cell, RefCell, Ref, RefMut};
3940
use std::fmt;
4041
use syntax::ast;
4142
use syntax::codemap;
@@ -72,10 +73,36 @@ pub type Bound<T> = Option<T>;
7273
pub type UnitResult<'tcx> = RelateResult<'tcx, ()>; // "unify result"
7374
pub type FixupResult<T> = Result<T, FixupError>; // "fixup result"
7475

76+
/// A version of &ty::Tables which can be global or local.
77+
/// Only the local version supports borrow_mut.
78+
#[derive(Copy, Clone)]
79+
pub enum InferTables<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
80+
Global(&'a RefCell<ty::Tables<'gcx>>),
81+
Local(&'a RefCell<ty::Tables<'tcx>>)
82+
}
83+
84+
impl<'a, 'gcx, 'tcx> InferTables<'a, 'gcx, 'tcx> {
85+
pub fn borrow(self) -> Ref<'a, ty::Tables<'tcx>> {
86+
match self {
87+
InferTables::Global(tables) => tables.borrow(),
88+
InferTables::Local(tables) => tables.borrow()
89+
}
90+
}
91+
92+
pub fn borrow_mut(self) -> RefMut<'a, ty::Tables<'tcx>> {
93+
match self {
94+
InferTables::Global(_) => {
95+
bug!("InferTables: infcx.tables.borrow_mut() outside of type-checking");
96+
}
97+
InferTables::Local(tables) => tables.borrow_mut()
98+
}
99+
}
100+
}
101+
75102
pub struct InferCtxt<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
76103
pub tcx: TyCtxt<'a, 'gcx, 'tcx>,
77104

78-
pub tables: &'a RefCell<ty::Tables<'tcx>>,
105+
pub tables: InferTables<'a, 'gcx, 'tcx>,
79106

80107
// We instantiate UnificationTable with bounds<Ty> because the
81108
// types that might instantiate a general type variable have an
@@ -390,48 +417,106 @@ impl fmt::Display for FixupError {
390417
}
391418
}
392419

393-
impl<'a, 'tcx> InferCtxt<'a, 'tcx, 'tcx> {
394-
pub fn enter<F, R>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
395-
tables: Option<ty::Tables<'tcx>>,
396-
param_env: Option<ty::ParameterEnvironment<'tcx>>,
397-
projection_mode: ProjectionMode,
398-
f: F) -> R
399-
where F: for<'b> FnOnce(InferCtxt<'b, 'tcx, 'tcx>) -> R
420+
/// Helper type of a temporary returned by tcx.infer_ctxt(...).
421+
/// Necessary because we can't write the following bound:
422+
/// F: for<'b, 'tcx> where 'gcx: 'tcx FnOnce(InferCtxt<'b, 'gcx, 'tcx>).
423+
pub struct InferCtxtBuilder<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
424+
global_tcx: TyCtxt<'a, 'gcx, 'gcx>,
425+
arenas: ty::CtxtArenas<'tcx>,
426+
tables: Option<RefCell<ty::Tables<'tcx>>>,
427+
param_env: Option<ty::ParameterEnvironment<'gcx>>,
428+
projection_mode: ProjectionMode,
429+
normalize: bool
430+
}
431+
432+
impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'gcx> {
433+
pub fn infer_ctxt(self,
434+
tables: Option<ty::Tables<'tcx>>,
435+
param_env: Option<ty::ParameterEnvironment<'gcx>>,
436+
projection_mode: ProjectionMode)
437+
-> InferCtxtBuilder<'a, 'gcx, 'tcx> {
438+
InferCtxtBuilder {
439+
global_tcx: self,
440+
arenas: ty::CtxtArenas::new(),
441+
tables: tables.map(RefCell::new),
442+
param_env: param_env,
443+
projection_mode: projection_mode,
444+
normalize: false
445+
}
446+
}
447+
448+
pub fn normalizing_infer_ctxt(self, projection_mode: ProjectionMode)
449+
-> InferCtxtBuilder<'a, 'gcx, 'tcx> {
450+
InferCtxtBuilder {
451+
global_tcx: self,
452+
arenas: ty::CtxtArenas::new(),
453+
tables: None,
454+
param_env: None,
455+
projection_mode: projection_mode,
456+
normalize: false
457+
}
458+
}
459+
460+
/// Fake InferCtxt with the global tcx. Used by pre-MIR borrowck
461+
/// for MemCategorizationContext/ExprUseVisitor.
462+
/// If any inference functionality is used, ICEs will occur.
463+
pub fn borrowck_fake_infer_ctxt(self, param_env: ty::ParameterEnvironment<'gcx>)
464+
-> InferCtxt<'a, 'gcx, 'gcx> {
465+
InferCtxt {
466+
tcx: self,
467+
tables: InferTables::Global(&self.tables),
468+
type_variables: RefCell::new(type_variable::TypeVariableTable::new()),
469+
int_unification_table: RefCell::new(UnificationTable::new()),
470+
float_unification_table: RefCell::new(UnificationTable::new()),
471+
region_vars: RegionVarBindings::new(self),
472+
parameter_environment: param_env,
473+
selection_cache: traits::SelectionCache::new(),
474+
evaluation_cache: traits::EvaluationCache::new(),
475+
reported_trait_errors: RefCell::new(FnvHashSet()),
476+
normalize: false,
477+
projection_mode: ProjectionMode::AnyFinal,
478+
tainted_by_errors_flag: Cell::new(false),
479+
err_count_on_creation: self.sess.err_count()
480+
}
481+
}
482+
}
483+
484+
impl<'a, 'gcx, 'tcx> InferCtxtBuilder<'a, 'gcx, 'tcx> {
485+
pub fn enter<F, R>(&'tcx mut self, f: F) -> R
486+
where F: for<'b> FnOnce(InferCtxt<'b, 'gcx, 'tcx>) -> R
400487
{
401-
let new_tables;
402-
let tables = if let Some(tables) = tables {
403-
new_tables = RefCell::new(tables);
404-
&new_tables
488+
let InferCtxtBuilder {
489+
global_tcx,
490+
ref arenas,
491+
ref tables,
492+
ref mut param_env,
493+
projection_mode,
494+
normalize
495+
} = *self;
496+
let tables = if let Some(ref tables) = *tables {
497+
InferTables::Local(tables)
405498
} else {
406-
&tcx.tables
499+
InferTables::Global(&global_tcx.tables)
407500
};
408-
f(InferCtxt {
501+
let param_env = param_env.take().unwrap_or_else(|| {
502+
global_tcx.empty_parameter_environment()
503+
});
504+
global_tcx.enter_local(arenas, |tcx| f(InferCtxt {
409505
tcx: tcx,
410506
tables: tables,
411507
type_variables: RefCell::new(type_variable::TypeVariableTable::new()),
412508
int_unification_table: RefCell::new(UnificationTable::new()),
413509
float_unification_table: RefCell::new(UnificationTable::new()),
414510
region_vars: RegionVarBindings::new(tcx),
415-
parameter_environment: param_env.unwrap_or(tcx.empty_parameter_environment()),
511+
parameter_environment: param_env,
416512
selection_cache: traits::SelectionCache::new(),
417513
evaluation_cache: traits::EvaluationCache::new(),
418514
reported_trait_errors: RefCell::new(FnvHashSet()),
419-
normalize: false,
515+
normalize: normalize,
420516
projection_mode: projection_mode,
421-
tainted_by_errors_flag: Cell::new(false),
517+
tainted_by_errors_flag: Cell::new(false),
422518
err_count_on_creation: tcx.sess.err_count()
423-
})
424-
}
425-
426-
pub fn enter_normalizing<F, R>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
427-
projection_mode: ProjectionMode,
428-
f: F) -> R
429-
where F: for<'b> FnOnce(InferCtxt<'b, 'tcx, 'tcx>) -> R
430-
{
431-
InferCtxt::enter(tcx, None, None, projection_mode, |mut infcx| {
432-
infcx.normalize = true;
433-
f(infcx)
434-
})
519+
}))
435520
}
436521
}
437522

@@ -459,10 +544,54 @@ pub struct CombinedSnapshot {
459544
region_vars_snapshot: RegionSnapshot,
460545
}
461546

547+
/// Helper trait for shortening the lifetimes inside a
548+
/// value for post-type-checking normalization.
549+
pub trait TransNormalize<'gcx>: TypeFoldable<'gcx> {
550+
fn trans_normalize<'a, 'tcx>(&self, infcx: &InferCtxt<'a, 'gcx, 'tcx>) -> Self;
551+
}
552+
553+
macro_rules! items { ($($item:item)+) => ($($item)+) }
554+
macro_rules! impl_trans_normalize {
555+
($lt_gcx:tt, $($ty:ty),+) => {
556+
items!($(impl<$lt_gcx> TransNormalize<$lt_gcx> for $ty {
557+
fn trans_normalize<'a, 'tcx>(&self,
558+
infcx: &InferCtxt<'a, $lt_gcx, 'tcx>)
559+
-> Self {
560+
infcx.normalize_projections_in(self)
561+
}
562+
})+);
563+
}
564+
}
565+
566+
impl_trans_normalize!('gcx,
567+
Ty<'gcx>,
568+
&'gcx Substs<'gcx>,
569+
ty::FnSig<'gcx>,
570+
ty::FnOutput<'gcx>,
571+
&'gcx ty::BareFnTy<'gcx>,
572+
ty::ClosureSubsts<'gcx>,
573+
ty::PolyTraitRef<'gcx>
574+
);
575+
576+
impl<'gcx> TransNormalize<'gcx> for LvalueTy<'gcx> {
577+
fn trans_normalize<'a, 'tcx>(&self, infcx: &InferCtxt<'a, 'gcx, 'tcx>) -> Self {
578+
match *self {
579+
LvalueTy::Ty { ty } => LvalueTy::Ty { ty: ty.trans_normalize(infcx) },
580+
LvalueTy::Downcast { adt_def, substs, variant_index } => {
581+
LvalueTy::Downcast {
582+
adt_def: adt_def,
583+
substs: substs.trans_normalize(infcx),
584+
variant_index: variant_index
585+
}
586+
}
587+
}
588+
}
589+
}
590+
462591
// NOTE: Callable from trans only!
463592
impl<'a, 'tcx> TyCtxt<'a, 'tcx, 'tcx> {
464593
pub fn normalize_associated_type<T>(self, value: &T) -> T
465-
where T : TypeFoldable<'tcx>
594+
where T: TransNormalize<'tcx>
466595
{
467596
debug!("normalize_associated_type(t={:?})", value);
468597

@@ -472,15 +601,15 @@ impl<'a, 'tcx> TyCtxt<'a, 'tcx, 'tcx> {
472601
return value;
473602
}
474603

475-
InferCtxt::enter(self, None, None, ProjectionMode::Any, |infcx| {
476-
infcx.normalize_projections_in(&value)
604+
self.infer_ctxt(None, None, ProjectionMode::Any).enter(|infcx| {
605+
value.trans_normalize(&infcx)
477606
})
478607
}
479608
}
480609

481610
impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
482-
fn normalize_projections_in<T>(&self, value: &T) -> T
483-
where T : TypeFoldable<'tcx>
611+
fn normalize_projections_in<T>(&self, value: &T) -> T::Lifted
612+
where T: TypeFoldable<'tcx> + ty::Lift<'gcx>
484613
{
485614
let mut selcx = traits::SelectionContext::new(self);
486615
let cause = traits::ObligationCause::dummy();
@@ -503,16 +632,21 @@ pub fn drain_fulfillment_cx_or_panic<T>(&self,
503632
span: Span,
504633
fulfill_cx: &mut traits::FulfillmentContext<'tcx>,
505634
result: &T)
506-
-> T
507-
where T : TypeFoldable<'tcx>
635+
-> T::Lifted
636+
where T: TypeFoldable<'tcx> + ty::Lift<'gcx>
508637
{
509-
match self.drain_fulfillment_cx(fulfill_cx, result) {
638+
let when = "resolving bounds after type-checking";
639+
let v = match self.drain_fulfillment_cx(fulfill_cx, result) {
510640
Ok(v) => v,
511641
Err(errors) => {
512-
span_bug!(
513-
span,
514-
"Encountered errors `{:?}` fulfilling during trans",
515-
errors);
642+
span_bug!(span, "Encountered errors `{:?}` {}", errors, when);
643+
}
644+
};
645+
646+
match self.tcx.lift_to_global(&v) {
647+
Some(v) => v,
648+
None => {
649+
span_bug!(span, "Uninferred types/regions in `{:?}` {}", v, when);
516650
}
517651
}
518652
}
@@ -1449,18 +1583,16 @@ pub fn drain_fulfillment_cx<T>(&self,
14491583
self.resolve_type_vars_or_error(&ty)
14501584
}
14511585

1452-
pub fn tables_are_tcx_tables(&self) -> bool {
1453-
let tables: &RefCell<ty::Tables> = &self.tables;
1454-
let tcx_tables: &RefCell<ty::Tables> = &self.tcx.tables;
1455-
tables as *const _ as usize == tcx_tables as *const _ as usize
1456-
}
1457-
14581586
pub fn type_moves_by_default(&self, ty: Ty<'tcx>, span: Span) -> bool {
14591587
let ty = self.resolve_type_vars_if_possible(&ty);
14601588
if let Some(ty) = self.tcx.lift_to_global(&ty) {
1461-
// HACK(eddyb) Temporarily handle infer type in the global tcx.
1462-
if !ty.needs_infer() &&
1463-
!(ty.has_closure_types() && !self.tables_are_tcx_tables()) {
1589+
// Even if the type may have no inference variables, during
1590+
// type-checking closure types are in local tables only.
1591+
let local_closures = match self.tables {
1592+
InferTables::Local(_) => ty.has_closure_types(),
1593+
InferTables::Global(_) => false
1594+
};
1595+
if !local_closures {
14641596
return ty.moves_by_default(self.tcx.global_tcx(), self.param_env(), span);
14651597
}
14661598
}
@@ -1527,7 +1659,7 @@ pub fn drain_fulfillment_cx<T>(&self,
15271659
// during trans, we see closure ids from other traits.
15281660
// That may require loading the closure data out of the
15291661
// cstore.
1530-
Some(ty::Tables::closure_kind(&self.tables, self.tcx, def_id))
1662+
Some(self.tcx.closure_kind(def_id))
15311663
}
15321664
}
15331665

@@ -1536,12 +1668,13 @@ pub fn drain_fulfillment_cx<T>(&self,
15361668
substs: ty::ClosureSubsts<'tcx>)
15371669
-> ty::ClosureTy<'tcx>
15381670
{
1539-
let closure_ty =
1540-
ty::Tables::closure_type(self.tables,
1541-
self.tcx,
1542-
def_id,
1543-
substs);
1671+
if let InferTables::Local(tables) = self.tables {
1672+
if let Some(ty) = tables.borrow().closure_tys.get(&def_id) {
1673+
return ty.subst(self.tcx, substs.func_substs);
1674+
}
1675+
}
15441676

1677+
let closure_ty = self.tcx.closure_type(def_id, substs);
15451678
if self.normalize {
15461679
let closure_ty = self.tcx.erase_regions(&closure_ty);
15471680

0 commit comments

Comments
 (0)