Skip to content

Commit 7a4f394

Browse files
committed
Auto merge of #44501 - nikomatsakis:issue-44137-non-query-data-in-tcx, 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
2 parents f6d7514 + 7715f97 commit 7a4f394

File tree

25 files changed

+438
-241
lines changed

25 files changed

+438
-241
lines changed

CONTRIBUTING.md

+4-2
Original file line numberDiff line numberDiff line change
@@ -360,8 +360,10 @@ git add path/to/submodule
360360

361361
outside the submodule.
362362

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

366368
## Writing Documentation
367369
[writing-documentation]: #writing-documentation

src/librustc/dep_graph/dep_node.rs

+2
Original file line numberDiff line numberDiff line change
@@ -554,6 +554,7 @@ define_dep_nodes!( <'tcx>
554554
[] LookupDeprecationEntry(DefId),
555555
[] ItemBodyNestedBodies(DefId),
556556
[] ConstIsRvaluePromotableToStatic(DefId),
557+
[] RvaluePromotableMap(DefId),
557558
[] ImplParent(DefId),
558559
[] TraitOfItem(DefId),
559560
[] IsExportedSymbol(DefId),
@@ -609,6 +610,7 @@ define_dep_nodes!( <'tcx>
609610
[] PostorderCnums,
610611
[] HasCloneClosures(CrateNum),
611612
[] HasCopyClosures(CrateNum),
613+
[] EraseRegionsTy { ty: Ty<'tcx> },
612614

613615
[] Freevars(DefId),
614616
[] MaybeUnusedTraitImport(DefId),

src/librustc/lib.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@
6060
#![cfg_attr(stage0, feature(const_fn))]
6161
#![cfg_attr(not(stage0), feature(const_atomic_bool_new))]
6262

63-
#![recursion_limit="256"]
63+
#![recursion_limit="512"]
6464

6565
extern crate arena;
6666
#[macro_use] extern crate bitflags;

src/librustc/middle/expr_use_visitor.rs

+19-3
Original file line numberDiff line numberDiff line change
@@ -27,10 +27,11 @@ use middle::region;
2727
use ty::{self, TyCtxt, adjustment};
2828

2929
use hir::{self, PatKind};
30-
30+
use std::rc::Rc;
3131
use syntax::ast;
3232
use syntax::ptr::P;
3333
use syntax_pos::Span;
34+
use util::nodemap::ItemLocalMap;
3435

3536
///////////////////////////////////////////////////////////////////////////
3637
// The Delegate trait
@@ -262,15 +263,30 @@ macro_rules! return_if_err {
262263
}
263264

264265
impl<'a, 'tcx> ExprUseVisitor<'a, 'tcx, 'tcx> {
266+
/// Creates the ExprUseVisitor, configuring it with the various options provided:
267+
///
268+
/// - `delegate` -- who receives the callbacks
269+
/// - `param_env` --- parameter environment for trait lookups (esp. pertaining to `Copy`)
270+
/// - `region_scope_tree` --- region scope tree for the code being analyzed
271+
/// - `tables` --- typeck results for the code being analyzed
272+
/// - `rvalue_promotable_map` --- if you care about rvalue promotion, then provide
273+
/// the map here (it can be computed with `tcx.rvalue_promotable_map(def_id)`).
274+
/// `None` means that rvalues will be given more conservative lifetimes.
275+
///
276+
/// See also `with_infer`, which is used *during* typeck.
265277
pub fn new(delegate: &'a mut (Delegate<'tcx>+'a),
266278
tcx: TyCtxt<'a, 'tcx, 'tcx>,
267279
param_env: ty::ParamEnv<'tcx>,
268280
region_scope_tree: &'a region::ScopeTree,
269-
tables: &'a ty::TypeckTables<'tcx>)
281+
tables: &'a ty::TypeckTables<'tcx>,
282+
rvalue_promotable_map: Option<Rc<ItemLocalMap<bool>>>)
270283
-> Self
271284
{
272285
ExprUseVisitor {
273-
mc: mc::MemCategorizationContext::new(tcx, region_scope_tree, tables),
286+
mc: mc::MemCategorizationContext::new(tcx,
287+
region_scope_tree,
288+
tables,
289+
rvalue_promotable_map),
274290
delegate,
275291
param_env,
276292
}

src/librustc/middle/mem_categorization.rs

+34-6
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,7 @@ use syntax_pos::Span;
8686

8787
use std::fmt;
8888
use std::rc::Rc;
89+
use util::nodemap::ItemLocalMap;
8990

9091
#[derive(Clone, PartialEq)]
9192
pub enum Categorization<'tcx> {
@@ -285,6 +286,7 @@ pub struct MemCategorizationContext<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
285286
pub tcx: TyCtxt<'a, 'gcx, 'tcx>,
286287
pub region_scope_tree: &'a region::ScopeTree,
287288
pub tables: &'a ty::TypeckTables<'tcx>,
289+
rvalue_promotable_map: Option<Rc<ItemLocalMap<bool>>>,
288290
infcx: Option<&'a InferCtxt<'a, 'gcx, 'tcx>>,
289291
}
290292

@@ -392,21 +394,46 @@ impl MutabilityCategory {
392394
impl<'a, 'tcx> MemCategorizationContext<'a, 'tcx, 'tcx> {
393395
pub fn new(tcx: TyCtxt<'a, 'tcx, 'tcx>,
394396
region_scope_tree: &'a region::ScopeTree,
395-
tables: &'a ty::TypeckTables<'tcx>)
397+
tables: &'a ty::TypeckTables<'tcx>,
398+
rvalue_promotable_map: Option<Rc<ItemLocalMap<bool>>>)
396399
-> MemCategorizationContext<'a, 'tcx, 'tcx> {
397-
MemCategorizationContext { tcx, region_scope_tree, tables, infcx: None }
400+
MemCategorizationContext {
401+
tcx,
402+
region_scope_tree,
403+
tables,
404+
rvalue_promotable_map,
405+
infcx: None
406+
}
398407
}
399408
}
400409

