Skip to content

Commit fc5c31c

Browse files
committed
rustc: make the comon case of tcx.infer_ctxt(()) nicer.
1 parent 63481a5 commit fc5c31c

File tree

19 files changed

+102
-112
lines changed

19 files changed

+102
-112
lines changed

src/librustc/infer/mod.rs

Lines changed: 30 additions & 70 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ use ty::fold::{TypeFoldable, TypeFolder, TypeVisitor};
3131
use ty::relate::RelateResult;
3232
use traits::{self, ObligationCause, PredicateObligations, Reveal};
3333
use rustc_data_structures::unify::{self, UnificationTable};
34-
use std::cell::{Cell, RefCell, Ref, RefMut};
34+
use std::cell::{Cell, RefCell, Ref};
3535
use std::fmt;
3636
use syntax::ast;
3737
use errors::DiagnosticBuilder;
@@ -72,39 +72,14 @@ pub type Bound<T> = Option<T>;
7272
pub type UnitResult<'tcx> = RelateResult<'tcx, ()>; // "unify result"
7373
pub type FixupResult<T> = Result<T, FixupError>; // "fixup result"
7474

75-
/// A version of &ty::TypeckTables which can be `Missing` (not needed),
76-
/// `InProgress` (during typeck) or `Interned` (result of typeck).
77-
/// Only the `InProgress` version supports `borrow_mut`.
78-
#[derive(Copy, Clone)]
79-
pub enum InferTables<'a, 'tcx: 'a> {
80-
InProgress(&'a RefCell<ty::TypeckTables<'tcx>>),
81-
Missing
82-
}
83-
84-
impl<'a, 'tcx> InferTables<'a, 'tcx> {
85-
pub fn borrow(self) -> Ref<'a, ty::TypeckTables<'tcx>> {
86-
match self {
87-
InferTables::InProgress(tables) => tables.borrow(),
88-
InferTables::Missing => {
89-
bug!("InferTables: infcx.tables.borrow() with no tables")
90-
}
91-
}
92-
}
93-
94-
pub fn borrow_mut(self) -> RefMut<'a, ty::TypeckTables<'tcx>> {
95-
match self {
96-
InferTables::InProgress(tables) => tables.borrow_mut(),
97-
InferTables::Missing => {
98-
bug!("InferTables: infcx.tables.borrow_mut() with no tables")
99-
}
100-
}
101-
}
102-
}
103-
10475
pub struct InferCtxt<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
10576
pub tcx: TyCtxt<'a, 'gcx, 'tcx>,
10677

107-
pub tables: InferTables<'a, 'tcx>,
78+
/// During type-checking/inference of a body, `in_progress_tables`
79+
/// contains a reference to the tables being built up, which are
80+
/// used for reading closure kinds/signatures as they are inferred,
81+
/// and for error reporting logic to read arbitrary node types.
82+
pub in_progress_tables: Option<&'a RefCell<ty::TypeckTables<'tcx>>>,
10883

10984
// Cache for projections. This cache is snapshotted along with the
11085
// infcx.
@@ -360,23 +335,7 @@ impl fmt::Display for FixupError {
360335
}
361336
}
362337

363-
pub trait InferEnv<'a, 'tcx> {
364-
fn fresh_tables(self) -> Option<ty::TypeckTables<'tcx>>;
365-
}
366-
367-
impl<'a, 'tcx> InferEnv<'a, 'tcx> for () {
368-
fn fresh_tables(self) -> Option<ty::TypeckTables<'tcx>> {
369-
None
370-
}
371-
}
372-
373-
impl<'a, 'tcx> InferEnv<'a, 'tcx> for ty::TypeckTables<'tcx> {
374-
fn fresh_tables(self) -> Option<ty::TypeckTables<'tcx>> {
375-
Some(self)
376-
}
377-
}
378-
379-
/// Helper type of a temporary returned by tcx.infer_ctxt(...).
338+
/// Helper type of a temporary returned by tcx.infer_ctxt().
380339
/// Necessary because we can't write the following bound:
381340
/// F: for<'b, 'tcx> where 'gcx: 'tcx FnOnce(InferCtxt<'b, 'gcx, 'tcx>).
382341
pub struct InferCtxtBuilder<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
@@ -386,16 +345,23 @@ pub struct InferCtxtBuilder<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
386345
}
387346

