Skip to content

Commit

Permalink
Auto merge of #33425 - eddyb:rift, r=nikomatsakis
Browse files Browse the repository at this point in the history
Split the type context into a global and a local (inference-only) one.

After this change, each `InferCtxt` creates its own local type interner for types with inference by-products.
Most of the code which handles both a global and a local interner uses `'gcx` and `'tcx` for them.
A reference to the type context in that situation (e.g. `infcx.tcx`) is `TyCtxt<'a, 'gcx, 'tcx>`.
The global type context which used to be `&'a TyCtxt<'tcx>` is now `TyCtxt<'a, 'tcx, 'tcx>`.

In order to minimize the number of extra lifetime parameters, many functions became methods.
Where possible (some inherent impls), lifetime parameters were added on the impl, not each method.

As inference by-products no longer escape their inference contexts, memory usage is lower.
Example of `-Z time-passes` excerpt for `librustc`, stage1 (~100MB gains):
Before "rustc: Split local type contexts interners from the global one.":
```
time: 0.395; rss: 335MB item-types checking
time: 15.392; rss: 472MB        item-bodies checking
time: 0.000; rss: 472MB drop-impl checking
time: 1.140; rss: 478MB const checking
time: 0.139; rss: 478MB privacy checking
time: 0.024; rss: 478MB stability index
time: 0.072; rss: 478MB intrinsic checking
time: 0.038; rss: 478MB effect checking
time: 0.255; rss: 478MB match checking
time: 0.128; rss: 484MB liveness checking
time: 1.372; rss: 484MB rvalue checking
time: 1.404; rss: 597MB MIR dump
time: 0.809; rss: 599MB MIR passes
```
After:
```
time: 0.467; rss: 337MB item-types checking
time: 17.443; rss: 395MB        item-bodies checking
time: 0.000; rss: 395MB drop-impl checking
time: 1.423; rss: 401MB const checking
time: 0.141; rss: 401MB privacy checking
time: 0.024; rss: 401MB stability index
time: 0.116; rss: 401MB intrinsic checking
time: 0.038; rss: 401MB effect checking
time: 0.382; rss: 401MB match checking
time: 0.132; rss: 407MB liveness checking
time: 1.678; rss: 407MB rvalue checking
time: 1.614; rss: 503MB MIR dump
time: 0.957; rss: 512MB MIR passes
```

**NOTE**: Functions changed to methods weren't re-indented to keep this PR easier to review.
Once approved, the changes will be mechanically performed.
However, indentation changes of function arguments are there - and I believe there's a way to hide whitespace-only changes in diffs on GitHub.
  • Loading branch information
bors committed May 11, 2016
2 parents 80ec1b9 + 42eb703 commit c7ab884
Show file tree
Hide file tree
Showing 199 changed files with 15,089 additions and 14,867 deletions.
6 changes: 3 additions & 3 deletions src/librustc/cfg/construct.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ use syntax::ptr::P;
use hir::{self, PatKind};

struct CFGBuilder<'a, 'tcx: 'a> {
tcx: &'a TyCtxt<'tcx>,
tcx: TyCtxt<'a, 'tcx, 'tcx>,
graph: CFGGraph,
fn_exit: CFGIndex,
loop_scopes: Vec<LoopScope>,
Expand All @@ -32,8 +32,8 @@ struct LoopScope {
break_index: CFGIndex, // where to go on a `break
}

