Skip to content

Commit

Permalink
Auto merge of #44501 - nikomatsakis:issue-44137-non-query-data-in-tcx…
Browse files Browse the repository at this point in the history
…, r=eddyb

remove or encapsulate the remaining non-query data in tcx

I wound up removing the existing cache around inhabitedness since it didn't seem to be adding much value. I reworked const rvalue promotion, but not that much (i.e., I did not split the computation into bits, as @eddyb had tossed out as a suggestion). But it's now demand driven, at least.

cc @michaelwoerister -- see the `forbid_reads` change in last commit

r? @eddyb -- since the trickiest of this PR is the work on const rvalue promotion

cc #44137
  • Loading branch information
bors committed Oct 18, 2017
2 parents f6d7514 + 7715f97 commit 7a4f394
Show file tree
Hide file tree
Showing 25 changed files with 438 additions and 241 deletions.
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 @@ -554,6 +554,7 @@ define_dep_nodes!( <'tcx>
[] LookupDeprecationEntry(DefId),
[] ItemBodyNestedBodies(DefId),
[] ConstIsRvaluePromotableToStatic(DefId),
[] RvaluePromotableMap(DefId),
[] ImplParent(DefId),
[] TraitOfItem(DefId),
[] IsExportedSymbol(DefId),
Expand Down Expand Up @@ -609,6 +610,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 @@ -869,8 +896,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 @@ -885,7 +913,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

0 comments on commit 7a4f394

Please sign in to comment.