Skip to content

Commit 1b7acb6

Browse files
committed
centralize the caching for is-copy, is-sized, and is-freeze
Use the trait-environment+type as the key. Note that these are only invoked on types that live for the entire compilation (no inference artifacts). We no longer need the various special-case bits and caches that were in place before.
1 parent 81734e0 commit 1b7acb6

File tree

22 files changed

+219
-272
lines changed

22 files changed

+219
-272
lines changed

src/librustc/dep_graph/dep_node.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,9 @@ pub enum DepNode<D: Clone + Debug> {
108108
SymbolName(D),
109109
SpecializationGraph(D),
110110
ObjectSafety(D),
111+
IsCopy(D),
112+
IsSized(D),
113+
IsFreeze(D),
111114

112115
// The set of impls for a given trait. Ultimately, it would be
113116
// nice to get more fine-grained here (e.g., to include a
@@ -233,6 +236,9 @@ impl<D: Clone + Debug> DepNode<D> {
233236
// they are always absolute.
234237
WorkProduct(ref id) => Some(WorkProduct(id.clone())),
235238

239+
IsCopy(ref d) => op(d).map(IsCopy),
240+
IsSized(ref d) => op(d).map(IsSized),
241+
IsFreeze(ref d) => op(d).map(IsFreeze),
236242
Hir(ref d) => op(d).map(Hir),
237243
HirBody(ref d) => op(d).map(HirBody),
238244
MetaData(ref d) => op(d).map(MetaData),

src/librustc/infer/mod.rs

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ use middle::lang_items;
2828
use mir::tcx::LvalueTy;
2929
use ty::subst::{Kind, Subst, Substs};
3030
use ty::{TyVid, IntVid, FloatVid};
31-
use ty::{self, Ty, TyCtxt};
31+
use ty::{self, ParameterEnvironment, Ty, TyCtxt};
3232
use ty::error::{ExpectedFound, TypeError, UnconstrainedNumeric};
3333
use ty::fold::{TypeFoldable, TypeFolder, TypeVisitor};
3434
use ty::relate::{Relate, RelateResult, TypeRelation};
@@ -526,9 +526,7 @@ impl<'a, 'gcx, 'tcx> InferCtxtBuilder<'a, 'gcx, 'tcx> {
526526
let tables = tables.map(InferTables::Interned).unwrap_or_else(|| {
527527
fresh_tables.as_ref().map_or(InferTables::Missing, InferTables::InProgress)
528528
});
529-
let param_env = param_env.take().unwrap_or_else(|| {
530-
global_tcx.empty_parameter_environment()
531-
});
529+
let param_env = param_env.take().unwrap_or_else(|| ParameterEnvironment::empty());
532530
global_tcx.enter_local(arena, |tcx| f(InferCtxt {
533531
tcx: tcx,
534532
tables: tables,
@@ -650,7 +648,7 @@ impl<'a, 'tcx> TyCtxt<'a, 'tcx, 'tcx> {
650648
}
651649

652650
pub fn normalize_associated_type_in_env<T>(
653-
self, value: &T, env: &'a ty::ParameterEnvironment<'tcx>
651+
self, value: &T, env: ty::ParameterEnvironment<'tcx>
654652
) -> T
655653
where T: TransNormalize<'tcx>
656654
{
@@ -662,7 +660,7 @@ impl<'a, 'tcx> TyCtxt<'a, 'tcx, 'tcx> {
662660
return value;
663661
}
664662

665-
self.infer_ctxt(env.clone(), Reveal::All).enter(|infcx| {
663+
self.infer_ctxt(env, Reveal::All).enter(|infcx| {
666664
value.trans_normalize(&infcx)
667665
})
668666
}
@@ -1674,8 +1672,8 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
16741672
self.tables.borrow().upvar_capture_map.get(&upvar_id).cloned()
16751673
}
16761674

1677-
pub fn param_env(&self) -> &ty::ParameterEnvironment<'gcx> {
1678-
&self.parameter_environment
1675+
pub fn param_env(&self) -> ty::ParameterEnvironment<'gcx> {
1676+
self.parameter_environment
16791677
}
16801678

16811679
pub fn closure_kind(&self,

src/librustc/traits/mod.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -477,7 +477,7 @@ pub fn normalize_param_env_or_error<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
477477
debug!("normalize_param_env_or_error: elaborated-predicates={:?}",
478478
predicates);
479479

480-
let elaborated_env = unnormalized_env.with_caller_bounds(tcx.intern_predicates(&predicates));
480+
let elaborated_env = ty::ParameterEnvironment::new(tcx.intern_predicates(&predicates));
481481

482482
tcx.infer_ctxt(elaborated_env, Reveal::UserFacing).enter(|infcx| {
483483
let predicates = match fully_normalize(
@@ -528,7 +528,7 @@ pub fn normalize_param_env_or_error<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
528528
debug!("normalize_param_env_or_error: resolved predicates={:?}",
529529
predicates);
530530

531-
infcx.parameter_environment.with_caller_bounds(tcx.intern_predicates(&predicates))
531+
ty::ParameterEnvironment::new(tcx.intern_predicates(&predicates))
532532
})
533533
}
534534

src/librustc/traits/select.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -315,7 +315,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
315315
self.infcx.tcx
316316
}
317317

318-
pub fn param_env(&self) -> &'cx ty::ParameterEnvironment<'gcx> {
318+
pub fn param_env(&self) -> ty::ParameterEnvironment<'gcx> {
319319
self.infcx.param_env()
320320
}
321321

src/librustc/ty/layout.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1079,7 +1079,7 @@ impl<'a, 'gcx, 'tcx> Layout {
10791079
let ptr_layout = |pointee: Ty<'gcx>| {
10801080
let non_zero = !ty.is_unsafe_ptr();
10811081
let pointee = infcx.normalize_projections(pointee);
1082-
if pointee.is_sized(tcx, &infcx.parameter_environment, DUMMY_SP) {
1082+
if pointee.is_sized(tcx, infcx.parameter_environment, DUMMY_SP) {
10831083
Ok(Scalar { value: Pointer, non_zero: non_zero })
10841084
} else {
10851085
let unsized_part = tcx.struct_tail(pointee);
@@ -1272,7 +1272,7 @@ impl<'a, 'gcx, 'tcx> Layout {
12721272
let fields = &def.variants[0].fields;
12731273
let last_field = &fields[fields.len()-1];
12741274
let always_sized = tcx.type_of(last_field.did)
1275-
.is_sized(tcx, &param_env, DUMMY_SP);
1275+
.is_sized(tcx, param_env, DUMMY_SP);
12761276
if !always_sized { StructKind::MaybeUnsizedUnivariant }
12771277
else { StructKind::AlwaysSizedUnivariant }
12781278
};

src/librustc/ty/maps.rs

Lines changed: 49 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
// except according to those terms.
1010

1111
use dep_graph::{DepGraph, DepNode, DepTrackingMap, DepTrackingMapConfig};
12-
use hir::def_id::{CrateNum, DefId, LOCAL_CRATE};
12+
use hir::def_id::{CrateNum, CRATE_DEF_INDEX, DefId, LOCAL_CRATE};
1313
use hir::def::Def;
1414
use hir;
1515
use middle::const_val;
@@ -136,6 +136,15 @@ impl Key for (MirSuite, MirPassIndex, DefId) {
136136
}
137137
}
138138

139+
impl<'tcx, T: Clone + Hash + Eq + Debug> Key for ty::ParameterEnvironmentAnd<'tcx, T> {
140+
fn map_crate(&self) -> CrateNum {
141+
LOCAL_CRATE
142+
}
143+
fn default_span(&self, _: TyCtxt) -> Span {
144+
DUMMY_SP
145+
}
146+
}
147+
139148
trait Value<'tcx>: Sized {
140149
fn from_cycle_error<'a>(tcx: TyCtxt<'a, 'tcx, 'tcx>) -> Self;
141150
}
@@ -244,6 +253,24 @@ impl<M: DepTrackingMapConfig<Key=DefId>> QueryDescription for M {
244253
}
245254
}
246255

256+
impl<'tcx> QueryDescription for queries::is_copy_raw<'tcx> {
257+
fn describe(_tcx: TyCtxt, env: ty::ParameterEnvironmentAnd<'tcx, Ty<'tcx>>) -> String {
258+
format!("computing whether `{}` is `Copy`", env.value)
259+
}
260+
}
261+
262+
impl<'tcx> QueryDescription for queries::is_sized_raw<'tcx> {
263+
fn describe(_tcx: TyCtxt, env: ty::ParameterEnvironmentAnd<'tcx, Ty<'tcx>>) -> String {
264+
format!("computing whether `{}` is `Sized`", env.value)
265+
}
266+
}
267+
268+
impl<'tcx> QueryDescription for queries::is_freeze_raw<'tcx> {
269+
fn describe(_tcx: TyCtxt, env: ty::ParameterEnvironmentAnd<'tcx, Ty<'tcx>>) -> String {
270+
format!("computing whether `{}` is freeze", env.value)
271+
}
272+
}
273+
247274
impl<'tcx> QueryDescription for queries::super_predicates_of<'tcx> {
248275
fn describe(tcx: TyCtxt, def_id: DefId) -> String {
249276
format!("computing the supertraits of `{}`",
@@ -856,6 +883,12 @@ define_maps! { <'tcx>
856883
-> ty::trait_def::TraitImpls,
857884
[] specialization_graph_of: SpecializationGraph(DefId) -> Rc<specialization_graph::Graph>,
858885
[] is_object_safe: ObjectSafety(DefId) -> bool,
886+
887+
// Trait selection queries. These are best used by invoking `ty.moves_by_default()`,
888+
// `ty.is_copy()`, etc, since that will prune the environment where possible.
889+
[] is_copy_raw: is_copy_dep_node(ty::ParameterEnvironmentAnd<'tcx, Ty<'tcx>>) -> bool,
890+
[] is_sized_raw: is_sized_dep_node(ty::ParameterEnvironmentAnd<'tcx, Ty<'tcx>>) -> bool,
891+
[] is_freeze_raw: is_freeze_dep_node(ty::ParameterEnvironmentAnd<'tcx, Ty<'tcx>>) -> bool,
859892
}
860893

861894
fn coherent_trait_dep_node((_, def_id): (CrateNum, DefId)) -> DepNode<DefId> {
@@ -899,3 +932,18 @@ fn crate_variances(_: CrateNum) -> DepNode<DefId> {
899932
fn relevant_trait_impls_for((def_id, _): (DefId, SimplifiedType)) -> DepNode<DefId> {
900933
DepNode::TraitImpls(def_id)
901934
}
935+
936+
fn is_copy_dep_node<'tcx>(_: ty::ParameterEnvironmentAnd<'tcx, Ty<'tcx>>) -> DepNode<DefId> {
937+
let krate_def_id = DefId::local(CRATE_DEF_INDEX);
938+
DepNode::IsCopy(krate_def_id)
939+
}
940+
941+
fn is_sized_dep_node<'tcx>(_: ty::ParameterEnvironmentAnd<'tcx, Ty<'tcx>>) -> DepNode<DefId> {
942+
let krate_def_id = DefId::local(CRATE_DEF_INDEX);
943+
DepNode::IsSized(krate_def_id)
944+
}
945+
946+
fn is_freeze_dep_node<'tcx>(_: ty::ParameterEnvironmentAnd<'tcx, Ty<'tcx>>) -> DepNode<DefId> {
947+
let krate_def_id = DefId::local(CRATE_DEF_INDEX);
948+
DepNode::IsSized(krate_def_id)
949+
}

src/librustc/ty/mod.rs

Lines changed: 23 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ use util::common::ErrorReported;
3535
use util::nodemap::{NodeSet, DefIdMap, FxHashMap, FxHashSet};
3636

3737
use serialize::{self, Encodable, Encoder};
38-
use std::cell::{Cell, RefCell};
38+
use std::cell::Cell;
3939
use std::collections::BTreeMap;
4040
use std::cmp;
4141
use std::fmt;
@@ -507,8 +507,6 @@ bitflags! {
507507
// Caches for type_is_sized, type_moves_by_default
508508
const SIZEDNESS_CACHED = 1 << 16,
509509
const IS_SIZED = 1 << 17,
510-
const MOVENESS_CACHED = 1 << 18,
511-
const MOVES_BY_DEFAULT = 1 << 19,
512510
const FREEZENESS_CACHED = 1 << 20,
513511
const IS_FREEZE = 1 << 21,
514512
const NEEDS_DROP_CACHED = 1 << 22,
@@ -1250,45 +1248,34 @@ impl<'tcx> InstantiatedPredicates<'tcx> {
12501248
}
12511249

12521250
/// When type checking, we use the `ParameterEnvironment` to track
1253-
/// details about the type/lifetime parameters that are in scope.
1254-
/// It primarily stores the bounds information.
1255-
///
1256-
/// Note: This information might seem to be redundant with the data in
1257-
/// `tcx.ty_param_defs`, but it is not. That table contains the
1258-
/// parameter definitions from an "outside" perspective, but this
1259-
/// struct will contain the bounds for a parameter as seen from inside
1260-
/// the function body. Currently the only real distinction is that
1261-
/// bound lifetime parameters are replaced with free ones, but in the
1262-
/// future I hope to refine the representation of types so as to make
1263-
/// more distinctions clearer.
1264-
#[derive(Clone)]
1251+
/// details about the set of where-clauses that are in scope at this
1252+
/// particular point.
1253+
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
12651254
pub struct ParameterEnvironment<'tcx> {
12661255
/// Obligations that the caller must satisfy. This is basically
12671256
/// the set of bounds on the in-scope type parameters, translated
12681257
/// into Obligations, and elaborated and normalized.
1269-
pub caller_bounds: &'tcx [ty::Predicate<'tcx>],
1270-
1271-
/// A cache for `moves_by_default`.
1272-
pub is_copy_cache: RefCell<FxHashMap<Ty<'tcx>, bool>>,
1258+
pub caller_bounds: &'tcx Slice<ty::Predicate<'tcx>>,
1259+
}
12731260

1274-
/// A cache for `type_is_sized`
1275-
pub is_sized_cache: RefCell<FxHashMap<Ty<'tcx>, bool>>,
1261+
impl<'tcx> ParameterEnvironment<'tcx> {
1262+
pub fn and<T>(self, value: T) -> ParameterEnvironmentAnd<'tcx, T> {
1263+
ParameterEnvironmentAnd {
1264+
param_env: self,
1265+
value: value,
1266+
}
1267+
}
1268+
}
12761269

1277-
/// A cache for `type_is_freeze`
1278-
pub is_freeze_cache: RefCell<FxHashMap<Ty<'tcx>, bool>>,
1270+
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
1271+
pub struct ParameterEnvironmentAnd<'tcx, T> {
1272+
pub param_env: ParameterEnvironment<'tcx>,
1273+
pub value: T,
12791274
}
12801275