401410
impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> {
411+
/// Creates a `MemCategorizationContext` during type inference.
412+
/// This is used during upvar analysis and a few other places.
413+
/// Because the typeck tables are not yet complete, the results
414+
/// from the analysis must be used with caution:
415+
///
416+
/// - rvalue promotions are not known, so the lifetimes of
417+
/// temporaries may be overly conservative;
418+
/// - similarly, as the results of upvar analysis are not yet
419+
/// known, the results around upvar accesses may be incorrect.
402420
pub fn with_infer(infcx: &'a InferCtxt<'a, 'gcx, 'tcx>,
403421
region_scope_tree: &'a region::ScopeTree,
404422
tables: &'a ty::TypeckTables<'tcx>)
405423
-> MemCategorizationContext<'a, 'gcx, 'tcx> {
424+
let tcx = infcx.tcx;
425+
426+
// Subtle: we can't do rvalue promotion analysis until the
427+
// typeck phase is complete, which means that you can't trust
428+
// the rvalue lifetimes that result, but that's ok, since we
429+
// don't need to know those during type inference.
430+
let rvalue_promotable_map = None;
431+
406432
MemCategorizationContext {
407-
tcx: infcx.tcx,
433+
tcx,
408434
region_scope_tree,
409435
tables,
436+
rvalue_promotable_map,
410437
infcx: Some(infcx),
411438
}
412439
}
@@ -869,8 +896,9 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> {
869896
span: Span,
870897
expr_ty: Ty<'tcx>)
871898
-> cmt<'tcx> {
872-
let promotable = self.tcx.rvalue_promotable_to_static.borrow().get(&id).cloned()
873-
.unwrap_or(false);
899+
let hir_id = self.tcx.hir.node_to_hir_id(id);
900+
let promotable = self.rvalue_promotable_map.as_ref().map(|m| m[&hir_id.local_id])
901+
.unwrap_or(false);
874902

875903
// Always promote `[T; 0]` (even when e.g. borrowed mutably).
876904
let promotable = match expr_ty.sty {
@@ -885,7 +913,7 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> {
885913
let re = if promotable {
886914
self.tcx.types.re_static
887915
} else {
888-
self.temporary_scope(self.tcx.hir.node_to_hir_id(id).local_id)
916+
self.temporary_scope(hir_id.local_id)
889917
};
890918
let ret = self.cat_rvalue(id, span, re, expr_ty);
891919
debug!("cat_rvalue_node ret {:?}", ret);

src/librustc/ty/context.rs

-12
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,6 @@ use ty::RegionKind;
4343
use ty::{TyVar, TyVid, IntVar, IntVid, FloatVar, FloatVid};
4444
use ty::TypeVariants::*;
4545
use ty::layout::{Layout, TargetDataLayout};
46-
use ty::inhabitedness::DefIdForest;
4746
use ty::maps;
4847
use ty::steal::Steal;
4948
use ty::BindingMode;
@@ -893,11 +892,6 @@ pub struct GlobalCtxt<'tcx> {
893892
// Internal cache for metadata decoding. No need to track deps on this.
894893
pub rcache: RefCell<FxHashMap<ty::CReaderCacheKey, Ty<'tcx>>>,
895894

896-
// FIXME dep tracking -- should be harmless enough
897-
pub normalized_cache: RefCell<FxHashMap<Ty<'tcx>, Ty<'tcx>>>,
898-
899-
pub inhabitedness_cache: RefCell<FxHashMap<Ty<'tcx>, DefIdForest>>,
900-
901895
/// Caches the results of trait selection. This cache is used
902896
/// for things that do not have to do with the parameters in scope.
903897
pub selection_cache: traits::SelectionCache<'tcx>,
@@ -907,9 +901,6 @@ pub struct GlobalCtxt<'tcx> {
907901
/// Merge this with `selection_cache`?
908902
pub evaluation_cache: traits::EvaluationCache<'tcx>,
909903

910-
/// Maps Expr NodeId's to `true` iff `&expr` can have 'static lifetime.
911-
pub rvalue_promotable_to_static: RefCell<NodeMap<bool>>,
912-
913904
/// The definite name of the current crate after taking into account
914905
/// attributes, commandline parameters, etc.
915906
pub crate_name: Symbol,
@@ -1178,11 +1169,8 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
11781169
maps: maps::Maps::new(providers),
11791170
mir_passes,
11801171
rcache: RefCell::new(FxHashMap()),
1181-
normalized_cache: RefCell::new(FxHashMap()),
1182-
inhabitedness_cache: RefCell::new(FxHashMap()),
11831172
selection_cache: traits::SelectionCache::new(),
11841173
evaluation_cache: traits::EvaluationCache::new(),
1185-
rvalue_promotable_to_static: RefCell::new(NodeMap()),
11861174
crate_name: Symbol::intern(crate_name),
11871175
data_layout,
11881176
layout_interner: RefCell::new(FxHashSet()),

src/librustc/ty/erase_regions.rs

+79
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
use ty::{self, Ty, TyCtxt};
12+
use ty::fold::{TypeFolder, TypeFoldable};
13+
14+
pub(super) fn provide(providers: &mut ty::maps::Providers) {
15+
*providers = ty::maps::Providers {
16+
erase_regions_ty,
17+
..*providers
18+
};
19+
}
20+
21+
fn erase_regions_ty<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, ty: Ty<'tcx>) -> Ty<'tcx> {
22+
// NB: use `super_fold_with` here. If we used `fold_with`, it
23+
// could invoke the `erase_regions_ty` query recursively.
24+
ty.super_fold_with(&mut RegionEraserVisitor { tcx })
25+
}
26+
27+
impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
28+
/// Returns an equivalent value with all free regions removed (note
29+
/// that late-bound regions remain, because they are important for
30+
/// subtyping, but they are anonymized and normalized as well)..
31+
pub fn erase_regions<T>(self, value: &T) -> T
32+
where T : TypeFoldable<'tcx>
33+
{
34+
let value1 = value.fold_with(&mut RegionEraserVisitor { tcx: self });
35+
debug!("erase_regions({:?}) = {:?}", value, value1);
36+
value1
37+
}
38+
}
39+
40+
struct RegionEraserVisitor<'a, 'gcx: 'tcx, 'tcx: 'a> {
41+
tcx: TyCtxt<'a, 'gcx, 'tcx>,
42+
}
43+
44+
impl<'a, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for RegionEraserVisitor<'a, 'gcx, 'tcx> {
45+
fn tcx<'b>(&'b self) -> TyCtxt<'b, 'gcx, 'tcx> {
46+
self.tcx
47+
}
48+
49+
fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
50+
if let Some(ty_lifted) = self.tcx.lift_to_global(&ty) {
51+
self.tcx.erase_regions_ty(ty_lifted)
52+
} else {
53+
ty.super_fold_with(self)
54+
}
55+
}
56+
57+
fn fold_binder<T>(&mut self, t: &ty::Binder<T>) -> ty::Binder<T>
58+
where T : TypeFoldable<'tcx>
59+
{
60+
let u = self.tcx.anonymize_late_bound_regions(t);
61+
u.super_fold_with(self)
62+
}
63+
64+
fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> {
65+
// because late-bound regions affect subtyping, we can't
66+
// erase the bound/free distinction, but we can replace
67+
// all free regions with 'erased.
68+
//
69+
// Note that we *CAN* replace early-bound regions -- the
70+
// type system never "sees" those, they get substituted
71+
// away. In trans, they will always be erased to 'erased
72+
// whenever a substitution occurs.
73+
match *r {
74+
ty::ReLateBound(..) => r,
75+
_ => self.tcx.types.re_erased
76+
}
77+
}
78+
}
79+