pub fn construct(tcx: &TyCtxt,
blk: &hir::Block) -> CFG {
pub fn construct<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
blk: &hir::Block) -> CFG {
let mut graph = graph::Graph::new();
let entry = graph.add_node(CFGNodeData::Entry);

Expand Down
4 changes: 2 additions & 2 deletions src/librustc/cfg/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -58,8 +58,8 @@ pub type CFGNode = graph::Node<CFGNodeData>;
pub type CFGEdge = graph::Edge<CFGEdgeData>;

impl CFG {
pub fn new(tcx: &TyCtxt,
blk: &hir::Block) -> CFG {
pub fn new<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
blk: &hir::Block) -> CFG {
construct::construct(tcx, blk)
}

Expand Down
8 changes: 4 additions & 4 deletions src/librustc/dep_graph/visit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,13 +22,13 @@ use super::dep_node::DepNode;
/// read edge from the corresponding AST node. This is used in
/// compiler passes to automatically record the item that they are
/// working on.
pub fn visit_all_items_in_krate<'tcx,V,F>(tcx: &TyCtxt<'tcx>,
mut dep_node_fn: F,
visitor: &mut V)
pub fn visit_all_items_in_krate<'a, 'tcx, V, F>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
mut dep_node_fn: F,
visitor: &mut V)
where F: FnMut(DefId) -> DepNode<DefId>, V: Visitor<'tcx>
{
struct TrackingVisitor<'visit, 'tcx: 'visit, F: 'visit, V: 'visit> {
tcx: &'visit TyCtxt<'tcx>,
tcx: TyCtxt<'visit, 'tcx, 'tcx>,
dep_node_fn: &'visit mut F,
visitor: &'visit mut V
}
Expand Down
3 changes: 1 addition & 2 deletions src/librustc/hir/def.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,7 @@ use hir;
#[derive(Clone, Copy, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
pub enum Def {
Fn(DefId),
SelfTy(Option<DefId>, // trait id
Option<(ast::NodeId, ast::NodeId)>), // (impl id, self type id)
SelfTy(Option<DefId> /* trait */, Option<ast::NodeId> /* impl */),
Mod(DefId),
ForeignMod(DefId),
Static(DefId, bool /* is_mutbl */),
Expand Down
2 changes: 1 addition & 1 deletion src/librustc/hir/pat_util.rs
Original file line number Diff line number Diff line change
Expand Up @@ -209,7 +209,7 @@ pub fn simple_name<'a>(pat: &'a hir::Pat) -> Option<ast::Name> {
}
}

pub fn def_to_path(tcx: &TyCtxt, id: DefId) -> hir::Path {
pub fn def_to_path<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, id: DefId) -> hir::Path {
let name = tcx.item_name(id);
hir::Path::from_ident(DUMMY_SP, hir::Ident::from_name(name))
}
Expand Down
28 changes: 14 additions & 14 deletions src/librustc/infer/bivariate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,35 +25,35 @@
//! In particular, it might be enough to say (A,B) are bivariant for
//! all (A,B).
use super::combine::{self, CombineFields};
use super::combine::CombineFields;
use super::type_variable::{BiTo};

use ty::{self, Ty, TyCtxt};
use ty::TyVar;
use ty::relate::{Relate, RelateResult, TypeRelation};

pub struct Bivariate<'a, 'tcx: 'a> {
fields: CombineFields<'a, 'tcx>
pub struct Bivariate<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
fields: CombineFields<'a, 'gcx, 'tcx>
}