1281-
impl<'a, 'tcx> ParameterEnvironment<'tcx> {
1282-
pub fn with_caller_bounds(&self,
1283-
caller_bounds: &'tcx [ty::Predicate<'tcx>])
1284-
-> ParameterEnvironment<'tcx>
1285-
{
1286-
ParameterEnvironment {
1287-
caller_bounds: caller_bounds,
1288-
is_copy_cache: RefCell::new(FxHashMap()),
1289-
is_sized_cache: RefCell::new(FxHashMap()),
1290-
is_freeze_cache: RefCell::new(FxHashMap()),
1291-
}
1276+
impl<'tcx, T> ParameterEnvironmentAnd<'tcx, T> {
1277+
pub fn into_parts(self) -> (ParameterEnvironment<'tcx>, T) {
1278+
(self.param_env, self.value)
12921279
}
12931280
}
12941281

@@ -2357,17 +2344,6 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
23572344
}
23582345
}
23592346

2360-
/// Construct a parameter environment suitable for static contexts or other contexts where there
2361-
/// are no free type/lifetime parameters in scope.
2362-
pub fn empty_parameter_environment(self) -> ParameterEnvironment<'tcx> {
2363-
ty::ParameterEnvironment {
2364-
caller_bounds: Slice::empty(),
2365-
is_copy_cache: RefCell::new(FxHashMap()),
2366-
is_sized_cache: RefCell::new(FxHashMap()),
2367-
is_freeze_cache: RefCell::new(FxHashMap()),
2368-
}
2369-
}
2370-
23712347
/// See `ParameterEnvironment` struct def'n for details.
23722348
pub fn parameter_environment(self, def_id: DefId) -> ParameterEnvironment<'gcx> {
23732349
//
@@ -2391,12 +2367,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
23912367
// sure that this will succeed without errors anyway.
23922368
//
23932369

2394-
let unnormalized_env = ty::ParameterEnvironment {
2395-
caller_bounds: tcx.intern_predicates(&predicates),
2396-
is_copy_cache: RefCell::new(FxHashMap()),
2397-
is_sized_cache: RefCell::new(FxHashMap()),
2398-
is_freeze_cache: RefCell::new(FxHashMap()),
2399-
};
2370+
let unnormalized_env = ty::ParameterEnvironment::new(tcx.intern_predicates(&predicates));
24002371

24012372
let body_id = self.hir.as_local_node_id(def_id).map_or(DUMMY_NODE_ID, |id| {
24022373
self.hir.maybe_body_owned_by(id).map_or(id, |body| body.node_id)
@@ -2566,6 +2537,7 @@ fn trait_of_item<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> Option
25662537

25672538

25682539
pub fn provide(providers: &mut ty::maps::Providers) {
2540+
util::provide(providers);
25692541
*providers = ty::maps::Providers {
25702542
associated_item,
25712543
associated_item_def_ids,

0 commit comments

Comments
 (0)