Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

remove or encapsulate the remaining non-query data in tcx #44501

Merged
merged 10 commits into from
Oct 18, 2017
6 changes: 4 additions & 2 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -360,8 +360,10 @@ git add path/to/submodule

outside the submodule.

It can also be more convenient during development to set `submodules = false`
in the `config.toml` to prevent `x.py` from resetting to the original branch.
In order to prepare your PR, you can run the build locally by doing
`./x.py build src/tools/TOOL`. If you will be editing the sources
there, you may wish to set `submodules = false` in the `config.toml`
to prevent `x.py` from resetting to the original branch.

## Writing Documentation
[writing-documentation]: #writing-documentation
Expand Down
2 changes: 2 additions & 0 deletions src/librustc/dep_graph/dep_node.rs
Original file line number Diff line number Diff line change
Expand Up @@ -553,6 +553,7 @@ define_dep_nodes!( <'tcx>
[] LookupDeprecationEntry(DefId),
[] ItemBodyNestedBodies(DefId),
[] ConstIsRvaluePromotableToStatic(DefId),
[] RvaluePromotableMap(DefId),
[] ImplParent(DefId),
[] TraitOfItem(DefId),
[] IsExportedSymbol(DefId),
Expand Down Expand Up @@ -608,6 +609,7 @@ define_dep_nodes!( <'tcx>
[] PostorderCnums,
[] HasCloneClosures(CrateNum),
[] HasCopyClosures(CrateNum),
[] EraseRegionsTy { ty: Ty<'tcx> },

[] Freevars(DefId),
[] MaybeUnusedTraitImport(DefId),
Expand Down
2 changes: 1 addition & 1 deletion src/librustc/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@
#![cfg_attr(stage0, feature(const_fn))]
#![cfg_attr(not(stage0), feature(const_atomic_bool_new))]

#![recursion_limit="256"]
#![recursion_limit="512"]

extern crate arena;
#[macro_use] extern crate bitflags;
Expand Down
22 changes: 19 additions & 3 deletions src/librustc/middle/expr_use_visitor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,10 +27,11 @@ use middle::region;
use ty::{self, TyCtxt, adjustment};

use hir::{self, PatKind};

use std::rc::Rc;
use syntax::ast;
use syntax::ptr::P;
use syntax_pos::Span;
use util::nodemap::ItemLocalMap;

///////////////////////////////////////////////////////////////////////////
// The Delegate trait
Expand Down Expand Up @@ -262,15 +263,30 @@ macro_rules! return_if_err {
}

impl<'a, 'tcx> ExprUseVisitor<'a, 'tcx, 'tcx> {
/// Creates the ExprUseVisitor, configuring it with the various options provided:
///
/// - `delegate` -- who receives the callbacks
/// - `param_env` --- parameter environment for trait lookups (esp. pertaining to `Copy`)
/// - `region_scope_tree` --- region scope tree for the code being analyzed
/// - `tables` --- typeck results for the code being analyzed
/// - `rvalue_promotable_map` --- if you care about rvalue promotion, then provide
/// the map here (it can be computed with `tcx.rvalue_promotable_map(def_id)`).
/// `None` means that rvalues will be given more conservative lifetimes.
///
/// See also `with_infer`, which is used *during* typeck.
pub fn new(delegate: &'a mut (Delegate<'tcx>+'a),
tcx: TyCtxt<'a, 'tcx, 'tcx>,
param_env: ty::ParamEnv<'tcx>,
region_scope_tree: &'a region::ScopeTree,
tables: &'a ty::TypeckTables<'tcx>)
tables: &'a ty::TypeckTables<'tcx>,
rvalue_promotable_map: Option<Rc<ItemLocalMap<bool>>>)
-> Self
{
ExprUseVisitor {
mc: mc::MemCategorizationContext::new(tcx, region_scope_tree, tables),
mc: mc::MemCategorizationContext::new(tcx,
region_scope_tree,
tables,
rvalue_promotable_map),
delegate,
param_env,
}
Expand Down
40 changes: 34 additions & 6 deletions src/librustc/middle/mem_categorization.rs
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,7 @@ use syntax_pos::Span;

use std::fmt;
use std::rc::Rc;
use util::nodemap::ItemLocalMap;

#[derive(Clone, PartialEq)]
pub enum Categorization<'tcx> {
Expand Down Expand Up @@ -285,6 +286,7 @@ pub struct MemCategorizationContext<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
pub tcx: TyCtxt<'a, 'gcx, 'tcx>,
pub region_scope_tree: &'a region::ScopeTree,
pub tables: &'a ty::TypeckTables<'tcx>,
rvalue_promotable_map: Option<Rc<ItemLocalMap<bool>>>,
infcx: Option<&'a InferCtxt<'a, 'gcx, 'tcx>>,
}

Expand Down Expand Up @@ -392,21 +394,46 @@ impl MutabilityCategory {
impl<'a, 'tcx> MemCategorizationContext<'a, 'tcx, 'tcx> {
pub fn new(tcx: TyCtxt<'a, 'tcx, 'tcx>,
region_scope_tree: &'a region::ScopeTree,
tables: &'a ty::TypeckTables<'tcx>)
tables: &'a ty::TypeckTables<'tcx>,
rvalue_promotable_map: Option<Rc<ItemLocalMap<bool>>>)
-> MemCategorizationContext<'a, 'tcx, 'tcx> {
MemCategorizationContext { tcx, region_scope_tree, tables, infcx: None }
MemCategorizationContext {
tcx,
region_scope_tree,
tables,
rvalue_promotable_map,
infcx: None
}
}
}

impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> {
/// Creates a `MemCategorizationContext` during type inference.
/// This is used during upvar analysis and a few other places.
/// Because the typeck tables are not yet complete, the results
/// from the analysis must be used with caution:
///
/// - rvalue promotions are not known, so the lifetimes of
/// temporaries may be overly conservative;
/// - similarly, as the results of upvar analysis are not yet
/// known, the results around upvar accesses may be incorrect.
pub fn with_infer(infcx: &'a InferCtxt<'a, 'gcx, 'tcx>,
region_scope_tree: &'a region::ScopeTree,
tables: &'a ty::TypeckTables<'tcx>)
-> MemCategorizationContext<'a, 'gcx, 'tcx> {
let tcx = infcx.tcx;

// Subtle: we can't do rvalue promotion analysis until the
// typeck phase is complete, which means that you can't trust
// the rvalue lifetimes that result, but that's ok, since we
// don't need to know those during type inference.
let rvalue_promotable_map = None;

MemCategorizationContext {
tcx: infcx.tcx,
tcx,
region_scope_tree,
tables,
rvalue_promotable_map,
infcx: Some(infcx),
}
}
Expand Down Expand Up @@ -871,8 +898,9 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> {
span: Span,
expr_ty: Ty<'tcx>)
-> cmt<'tcx> {
let promotable = self.tcx.rvalue_promotable_to_static.borrow().get(&id).cloned()
.unwrap_or(false);
let hir_id = self.tcx.hir.node_to_hir_id(id);
let promotable = self.rvalue_promotable_map.as_ref().map(|m| m[&hir_id.local_id])
.unwrap_or(false);

// Always promote `[T; 0]` (even when e.g. borrowed mutably).
let promotable = match expr_ty.sty {
Expand All @@ -887,7 +915,7 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> {
let re = if promotable {
self.tcx.types.re_static
} else {
self.temporary_scope(self.tcx.hir.node_to_hir_id(id).local_id)
self.temporary_scope(hir_id.local_id)
};
let ret = self.cat_rvalue(id, span, re, expr_ty);
debug!("cat_rvalue_node ret {:?}", ret);
Expand Down
12 changes: 0 additions & 12 deletions src/librustc/ty/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,6 @@ use ty::RegionKind;
use ty::{TyVar, TyVid, IntVar, IntVid, FloatVar, FloatVid};
use ty::TypeVariants::*;
use ty::layout::{Layout, TargetDataLayout};
use ty::inhabitedness::DefIdForest;
use ty::maps;
use ty::steal::Steal;
use ty::BindingMode;
Expand Down Expand Up @@ -893,11 +892,6 @@ pub struct GlobalCtxt<'tcx> {
// Internal cache for metadata decoding. No need to track deps on this.
pub rcache: RefCell<FxHashMap<ty::CReaderCacheKey, Ty<'tcx>>>,

// FIXME dep tracking -- should be harmless enough
pub normalized_cache: RefCell<FxHashMap<Ty<'tcx>, Ty<'tcx>>>,

pub inhabitedness_cache: RefCell<FxHashMap<Ty<'tcx>, DefIdForest>>,

/// Caches the results of trait selection. This cache is used
/// for things that do not have to do with the parameters in scope.
pub selection_cache: traits::SelectionCache<'tcx>,
Expand All @@ -907,9 +901,6 @@ pub struct GlobalCtxt<'tcx> {
/// Merge this with `selection_cache`?
pub evaluation_cache: traits::EvaluationCache<'tcx>,

/// Maps Expr NodeId's to `true` iff `&expr` can have 'static lifetime.
pub rvalue_promotable_to_static: RefCell<NodeMap<bool>>,

/// The definite name of the current crate after taking into account
/// attributes, commandline parameters, etc.
pub crate_name: Symbol,
Expand Down Expand Up @@ -1178,11 +1169,8 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
maps: maps::Maps::new(providers),
mir_passes,
rcache: RefCell::new(FxHashMap()),
normalized_cache: RefCell::new(FxHashMap()),
inhabitedness_cache: RefCell::new(FxHashMap()),
selection_cache: traits::SelectionCache::new(),
evaluation_cache: traits::EvaluationCache::new(),
rvalue_promotable_to_static: RefCell::new(NodeMap()),
crate_name: Symbol::intern(crate_name),
data_layout,
layout_interner: RefCell::new(FxHashSet()),
Expand Down
79 changes: 79 additions & 0 deletions src/librustc/ty/erase_regions.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

use ty::{self, Ty, TyCtxt};
use ty::fold::{TypeFolder, TypeFoldable};

pub(super) fn provide(providers: &mut ty::maps::Providers) {
*providers = ty::maps::Providers {
erase_regions_ty,
..*providers
};
}

fn erase_regions_ty<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, ty: Ty<'tcx>) -> Ty<'tcx> {
// NB: use `super_fold_with` here. If we used `fold_with`, it
// could invoke the `erase_regions_ty` query recursively.
ty.super_fold_with(&mut RegionEraserVisitor { tcx })
}

impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
/// Returns an equivalent value with all free regions removed (note
/// that late-bound regions remain, because they are important for
/// subtyping, but they are anonymized and normalized as well)..
pub fn erase_regions<T>(self, value: &T) -> T
where T : TypeFoldable<'tcx>
{
let value1 = value.fold_with(&mut RegionEraserVisitor { tcx: self });
debug!("erase_regions({:?}) = {:?}", value, value1);
value1
}
}

struct RegionEraserVisitor<'a, 'gcx: 'tcx, 'tcx: 'a> {
tcx: TyCtxt<'a, 'gcx, 'tcx>,
}

impl<'a, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for RegionEraserVisitor<'a, 'gcx, 'tcx> {
fn tcx<'b>(&'b self) -> TyCtxt<'b, 'gcx, 'tcx> {
self.tcx
}

fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
if let Some(ty_lifted) = self.tcx.lift_to_global(&ty) {
self.tcx.erase_regions_ty(ty_lifted)
} else {
ty.super_fold_with(self)
}
}

fn fold_binder<T>(&mut self, t: &ty::Binder<T>) -> ty::Binder<T>
where T : TypeFoldable<'tcx>
{
let u = self.tcx.anonymize_late_bound_regions(t);
u.super_fold_with(self)
}

fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> {
// because late-bound regions affect subtyping, we can't
// erase the bound/free distinction, but we can replace
// all free regions with 'erased.
//
// Note that we *CAN* replace early-bound regions -- the
// type system never "sees" those, they get substituted
// away. In trans, they will always be erased to 'erased
// whenever a substitution occurs.
match *r {
ty::ReLateBound(..) => r,
_ => self.tcx.types.re_erased
}
}
}

61 changes: 0 additions & 61 deletions src/librustc/ty/fold.rs
Original file line number Diff line number Diff line change
Expand Up @@ -444,67 +444,6 @@ impl<'a, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for RegionReplacer<'a, 'gcx, 'tcx> {
}
}

///////////////////////////////////////////////////////////////////////////
// Region eraser

impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
/// Returns an equivalent value with all free regions removed (note
/// that late-bound regions remain, because they are important for
/// subtyping, but they are anonymized and normalized as well)..
pub fn erase_regions<T>(self, value: &T) -> T
where T : TypeFoldable<'tcx>
{
let value1 = value.fold_with(&mut RegionEraser(self));
debug!("erase_regions({:?}) = {:?}",
value, value1);
return value1;

struct RegionEraser<'a, 'gcx: 'a+'tcx, 'tcx: 'a>(TyCtxt<'a, 'gcx, 'tcx>);

impl<'a, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for RegionEraser<'a, 'gcx, 'tcx> {
fn tcx<'b>(&'b self) -> TyCtxt<'b, 'gcx, 'tcx> { self.0 }

fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
if let Some(u) = self.tcx().normalized_cache.borrow().get(&ty).cloned() {
return u;
}

// FIXME(eddyb) should local contexts have a cache too?
if let Some(ty_lifted) = self.tcx().lift_to_global(&ty) {
let tcx = self.tcx().global_tcx();
let t_norm = ty_lifted.super_fold_with(&mut RegionEraser(tcx));
tcx.normalized_cache.borrow_mut().insert(ty_lifted, t_norm);
t_norm
} else {
ty.super_fold_with(self)
}
}

fn fold_binder<T>(&mut self, t: &ty::Binder<T>) -> ty::Binder<T>
where T : TypeFoldable<'tcx>
{
let u = self.tcx().anonymize_late_bound_regions(t);
u.super_fold_with(self)
}

fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> {
// because late-bound regions affect subtyping, we can't
// erase the bound/free distinction, but we can replace
// all free regions with 'erased.
//
// Note that we *CAN* replace early-bound regions -- the
// type system never "sees" those, they get substituted
// away. In trans, they will always be erased to 'erased
// whenever a substitution occurs.
match *r {
ty::ReLateBound(..) => r,
_ => self.tcx().types.re_erased
}
}
}
}
}

///////////////////////////////////////////////////////////////////////////
// Region shifter
//
Expand Down
Loading