impl<'a, 'tcx> Bivariate<'a, 'tcx> {
pub fn new(fields: CombineFields<'a, 'tcx>) -> Bivariate<'a, 'tcx> {
impl<'a, 'gcx, 'tcx> Bivariate<'a, 'gcx, 'tcx> {
pub fn new(fields: CombineFields<'a, 'gcx, 'tcx>) -> Bivariate<'a, 'gcx, 'tcx> {
Bivariate { fields: fields }
}
}

impl<'a, 'tcx> TypeRelation<'a, 'tcx> for Bivariate<'a, 'tcx> {
impl<'a, 'gcx, 'tcx> TypeRelation<'a, 'gcx, 'tcx> for Bivariate<'a, 'gcx, 'tcx> {
fn tag(&self) -> &'static str { "Bivariate" }

fn tcx(&self) -> &'a TyCtxt<'tcx> { self.fields.tcx() }
fn tcx(&self) -> TyCtxt<'a, 'gcx, 'tcx> { self.fields.tcx() }

fn a_is_expected(&self) -> bool { self.fields.a_is_expected }

fn relate_with_variance<T:Relate<'a,'tcx>>(&mut self,
variance: ty::Variance,
a: &T,
b: &T)
-> RelateResult<'tcx, T>
fn relate_with_variance<T: Relate<'tcx>>(&mut self,
variance: ty::Variance,
a: &T,
b: &T)
-> RelateResult<'tcx, T>
{
match variance {
// If we have Foo<A> and Foo is invariant w/r/t A,
Expand Down Expand Up @@ -96,7 +96,7 @@ impl<'a, 'tcx> TypeRelation<'a, 'tcx> for Bivariate<'a, 'tcx> {
}

_ => {
combine::super_combine_tys(self.fields.infcx, self, a, b)
self.fields.infcx.super_combine_tys(self, a, b)
}
}
}
Expand All @@ -107,7 +107,7 @@ impl<'a, 'tcx> TypeRelation<'a, 'tcx> for Bivariate<'a, 'tcx> {

fn binders<T>(&mut self, a: &ty::Binder<T>, b: &ty::Binder<T>)
-> RelateResult<'tcx, ty::Binder<T>>
where T: Relate<'a,'tcx>
where T: Relate<'tcx>
{
let a1 = self.tcx().erase_late_bound_regions(a);
let b1 = self.tcx().erase_late_bound_regions(b);
Expand Down
184 changes: 93 additions & 91 deletions src/librustc/infer/combine.rs
Original file line number Diff line number Diff line change
Expand Up @@ -52,131 +52,133 @@ use syntax::ast;
use syntax::codemap::Span;

#[derive(Clone)]
pub struct CombineFields<'a, 'tcx: 'a> {
pub infcx: &'a InferCtxt<'a, 'tcx>,
pub struct CombineFields<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
pub infcx: &'a InferCtxt<'a, 'gcx, 'tcx>,
pub a_is_expected: bool,
pub trace: TypeTrace<'tcx>,
pub cause: Option<ty::relate::Cause>,
pub obligations: PredicateObligations<'tcx>,
}

pub fn super_combine_tys<'a,'tcx:'a,R>(infcx: &InferCtxt<'a, 'tcx>,
relation: &mut R,
a: Ty<'tcx>,
b: Ty<'tcx>)
-> RelateResult<'tcx, Ty<'tcx>>
where R: TypeRelation<'a,'tcx>
{
let a_is_expected = relation.a_is_expected();

match (&a.sty, &b.sty) {
// Relate integral variables to other types
(&ty::TyInfer(ty::IntVar(a_id)), &ty::TyInfer(ty::IntVar(b_id))) => {
infcx.int_unification_table
.borrow_mut()
.unify_var_var(a_id, b_id)
.map_err(|e| int_unification_error(a_is_expected, e))?;
Ok(a)
}
(&ty::TyInfer(ty::IntVar(v_id)), &ty::TyInt(v)) => {
unify_integral_variable(infcx, a_is_expected, v_id, IntType(v))
}
(&ty::TyInt(v), &ty::TyInfer(ty::IntVar(v_id))) => {
unify_integral_variable(infcx, !a_is_expected, v_id, IntType(v))
}
(&ty::TyInfer(ty::IntVar(v_id)), &ty::TyUint(v)) => {
unify_integral_variable(infcx, a_is_expected, v_id, UintType(v))
}
(&ty::TyUint(v), &ty::TyInfer(ty::IntVar(v_id))) => {
unify_integral_variable(infcx, !a_is_expected, v_id, UintType(v))
}
impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
pub fn super_combine_tys<R>(&self,
relation: &mut R,
a: Ty<'tcx>,
b: Ty<'tcx>)
-> RelateResult<'tcx, Ty<'tcx>>
where R: TypeRelation<'a, 'gcx, 'tcx>
{
let a_is_expected = relation.a_is_expected();

match (&a.sty, &b.sty) {
// Relate integral variables to other types
(&ty::TyInfer(ty::IntVar(a_id)), &ty::TyInfer(ty::IntVar(b_id))) => {
self.int_unification_table
.borrow_mut()
.unify_var_var(a_id, b_id)
.map_err(|e| int_unification_error(a_is_expected, e))?;
Ok(a)
}
(&ty::TyInfer(ty::IntVar(v_id)), &ty::TyInt(v)) => {
self.unify_integral_variable(a_is_expected, v_id, IntType(v))
}
(&ty::TyInt(v), &ty::TyInfer(ty::IntVar(v_id))) => {
self.unify_integral_variable(!a_is_expected, v_id, IntType(v))
}
(&ty::TyInfer(ty::IntVar(v_id)), &ty::TyUint(v)) => {
self.unify_integral_variable(a_is_expected, v_id, UintType(v))
}
(&ty::TyUint(v), &ty::TyInfer(ty::IntVar(v_id))) => {
self.unify_integral_variable(!a_is_expected, v_id, UintType(v))
}

// Relate floating-point variables to other types
(&ty::TyInfer(ty::FloatVar(a_id)), &ty::TyInfer(ty::FloatVar(b_id))) => {
infcx.float_unification_table
.borrow_mut()
.unify_var_var(a_id, b_id)
.map_err(|e| float_unification_error(relation.a_is_expected(), e))?;
Ok(a)
}
(&ty::TyInfer(ty::FloatVar(v_id)), &ty::TyFloat(v)) => {
unify_float_variable(infcx, a_is_expected, v_id, v)
}
(&ty::TyFloat(v), &ty::TyInfer(ty::FloatVar(v_id))) => {
unify_float_variable(infcx, !a_is_expected, v_id, v)
}
// Relate floating-point variables to other types
(&ty::TyInfer(ty::FloatVar(a_id)), &ty::TyInfer(ty::FloatVar(b_id))) => {
self.float_unification_table
.borrow_mut()
.unify_var_var(a_id, b_id)
.map_err(|e| float_unification_error(relation.a_is_expected(), e))?;
Ok(a)
}
(&ty::TyInfer(ty::FloatVar(v_id)), &ty::TyFloat(v)) => {
self.unify_float_variable(a_is_expected, v_id, v)
}
(&ty::TyFloat(v), &ty::TyInfer(ty::FloatVar(v_id))) => {
self.unify_float_variable(!a_is_expected, v_id, v)
}

// All other cases of inference are errors
(&ty::TyInfer(_), _) |
(_, &ty::TyInfer(_)) => {
Err(TypeError::Sorts(ty::relate::expected_found(relation, &a, &b)))
}
// All other cases of inference are errors
(&ty::TyInfer(_), _) |
(_, &ty::TyInfer(_)) => {
Err(TypeError::Sorts(ty::relate::expected_found(relation, &a, &b)))
}


_ => {
ty::relate::super_relate_tys(relation, a, b)
_ => {
ty::relate::super_relate_tys(relation, a, b)
}
}
}
}

fn unify_integral_variable<'a,'tcx>(infcx: &InferCtxt<'a,'tcx>,
vid_is_expected: bool,
vid: ty::IntVid,
val: ty::IntVarValue)
-> RelateResult<'tcx, Ty<'tcx>>
{
infcx.int_unification_table
.borrow_mut()
.unify_var_value(vid, val)
.map_err(|e| int_unification_error(vid_is_expected, e))?;
match val {
IntType(v) => Ok(infcx.tcx.mk_mach_int(v)),
UintType(v) => Ok(infcx.tcx.mk_mach_uint(v)),
fn unify_integral_variable(&self,
vid_is_expected: bool,
vid: ty::IntVid,
val: ty::IntVarValue)
-> RelateResult<'tcx, Ty<'tcx>>
{
self.int_unification_table
.borrow_mut()
.unify_var_value(vid, val)
.map_err(|e| int_unification_error(vid_is_expected, e))?;
match val {
IntType(v) => Ok(self.tcx.mk_mach_int(v)),
UintType(v) => Ok(self.tcx.mk_mach_uint(v)),
}
}
}

fn unify_float_variable<'a,'tcx>(infcx: &InferCtxt<'a,'tcx>,
vid_is_expected: bool,
vid: ty::FloatVid,
val: ast::FloatTy)
-> RelateResult<'tcx, Ty<'tcx>>
{
infcx.float_unification_table
.borrow_mut()
.unify_var_value(vid, val)
.map_err(|e| float_unification_error(vid_is_expected, e))?;
Ok(infcx.tcx.mk_mach_float(val))
fn unify_float_variable(&self,
vid_is_expected: bool,
vid: ty::FloatVid,
val: ast::FloatTy)
-> RelateResult<'tcx, Ty<'tcx>>
{
self.float_unification_table
.borrow_mut()
.unify_var_value(vid, val)
.map_err(|e| float_unification_error(vid_is_expected, e))?;
Ok(self.tcx.mk_mach_float(val))
}
}

impl<'a, 'tcx> CombineFields<'a, 'tcx> {
pub fn tcx(&self) -> &'a TyCtxt<'tcx> {
impl<'a, 'gcx, 'tcx> CombineFields<'a, 'gcx, 'tcx> {
pub fn tcx(&self) -> TyCtxt<'a, 'gcx, 'tcx> {
self.infcx.tcx
}

pub fn switch_expected(&self) -> CombineFields<'a, 'tcx> {
pub fn switch_expected(&self) -> CombineFields<'a, 'gcx, 'tcx> {
CombineFields {
a_is_expected: !self.a_is_expected,
..(*self).clone()
}
}

pub fn equate(&self) -> Equate<'a, 'tcx> {
pub fn equate(&self) -> Equate<'a, 'gcx, 'tcx> {
Equate::new(self.clone())
}

pub fn bivariate(&self) -> Bivariate<'a, 'tcx> {
pub fn bivariate(&self) -> Bivariate<'a, 'gcx, 'tcx> {
Bivariate::new(self.clone())
}

pub fn sub(&self) -> Sub<'a, 'tcx> {
pub fn sub(&self) -> Sub<'a, 'gcx, 'tcx> {
Sub::new(self.clone())
}

pub fn lub(&self) -> Lub<'a, 'tcx> {
pub fn lub(&self) -> Lub<'a, 'gcx, 'tcx> {
Lub::new(self.clone())
}

pub fn glb(&self) -> Glb<'a, 'tcx> {
pub fn glb(&self) -> Glb<'a, 'gcx, 'tcx> {
Glb::new(self.clone())
}

Expand Down Expand Up @@ -289,16 +291,16 @@ impl<'a, 'tcx> CombineFields<'a, 'tcx> {
}
}

struct Generalizer<'cx, 'tcx:'cx> {
infcx: &'cx InferCtxt<'cx, 'tcx>,
struct Generalizer<'cx, 'gcx: 'cx+'tcx, 'tcx: 'cx> {
infcx: &'cx InferCtxt<'cx, 'gcx, 'tcx>,
span: Span,
for_vid: ty::TyVid,
make_region_vars: bool,
cycle_detected: bool,
}

impl<'cx, 'tcx> ty::fold::TypeFolder<'tcx> for Generalizer<'cx, 'tcx> {
fn tcx(&self) -> &TyCtxt<'tcx> {
impl<'cx, 'gcx, 'tcx> ty::fold::TypeFolder<'gcx, 'tcx> for Generalizer<'cx, 'gcx, 'tcx> {
fn tcx<'a>(&'a self) -> TyCtxt<'a, 'gcx, 'tcx> {
self.infcx.tcx
}

Expand Down
Loading

0 comments on commit c7ab884

Please sign in to comment.