388347
impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'gcx> {
389-
pub fn infer_ctxt<E: InferEnv<'a, 'gcx>>(self, env: E) -> InferCtxtBuilder<'a, 'gcx, 'tcx> {
348+
pub fn infer_ctxt(self) -> InferCtxtBuilder<'a, 'gcx, 'tcx> {
390349
InferCtxtBuilder {
391350
global_tcx: self,
392351
arena: DroplessArena::new(),
393-
fresh_tables: env.fresh_tables().map(RefCell::new),
352+
fresh_tables: None,
394353
}
395354
}
396355
}
397356

398357
impl<'a, 'gcx, 'tcx> InferCtxtBuilder<'a, 'gcx, 'tcx> {
358+
/// Used only by `rustc_typeck` during body type-checking/inference,
359+
/// will initialize `in_progress_tables` with fresh `TypeckTables`.
360+
pub fn with_fresh_in_progress_tables(mut self) -> Self {
361+
self.fresh_tables = Some(RefCell::new(ty::TypeckTables::empty()));
362+
self
363+
}
364+
399365
pub fn enter<F, R>(&'tcx mut self, f: F) -> R
400366
where F: for<'b> FnOnce(InferCtxt<'b, 'gcx, 'tcx>) -> R
401367
{
@@ -404,11 +370,10 @@ impl<'a, 'gcx, 'tcx> InferCtxtBuilder<'a, 'gcx, 'tcx> {
404370
ref arena,
405371
ref fresh_tables,
406372
} = *self;
407-
let tables = fresh_tables.as_ref()
408-
.map_or(InferTables::Missing, InferTables::InProgress);
373+
let in_progress_tables = fresh_tables.as_ref();
409374
global_tcx.enter_local(arena, |tcx| f(InferCtxt {
410-
tcx: tcx,
411-
tables: tables,
375+
tcx,
376+
in_progress_tables,
412377
projection_cache: RefCell::new(traits::ProjectionCache::new()),
413378
type_variables: RefCell::new(type_variable::TypeVariableTable::new()),
414379
int_unification_table: RefCell::new(UnificationTable::new()),
@@ -531,7 +496,7 @@ impl<'a, 'tcx> TyCtxt<'a, 'tcx, 'tcx> {
531496
return value;
532497
}
533498

534-
self.infer_ctxt(()).enter(|infcx| {
499+
self.infer_ctxt().enter(|infcx| {
535500
value.trans_normalize(&infcx, param_env)
536501
})
537502
}
@@ -553,7 +518,7 @@ impl<'a, 'tcx> TyCtxt<'a, 'tcx, 'tcx> {
553518
return value;
554519
}
555520

556-
self.infer_ctxt(()).enter(|infcx| {
521+
self.infer_ctxt().enter(|infcx| {
557522
value.trans_normalize(&infcx, env.reveal_all())
558523
})
559524
}
@@ -757,10 +722,9 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
757722
was_in_snapshot: in_snapshot,
758723
// Borrow tables "in progress" (i.e. during typeck)
759724
// to ban writes from within a snapshot to them.
760-
_in_progress_tables: match self.tables {
761-
InferTables::InProgress(ref tables) => tables.try_borrow().ok(),
762-
_ => None
763-
}
725+
_in_progress_tables: self.in_progress_tables.map(|tables| {
726+
tables.borrow()
727+
})
764728
}
765729
}
766730

@@ -1366,14 +1330,10 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
13661330
span: Span)
13671331
-> bool {
13681332
let ty = self.resolve_type_vars_if_possible(&ty);
1369-
if let Some((param_env, ty)) = self.tcx.lift_to_global(&(param_env, ty)) {
1370-
// Even if the type may have no inference variables, during
1371-
// type-checking closure types are in local tables only.
1372-
let local_closures = match self.tables {
1373-
InferTables::InProgress(_) => ty.has_closure_types(),
1374-
_ => false
1375-
};
1376-
if !local_closures {
1333+
// Even if the type may have no inference variables, during
1334+
// type-checking closure types are in local tables only.
1335+
if !self.in_progress_tables.is_some() || !ty.has_closure_types() {
1336+
if let Some((param_env, ty)) = self.tcx.lift_to_global(&(param_env, ty)) {
13771337
return ty.moves_by_default(self.tcx.global_tcx(), param_env, span);
13781338
}
13791339
}
@@ -1391,7 +1351,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
13911351
def_id: DefId)
13921352
-> Option<ty::ClosureKind>
13931353
{
1394-
if let InferTables::InProgress(tables) = self.tables {
1354+
if let Some(tables) = self.in_progress_tables {
13951355
if let Some(id) = self.tcx.hir.as_local_node_id(def_id) {
13961356
return tables.borrow()
13971357
.closure_kinds
@@ -1409,7 +1369,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
14091369
}
14101370

14111371
pub fn closure_type(&self, def_id: DefId) -> ty::PolyFnSig<'tcx> {
1412-
if let InferTables::InProgress(tables) = self.tables {
1372+
if let Some(tables) = self.in_progress_tables {
14131373
if let Some(id) = self.tcx.hir.as_local_node_id(def_id) {
14141374
if let Some(&ty) = tables.borrow().closure_tys.get(&id) {
14151375
return ty;

src/librustc/traits/error_reporting.rs

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ use hir::{self, intravisit, Local, Pat, Body};
2929
use hir::intravisit::{Visitor, NestedVisitorMap};
3030
use hir::map::NodeExpr;
3131
use hir::def_id::DefId;
32-
use infer::{self, InferCtxt, InferTables};
32+
use infer::{self, InferCtxt};
3333
use infer::type_variable::TypeVariableOrigin;
3434
use rustc::lint::builtin::EXTRA_REQUIREMENT_IN_IMPL;
3535
use std::fmt;
@@ -72,9 +72,12 @@ struct FindLocalByTypeVisitor<'a, 'gcx: 'a + 'tcx, 'tcx: 'a> {
7272
}
7373

7474
impl<'a, 'gcx, 'tcx> FindLocalByTypeVisitor<'a, 'gcx, 'tcx> {
75-
fn node_matches_type(&mut self, node_id: &'gcx NodeId) -> bool {
76-
match self.infcx.tables.borrow().node_types.get(node_id) {
77-
Some(&ty) => {
75+
fn node_matches_type(&mut self, node_id: NodeId) -> bool {
76+
let ty_opt = self.infcx.in_progress_tables.and_then(|tables| {
77+
tables.borrow().node_id_to_type_opt(node_id)
78+
});
79+
match ty_opt {
80+
Some(ty) => {
7881
let ty = self.infcx.resolve_type_vars_if_possible(&ty);
7982
ty.walk().any(|inner_ty| {
8083
inner_ty == *self.target_ty || match (&inner_ty.sty, &self.target_ty.sty) {
@@ -88,7 +91,7 @@ impl<'a, 'gcx, 'tcx> FindLocalByTypeVisitor<'a, 'gcx, 'tcx> {
8891
}
8992
})
9093
}
91-
_ => false,
94+
None => false,
9295
}
9396
}
9497
}
@@ -99,15 +102,15 @@ impl<'a, 'gcx, 'tcx> Visitor<'gcx> for FindLocalByTypeVisitor<'a, 'gcx, 'tcx> {
99102
}
100103

101104
fn visit_local(&mut self, local: &'gcx Local) {
102-
if self.found_local_pattern.is_none() && self.node_matches_type(&local.id) {
105+
if self.found_local_pattern.is_none() && self.node_matches_type(local.id) {
103106
self.found_local_pattern = Some(&*local.pat);
104107
}
105108
intravisit::walk_local(self, local);
106109
}
107110

108111
fn visit_body(&mut self, body: &'gcx Body) {
109112
for argument in &body.arguments {
110-
if self.found_arg_pattern.is_none() && self.node_matches_type(&argument.id) {
113+
if self.found_arg_pattern.is_none() && self.node_matches_type(argument.id) {
111114
self.found_arg_pattern = Some(&*argument.pat);
112115
}
113116
}
@@ -654,7 +657,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
654657

655658
// Additional context information explaining why the closure only implements
656659
// a particular trait.
657-
if let InferTables::InProgress(tables) = self.tables {
660+
if let Some(tables) = self.in_progress_tables {
658661
match tables.borrow().closure_kinds.get(&node_id) {
659662
Some(&(ty::ClosureKind::FnOnce, Some((span, name)))) => {
660663
err.span_note(span, &format!(

src/librustc/traits/mod.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -484,7 +484,7 @@ pub fn normalize_param_env_or_error<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
484484
let elaborated_env = ty::ParamEnv::new(tcx.intern_predicates(&predicates),
485485
unnormalized_env.reveal);
486486

487-
tcx.infer_ctxt(()).enter(|infcx| {
487+
tcx.infer_ctxt().enter(|infcx| {
488488
let predicates = match fully_normalize(
489489
&infcx,
490490
cause,
@@ -598,7 +598,7 @@ pub fn normalize_and_test_predicates<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
598598
debug!("normalize_and_test_predicates(predicates={:?})",
599599
predicates);
600600

601-
tcx.infer_ctxt(()).enter(|infcx| {
601+
tcx.infer_ctxt().enter(|infcx| {
602602
let param_env = ty::ParamEnv::empty(Reveal::All);
603603
let mut selcx = SelectionContext::new(&infcx);
604604
let mut fulfill_cx = FulfillmentContext::new();

src/librustc/traits/specialize/mod.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -125,7 +125,7 @@ pub fn find_associated_item<'a, 'tcx>(
125125
let ancestors = trait_def.ancestors(tcx, impl_data.impl_def_id);
126126
match ancestors.defs(tcx, item.name, item.kind).next() {
127127
Some(node_item) => {
128-
let substs = tcx.infer_ctxt(()).enter(|infcx| {
128+
let substs = tcx.infer_ctxt().enter(|infcx| {
129129
let param_env = ty::ParamEnv::empty(Reveal::All);
130130
let substs = substs.rebase_onto(tcx, trait_def_id, impl_data.substs);
131131
let substs = translate_substs(&infcx, param_env, impl_data.impl_def_id,
@@ -188,7 +188,7 @@ pub fn specializes<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
188188
let impl1_trait_ref = tcx.impl_trait_ref(impl1_def_id).unwrap();
189189

190190
// Create a infcx, taking the predicates of impl1 as assumptions:
191-
let result = tcx.infer_ctxt(()).enter(|infcx| {
191+
let result = tcx.infer_ctxt().enter(|infcx| {
192192
// Normalize the trait reference. The WF rules ought to ensure
193193
// that this always succeeds.
194194
let impl1_trait_ref =

src/librustc/traits/specialize/specialization_graph.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -109,7 +109,7 @@ impl<'a, 'gcx, 'tcx> Children {
109109
let possible_sibling = *slot;
110110

111111
let tcx = tcx.global_tcx();
112-
let (le, ge) = tcx.infer_ctxt(()).enter(|infcx| {
112+
let (le, ge) = tcx.infer_ctxt().enter(|infcx| {
113113
let overlap = traits::overlapping_impls(&infcx,
114114
possible_sibling,
115115
impl_def_id);

src/librustc/traits/trans/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ impl<'a, 'tcx> TyCtxt<'a, 'tcx, 'tcx> {
4646

4747
// Do the initial selection for the obligation. This yields the
4848
// shallow result we are looking for -- that is, what specific impl.
49-
self.infer_ctxt(()).enter(|infcx| {
49+
self.infer_ctxt().enter(|infcx| {
5050
let mut selcx = SelectionContext::new(&infcx);
5151

5252
let param_env = ty::ParamEnv::empty(Reveal::All);

src/librustc/ty/util.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -175,7 +175,7 @@ impl<'tcx> ty::ParamEnv<'tcx> {
175175
self_type: Ty<'tcx>, span: Span)
176176
-> Result<(), CopyImplementationError<'tcx>> {
177177
// FIXME: (@jroesch) float this code up
178-
tcx.infer_ctxt(()).enter(|infcx| {
178+
tcx.infer_ctxt().enter(|infcx| {
179179
let (adt, substs) = match self_type.sty {
180180
ty::TyAdt(adt, substs) => (adt, substs),
181181
_ => return Err(CopyImplementationError::NotAnAdt),
@@ -977,7 +977,7 @@ fn is_copy_raw<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
977977
{
978978
let (param_env, ty) = query.into_parts();
979979
let trait_def_id = tcx.require_lang_item(lang_items::CopyTraitLangItem);
980-
tcx.infer_ctxt(())
980+
tcx.infer_ctxt()
981981
.enter(|infcx| traits::type_known_to_meet_bound(&infcx,
982982
param_env,
983983
ty,
@@ -991,7 +991,7 @@ fn is_sized_raw<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
991991
{
992992
let (param_env, ty) = query.into_parts();
993993
let trait_def_id = tcx.require_lang_item(lang_items::SizedTraitLangItem);
994-
tcx.infer_ctxt(())
994+
tcx.infer_ctxt()
995995
.enter(|infcx| traits::type_known_to_meet_bound(&infcx,
996996
param_env,
997997
ty,
@@ -1005,7 +1005,7 @@ fn is_freeze_raw<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
10051005
{
10061006
let (param_env, ty) = query.into_parts();
10071007
let trait_def_id = tcx.require_lang_item(lang_items::FreezeTraitLangItem);
1008-
tcx.infer_ctxt(())
1008+
tcx.infer_ctxt()
10091009
.enter(|infcx| traits::type_known_to_meet_bound(&infcx,
10101010
param_env,
10111011
ty,

src/librustc_const_eval/eval.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -483,7 +483,7 @@ fn resolve_trait_associated_const<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
483483
debug!("resolve_trait_associated_const: trait_ref={:?}",
484484
trait_ref);
485485

486-
tcx.infer_ctxt(()).enter(|infcx| {
486+
tcx.infer_ctxt().enter(|infcx| {
487487
let param_env = ty::ParamEnv::empty(Reveal::UserFacing);
488488
let mut selcx = traits::SelectionContext::new(&infcx);
489489
let obligation = traits::Obligation::new(traits::ObligationCause::dummy(),

src/librustc_driver/test.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -154,7 +154,7 @@ fn test_env<F>(source_string: &str,
154154
index,
155155
"test_crate",
156156
|tcx| {
157-
tcx.infer_ctxt(()).enter(|infcx| {
157+
tcx.infer_ctxt().enter(|infcx| {
158158
let mut region_maps = RegionMaps::new();
159159
body(Env {
160160
infcx: &infcx,

src/librustc_lint/builtin.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -956,7 +956,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnconditionalRecursion {
956956
cx.param_env,
957957
trait_ref.to_poly_trait_predicate());
958958

959-
tcx.infer_ctxt(()).enter(|infcx| {
959+
tcx.infer_ctxt().enter(|infcx| {
960960
let mut selcx = traits::SelectionContext::new(&infcx);
961961
match selcx.select(&obligation) {
962962
// The method comes from a `T: Trait` bound.

src/librustc_mir/build/mod.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,7 @@ pub fn mir_build<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> Mir<'t
8383
};
8484

8585
let src = MirSource::from_node(tcx, id);
86-
tcx.infer_ctxt(()).enter(|infcx| {
86+
tcx.infer_ctxt().enter(|infcx| {
8787
let cx = Cx::new(&infcx, src);
8888
let mut mir = if cx.tables().tainted_by_errors {
8989
build::construct_error(cx, body_id)
@@ -171,7 +171,7 @@ fn create_constructor_shim<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
171171
{
172172
let span = tcx.hir.span(ctor_id);
173173
if let hir::VariantData::Tuple(ref fields, ctor_id) = *v {
174-
tcx.infer_ctxt(()).enter(|infcx| {
174+
tcx.infer_ctxt().enter(|infcx| {
175175
let (mut mir, src) =
176176
shim::build_adt_ctor(&infcx, ctor_id, fields, span);
177177

src/librustc_mir/transform/qualify_consts.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -998,7 +998,7 @@ impl MirPass for QualifyAndPromoteConstants {
998998
// Statics must be Sync.
999999
if mode == Mode::Static {
10001000
let ty = mir.return_ty;
1001-
tcx.infer_ctxt(()).enter(|infcx| {
1001+
tcx.infer_ctxt().enter(|infcx| {
10021002
let param_env = ty::ParamEnv::empty(Reveal::UserFacing);
10031003
let cause = traits::ObligationCause::new(mir.span, id, traits::SharedStatic);
10041004
let mut fulfillment_cx = traits::FulfillmentContext::new();

0 commit comments

Comments
 (0)