Skip to content

Commit 0f568e2

Browse files
committed
convert constant promotion into a query
1 parent 807e157 commit 0f568e2

File tree

13 files changed

+165
-54
lines changed

13 files changed

+165
-54
lines changed

src/librustc/dep_graph/dep_node.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -553,6 +553,7 @@ define_dep_nodes!( <'tcx>
553553
[] LookupDeprecationEntry(DefId),
554554
[] ItemBodyNestedBodies(DefId),
555555
[] ConstIsRvaluePromotableToStatic(DefId),
556+
[] RvaluePromotableMap(DefId),
556557
[] ImplParent(DefId),
557558
[] TraitOfItem(DefId),
558559
[] IsExportedSymbol(DefId),

src/librustc/middle/expr_use_visitor.rs

Lines changed: 19 additions & 3 deletions
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

Lines changed: 34 additions & 6 deletions
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 false 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
}
@@ -871,8 +898,9 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> {
871898
span: Span,
872899
expr_ty: Ty<'tcx>)
873900
-> cmt<'tcx> {
874-
let promotable = self.tcx.rvalue_promotable_to_static.borrow().get(&id).cloned()
875-
.unwrap_or(false);
901+
let hir_id = self.tcx.hir.node_to_hir_id(id);
902+
let promotable = self.rvalue_promotable_map.as_ref().map(|m| m[&hir_id.local_id])
903+
.unwrap_or(false);
876904

877905
// Always promote `[T; 0]` (even when e.g. borrowed mutably).
878906
let promotable = match expr_ty.sty {
@@ -887,7 +915,7 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> {
887915
let re = if promotable {
888916
self.tcx.types.re_static
889917
} else {
890-
self.temporary_scope(self.tcx.hir.node_to_hir_id(id).local_id)
918+
self.temporary_scope(hir_id.local_id)
891919
};
892920
let ret = self.cat_rvalue(id, span, re, expr_ty);
893921
debug!("cat_rvalue_node ret {:?}", ret);

src/librustc/ty/context.rs

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -904,9 +904,6 @@ pub struct GlobalCtxt<'tcx> {
904904
/// Merge this with `selection_cache`?
905905
pub evaluation_cache: traits::EvaluationCache<'tcx>,
906906

907-
/// Maps Expr NodeId's to `true` iff `&expr` can have 'static lifetime.
908-
pub rvalue_promotable_to_static: RefCell<NodeMap<bool>>,
909-
910907
/// The definite name of the current crate after taking into account
911908
/// attributes, commandline parameters, etc.
912909
pub crate_name: Symbol,
@@ -1178,7 +1175,6 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
11781175
normalized_cache: RefCell::new(FxHashMap()),
11791176
selection_cache: traits::SelectionCache::new(),
11801177
evaluation_cache: traits::EvaluationCache::new(),
1181-
rvalue_promotable_to_static: RefCell::new(NodeMap()),
11821178
crate_name: Symbol::intern(crate_name),
11831179
data_layout,
11841180
layout_interner: RefCell::new(FxHashSet()),

src/librustc/ty/maps/config.rs

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,12 @@ pub(super) trait QueryDescription: QueryConfig {
2929

3030
impl<M: QueryConfig<Key=DefId>> QueryDescription for M {
3131
default fn describe(tcx: TyCtxt, def_id: DefId) -> String {
32-
format!("processing `{}`", tcx.item_path_str(def_id))
32+
if !tcx.sess.verbose() {
33+
format!("processing `{}`", tcx.item_path_str(def_id))
34+
} else {
35+
let name = unsafe { ::std::intrinsics::type_name::<M>() };
36+
format!("processing `{}` applied to `{:?}`", name, def_id)
37+
}
3338
}
3439
}
3540

@@ -214,6 +219,13 @@ impl<'tcx> QueryDescription for queries::const_is_rvalue_promotable_to_static<'t
214219
}
215220
}
216221

222+
impl<'tcx> QueryDescription for queries::rvalue_promotable_map<'tcx> {
223+
fn describe(tcx: TyCtxt, def_id: DefId) -> String {
224+
format!("checking which parts of `{}` are promotable to static",
225+
tcx.item_path_str(def_id))
226+
}
227+
}
228+
217229
impl<'tcx> QueryDescription for queries::is_mir_available<'tcx> {
218230
fn describe(tcx: TyCtxt, def_id: DefId) -> String {
219231
format!("checking if item is mir available: `{}`",

src/librustc/ty/maps/mod.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ use ty::{self, CrateInherentImpls, Ty, TyCtxt};
3737
use ty::layout::{Layout, LayoutError};
3838
use ty::steal::Steal;
3939
use ty::subst::Substs;
40-
use util::nodemap::{DefIdSet, DefIdMap};
40+
use util::nodemap::{DefIdSet, DefIdMap, ItemLocalMap};
4141
use util::common::{profq_msg, ProfileQueriesMsg};
4242

4343
use rustc_data_structures::indexed_set::IdxSetBuf;
@@ -228,6 +228,7 @@ define_maps! { <'tcx>
228228
[] fn is_exported_symbol: IsExportedSymbol(DefId) -> bool,
229229
[] fn item_body_nested_bodies: ItemBodyNestedBodies(DefId) -> ExternBodyNestedBodies,
230230
[] fn const_is_rvalue_promotable_to_static: ConstIsRvaluePromotableToStatic(DefId) -> bool,
231+
[] fn rvalue_promotable_map: RvaluePromotableMap(DefId) -> Rc<ItemLocalMap<bool>>,
231232
[] fn is_mir_available: IsMirAvailable(DefId) -> bool,
232233
[] fn vtable_methods: vtable_methods_node(ty::PolyTraitRef<'tcx>)
233234
-> Rc<Vec<Option<(DefId, &'tcx Substs<'tcx>)>>>,

src/librustc_borrowck/borrowck/check_loans.rs

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -206,7 +206,13 @@ pub fn check_loans<'a, 'b, 'c, 'tcx>(bccx: &BorrowckCtxt<'a, 'tcx>,
206206
all_loans,
207207
param_env,
208208
};
209-
euv::ExprUseVisitor::new(&mut clcx, bccx.tcx, param_env, &bccx.region_scope_tree, bccx.tables)
209+
let rvalue_promotable_map = bccx.tcx.rvalue_promotable_map(def_id);
210+
euv::ExprUseVisitor::new(&mut clcx,
211+
bccx.tcx,
212+
param_env,
213+
&bccx.region_scope_tree,
214+
bccx.tables,
215+
Some(rvalue_promotable_map))
210216
.consume_body(body);
211217
}
212218

src/librustc_borrowck/borrowck/gather_loans/mod.rs

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,13 @@ pub fn gather_loans_in_fn<'a, 'tcx>(bccx: &BorrowckCtxt<'a, 'tcx>,
4848
move_error_collector: move_error::MoveErrorCollector::new(),
4949
};
5050

51-
euv::ExprUseVisitor::new(&mut glcx, bccx.tcx, param_env, &bccx.region_scope_tree, bccx.tables)
51+
let rvalue_promotable_map = bccx.tcx.rvalue_promotable_map(def_id);
52+
euv::ExprUseVisitor::new(&mut glcx,
53+
bccx.tcx,
54+
param_env,
55+
&bccx.region_scope_tree,
56+
bccx.tables,
57+
Some(rvalue_promotable_map))
5258
.consume_body(bccx.body);
5359

5460
glcx.report_potential_errors();

src/librustc_const_eval/check_match.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -526,7 +526,7 @@ fn check_for_mutation_in_guard(cx: &MatchVisitor, guard: &hir::Expr) {
526526
let mut checker = MutationChecker {
527527
cx,
528528
};
529-
ExprUseVisitor::new(&mut checker, cx.tcx, cx.param_env, cx.region_scope_tree, cx.tables)
529+
ExprUseVisitor::new(&mut checker, cx.tcx, cx.param_env, cx.region_scope_tree, cx.tables, None)
530530
.walk_expr(guard);
531531
}
532532

src/librustc_driver/driver.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ use rustc_typeck as typeck;
3838
use rustc_privacy;
3939
use rustc_plugin::registry::Registry;
4040
use rustc_plugin as plugin;
41-
use rustc_passes::{ast_validation, no_asm, loops, consts, static_recursion, hir_stats};
41+
use rustc_passes::{self, ast_validation, no_asm, loops, consts, static_recursion, hir_stats};
4242
use rustc_const_eval::{self, check_match};
4343
use super::Compilation;
4444
use ::DefaultTransCrate;
@@ -973,6 +973,7 @@ pub fn phase_3_run_analysis_passes<'tcx, F, R>(sess: &'tcx Session,
973973
traits::provide(&mut local_providers);
974974
reachable::provide(&mut local_providers);
975975
rustc_const_eval::provide(&mut local_providers);
976+
rustc_passes::provide(&mut local_providers);
976977
middle::region::provide(&mut local_providers);
977978
cstore::provide_local(&mut local_providers);
978979
lint::provide(&mut local_providers);

src/librustc_metadata/astencode.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,8 @@ impl<'a, 'b, 'tcx> IsolatedEncoder<'a, 'b, 'tcx> {
5656
};
5757

5858
let lazy_body = self.lazy(body);
59-
let tables = self.tcx.body_tables(body_id);
59+
let body_owner_def_id = self.tcx.hir.body_owner_def_id(body_id);
60+
let tables = self.tcx.typeck_tables_of(body_owner_def_id);
6061
let lazy_tables = self.lazy(tables);
6162

6263
let mut visitor = NestedBodyCollector {
@@ -67,7 +68,7 @@ impl<'a, 'b, 'tcx> IsolatedEncoder<'a, 'b, 'tcx> {
6768
let lazy_nested_bodies = self.lazy_seq_ref_from_slice(&visitor.bodies_found);
6869

6970
let rvalue_promotable_to_static =
70-
self.tcx.rvalue_promotable_to_static.borrow()[&body.value.id];
71+
self.tcx.const_is_rvalue_promotable_to_static(body_owner_def_id);
7172

7273
self.lazy(&Ast {
7374
body: lazy_body,

0 commit comments

Comments
 (0)