src/librustc/ty/fold.rs

-61
Original file line numberDiff line numberDiff line change
@@ -444,67 +444,6 @@ impl<'a, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for RegionReplacer<'a, 'gcx, 'tcx> {
444444
}
445445
}
446446

447-
///////////////////////////////////////////////////////////////////////////
448-
// Region eraser
449-
450-
impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
451-
/// Returns an equivalent value with all free regions removed (note
452-
/// that late-bound regions remain, because they are important for
453-
/// subtyping, but they are anonymized and normalized as well)..
454-
pub fn erase_regions<T>(self, value: &T) -> T
455-
where T : TypeFoldable<'tcx>
456-
{
457-
let value1 = value.fold_with(&mut RegionEraser(self));
458-
debug!("erase_regions({:?}) = {:?}",
459-
value, value1);
460-
return value1;
461-
462-
struct RegionEraser<'a, 'gcx: 'a+'tcx, 'tcx: 'a>(TyCtxt<'a, 'gcx, 'tcx>);
463-
464-
impl<'a, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for RegionEraser<'a, 'gcx, 'tcx> {
465-
fn tcx<'b>(&'b self) -> TyCtxt<'b, 'gcx, 'tcx> { self.0 }
466-
467-
fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
468-
if let Some(u) = self.tcx().normalized_cache.borrow().get(&ty).cloned() {
469-
return u;
470-
}
471-
472-
// FIXME(eddyb) should local contexts have a cache too?
473-
if let Some(ty_lifted) = self.tcx().lift_to_global(&ty) {
474-
let tcx = self.tcx().global_tcx();
475-
let t_norm = ty_lifted.super_fold_with(&mut RegionEraser(tcx));
476-
tcx.normalized_cache.borrow_mut().insert(ty_lifted, t_norm);
477-
t_norm
478-
} else {
479-
ty.super_fold_with(self)
480-
}
481-
}
482-
483-
fn fold_binder<T>(&mut self, t: &ty::Binder<T>) -> ty::Binder<T>
484-
where T : TypeFoldable<'tcx>
485-
{
486-
let u = self.tcx().anonymize_late_bound_regions(t);
487-
u.super_fold_with(self)
488-
}
489-
490-
fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> {
491-
// because late-bound regions affect subtyping, we can't
492-
// erase the bound/free distinction, but we can replace
493-
// all free regions with 'erased.
494-
//
495-
// Note that we *CAN* replace early-bound regions -- the
496-
// type system never "sees" those, they get substituted
497-
// away. In trans, they will always be erased to 'erased
498-
// whenever a substitution occurs.
499-
match *r {
500-
ty::ReLateBound(..) => r,
501-
_ => self.tcx().types.re_erased
502-
}
503-
}
504-
}
505-
}
506-
}
507-
508447
///////////////////////////////////////////////////////////////////////////
509448
// Region shifter
510449
//

0 commit comments

Comments
 (0)