Skip to content

Commit 789566b

Browse files
authored
Rollup merge of #41368 - nikomatsakis:incr-comp-dep-tracking-map, r=eddyb
make *most* maps private Currently we access the `DepTrackingMap` fields directly rather than using the query accessors. This seems bad. This branch removes several such uses, but not all, and extends the macro so that queries can hide their maps (so we can prevent regressions). The extension to the macro is kind of ugly :/ but couldn't find a simple way to do it otherwise (I guess I could use a nested macro...). Anyway I figure it's only temporary. r? @eddyb
2 parents 6e0c5af + 054642e commit 789566b

File tree

11 files changed

+169
-121
lines changed

11 files changed

+169
-121
lines changed

src/librustc/middle/dead.rs

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -475,14 +475,13 @@ impl<'a, 'tcx> DeadVisitor<'a, 'tcx> {
475475
// This is done to handle the case where, for example, the static
476476
// method of a private type is used, but the type itself is never
477477
// called directly.
478-
if let Some(impl_list) =
479-
self.tcx.maps.inherent_impls.borrow().get(&self.tcx.hir.local_def_id(id)) {
480-
for &impl_did in impl_list.iter() {
481-
for &item_did in &self.tcx.associated_item_def_ids(impl_did)[..] {
482-
if let Some(item_node_id) = self.tcx.hir.as_local_node_id(item_did) {
483-
if self.live_symbols.contains(&item_node_id) {
484-
return true;
485-
}
478+
let def_id = self.tcx.hir.local_def_id(id);
479+
let inherent_impls = self.tcx.inherent_impls(def_id);
480+
for &impl_did in inherent_impls.iter() {
481+
for &item_did in &self.tcx.associated_item_def_ids(impl_did)[..] {
482+
if let Some(item_node_id) = self.tcx.hir.as_local_node_id(item_did) {
483+
if self.live_symbols.contains(&item_node_id) {
484+
return true;
486485
}
487486
}
488487
}

src/librustc/ty/item_path.rs

Lines changed: 31 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -13,16 +13,19 @@ use hir::def_id::{CrateNum, DefId, CRATE_DEF_INDEX, LOCAL_CRATE};
1313
use ty::{self, Ty, TyCtxt};
1414
use syntax::ast;
1515
use syntax::symbol::Symbol;
16+
use syntax_pos::DUMMY_SP;
1617

1718
use std::cell::Cell;
1819

1920
thread_local! {
20-
static FORCE_ABSOLUTE: Cell<bool> = Cell::new(false)
21+
static FORCE_ABSOLUTE: Cell<bool> = Cell::new(false);
22+
static FORCE_IMPL_FILENAME_LINE: Cell<bool> = Cell::new(false);
2123
}
2224

23-
/// Enforces that item_path_str always returns an absolute path.
24-
/// This is useful when building symbols that contain types,
25-
/// where we want the crate name to be part of the symbol.
25+
/// Enforces that item_path_str always returns an absolute path and
26+
/// also enables "type-based" impl paths. This is used when building
27+
/// symbols that contain types, where we want the crate name to be
28+
/// part of the symbol.
2629
pub fn with_forced_absolute_paths<F: FnOnce() -> R, R>(f: F) -> R {
2730
FORCE_ABSOLUTE.with(|force| {
2831
let old = force.get();
@@ -33,6 +36,20 @@ pub fn with_forced_absolute_paths<F: FnOnce() -> R, R>(f: F) -> R {
3336
})
3437
}
3538

39+
/// Force us to name impls with just the filename/line number. We
40+
/// normally try to use types. But at some points, notably while printing
41+
/// cycle errors, this can result in extra or suboptimal error output,
42+
/// so this variable disables that check.
43+
pub fn with_forced_impl_filename_line<F: FnOnce() -> R, R>(f: F) -> R {
44+
FORCE_IMPL_FILENAME_LINE.with(|force| {
45+
let old = force.get();
46+
force.set(true);
47+
let result = f();
48+
force.set(old);
49+
result
50+
})
51+
}
52+
3653
impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
3754
/// Returns a string identifying this def-id. This string is
3855
/// suitable for user output. It is relative to the current crate
@@ -196,14 +213,16 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
196213
{
197214
let parent_def_id = self.parent_def_id(impl_def_id).unwrap();
198215

199-
let use_types = if !impl_def_id.is_local() {
200-
// always have full types available for extern crates
201-
true
202-
} else {
203-
// for local crates, check whether type info is
204-
// available; typeck might not have completed yet
205-
self.maps.impl_trait_ref.borrow().contains_key(&impl_def_id) &&
206-
self.maps.type_of.borrow().contains_key(&impl_def_id)
216+
// Always use types for non-local impls, where types are always
217+
// available, and filename/line-number is mostly uninteresting.
218+
let use_types = !impl_def_id.is_local() || {
219+
// Otherwise, use filename/line-number if forced.
220+
let force_no_types = FORCE_IMPL_FILENAME_LINE.with(|f| f.get());
221+
!force_no_types && {
222+
// Otherwise, use types if we can query them without inducing a cycle.
223+
ty::queries::impl_trait_ref::try_get(self, DUMMY_SP, impl_def_id).is_ok() &&
224+
ty::queries::type_of::try_get(self, DUMMY_SP, impl_def_id).is_ok()
225+
}
207226
};
208227

209228
if !use_types {

src/librustc/ty/maps.rs

Lines changed: 69 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -16,11 +16,13 @@ use middle::privacy::AccessLevels;
1616
use mir;
1717
use session::CompileResult;
1818
use ty::{self, CrateInherentImpls, Ty, TyCtxt};
19+
use ty::item_path;
1920
use ty::subst::Substs;
2021
use util::nodemap::NodeSet;
2122

2223
use rustc_data_structures::indexed_vec::IndexVec;
2324
use std::cell::{RefCell, RefMut};
25+
use std::mem;
2426
use std::ops::Deref;
2527
use std::rc::Rc;
2628
use syntax_pos::{Span, DUMMY_SP};
@@ -122,24 +124,36 @@ pub struct CycleError<'a, 'tcx: 'a> {
122124

123125
impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
124126
pub fn report_cycle(self, CycleError { span, cycle }: CycleError) {
125-
assert!(!cycle.is_empty());
126-
127-
let mut err = struct_span_err!(self.sess, span, E0391,
128-
"unsupported cyclic reference between types/traits detected");
129-
err.span_label(span, &format!("cyclic reference"));
130-
131-
err.span_note(cycle[0].0, &format!("the cycle begins when {}...",
132-
cycle[0].1.describe(self)));
133-
134-
for &(span, ref query) in &cycle[1..] {
135-
err.span_note(span, &format!("...which then requires {}...",
136-
query.describe(self)));
137-
}
127+
// Subtle: release the refcell lock before invoking `describe()`
128+
// below by dropping `cycle`.
129+
let stack = cycle.to_vec();
130+
mem::drop(cycle);
131+
132+
assert!(!stack.is_empty());
133+
134+
// Disable naming impls with types in this path, since that
135+
// sometimes cycles itself, leading to extra cycle errors.
136+
// (And cycle errors around impls tend to occur during the
137+
// collect/coherence phases anyhow.)
138+
item_path::with_forced_impl_filename_line(|| {
139+
let mut err =
140+
struct_span_err!(self.sess, span, E0391,
141+
"unsupported cyclic reference between types/traits detected");
142+
err.span_label(span, &format!("cyclic reference"));
143+
144+
err.span_note(stack[0].0, &format!("the cycle begins when {}...",
145+
stack[0].1.describe(self)));
146+
147+
for &(span, ref query) in &stack[1..] {
148+
err.span_note(span, &format!("...which then requires {}...",
149+
query.describe(self)));
150+
}
138151

139-
err.note(&format!("...which then again requires {}, completing the cycle.",
140-
cycle[0].1.describe(self)));
152+
err.note(&format!("...which then again requires {}, completing the cycle.",
153+
stack[0].1.describe(self)));
141154

142-
err.emit();
155+
err.emit();
156+
});
143157
}
144158

145159
fn cycle_check<F, R>(self, span: Span, query: Query<'gcx>, compute: F)
@@ -245,11 +259,11 @@ impl<'tcx> QueryDescription for queries::const_eval<'tcx> {
245259
macro_rules! define_maps {
246260
(<$tcx:tt>
247261
$($(#[$attr:meta])*
248-
pub $name:ident: $node:ident($K:ty) -> $V:ty),*) => {
262+
[$($pub:tt)*] $name:ident: $node:ident($K:ty) -> $V:ty),*) => {
249263
pub struct Maps<$tcx> {
250264
providers: IndexVec<CrateNum, Providers<$tcx>>,
251265
query_stack: RefCell<Vec<(Span, Query<$tcx>)>>,
252-
$($(#[$attr])* pub $name: RefCell<DepTrackingMap<queries::$name<$tcx>>>),*
266+
$($(#[$attr])* $($pub)* $name: RefCell<DepTrackingMap<queries::$name<$tcx>>>),*
253267
}
254268

255269
impl<$tcx> Maps<$tcx> {
@@ -306,6 +320,11 @@ macro_rules! define_maps {
306320
-> Result<R, CycleError<'a, $tcx>>
307321
where F: FnOnce(&$V) -> R
308322
{
323+
debug!("ty::queries::{}::try_get_with(key={:?}, span={:?})",
324+
stringify!($name),
325+
key,
326+
span);
327+
309328
if let Some(result) = tcx.maps.$name.borrow().get(&key) {
310329
return Ok(f(result));
311330
}
@@ -412,52 +431,52 @@ macro_rules! define_maps {
412431
// the driver creates (using several `rustc_*` crates).
413432
define_maps! { <'tcx>
414433
/// Records the type of every item.
415-
pub type_of: ItemSignature(DefId) -> Ty<'tcx>,
434+
[] type_of: ItemSignature(DefId) -> Ty<'tcx>,
416435

417436
/// Maps from the def-id of an item (trait/struct/enum/fn) to its
418437
/// associated generics and predicates.
419-
pub generics_of: ItemSignature(DefId) -> &'tcx ty::Generics,
420-
pub predicates_of: ItemSignature(DefId) -> ty::GenericPredicates<'tcx>,
438+
[] generics_of: ItemSignature(DefId) -> &'tcx ty::Generics,
439+
[] predicates_of: ItemSignature(DefId) -> ty::GenericPredicates<'tcx>,
421440

422441
/// Maps from the def-id of a trait to the list of
423442
/// super-predicates. This is a subset of the full list of
424443
/// predicates. We store these in a separate map because we must
425444
/// evaluate them even during type conversion, often before the
426445
/// full predicates are available (note that supertraits have
427446
/// additional acyclicity requirements).
428-
pub super_predicates_of: ItemSignature(DefId) -> ty::GenericPredicates<'tcx>,
447+
[] super_predicates_of: ItemSignature(DefId) -> ty::GenericPredicates<'tcx>,
429448

430449
/// To avoid cycles within the predicates of a single item we compute
431450
/// per-type-parameter predicates for resolving `T::AssocTy`.
432-
pub type_param_predicates: TypeParamPredicates((DefId, DefId))
451+
[] type_param_predicates: TypeParamPredicates((DefId, DefId))
433452
-> ty::GenericPredicates<'tcx>,
434453

435-
pub trait_def: ItemSignature(DefId) -> &'tcx ty::TraitDef,
436-
pub adt_def: ItemSignature(DefId) -> &'tcx ty::AdtDef,
437-
pub adt_destructor: AdtDestructor(DefId) -> Option<ty::Destructor>,
438-
pub adt_sized_constraint: SizedConstraint(DefId) -> &'tcx [Ty<'tcx>],
439-
pub adt_dtorck_constraint: DtorckConstraint(DefId) -> ty::DtorckConstraint<'tcx>,
454+
[] trait_def: ItemSignature(DefId) -> &'tcx ty::TraitDef,
455+
[] adt_def: ItemSignature(DefId) -> &'tcx ty::AdtDef,
456+
[] adt_destructor: AdtDestructor(DefId) -> Option<ty::Destructor>,
457+
[] adt_sized_constraint: SizedConstraint(DefId) -> &'tcx [Ty<'tcx>],
458+
[] adt_dtorck_constraint: DtorckConstraint(DefId) -> ty::DtorckConstraint<'tcx>,
440459

441460
/// True if this is a foreign item (i.e., linked via `extern { ... }`).
442-
pub is_foreign_item: IsForeignItem(DefId) -> bool,
461+
[] is_foreign_item: IsForeignItem(DefId) -> bool,
443462

444463
/// Maps from def-id of a type or region parameter to its
445464
/// (inferred) variance.
446-
pub variances_of: ItemSignature(DefId) -> Rc<Vec<ty::Variance>>,
465+
[pub] variances_of: ItemSignature(DefId) -> Rc<Vec<ty::Variance>>,
447466

448467
/// Maps from an impl/trait def-id to a list of the def-ids of its items
449-
pub associated_item_def_ids: AssociatedItemDefIds(DefId) -> Rc<Vec<DefId>>,
468+
[] associated_item_def_ids: AssociatedItemDefIds(DefId) -> Rc<Vec<DefId>>,
450469

451470
/// Maps from a trait item to the trait item "descriptor"
452-
pub associated_item: AssociatedItems(DefId) -> ty::AssociatedItem,
471+
[] associated_item: AssociatedItems(DefId) -> ty::AssociatedItem,
453472

454-
pub impl_trait_ref: ItemSignature(DefId) -> Option<ty::TraitRef<'tcx>>,
455-
pub impl_polarity: ItemSignature(DefId) -> hir::ImplPolarity,
473+
[] impl_trait_ref: ItemSignature(DefId) -> Option<ty::TraitRef<'tcx>>,
474+
[] impl_polarity: ItemSignature(DefId) -> hir::ImplPolarity,
456475

457476
/// Maps a DefId of a type to a list of its inherent impls.
458477
/// Contains implementations of methods that are inherent to a type.
459478
/// Methods in these implementations don't need to be exported.
460-
pub inherent_impls: InherentImpls(DefId) -> Rc<Vec<DefId>>,
479+
[] inherent_impls: InherentImpls(DefId) -> Rc<Vec<DefId>>,
461480

462481
/// Maps from the def-id of a function/method or const/static
463482
/// to its MIR. Mutation is done at an item granularity to
@@ -466,54 +485,54 @@ define_maps! { <'tcx>
466485
///
467486
/// Note that cross-crate MIR appears to be always borrowed
468487
/// (in the `RefCell` sense) to prevent accidental mutation.
469-
pub mir: Mir(DefId) -> &'tcx RefCell<mir::Mir<'tcx>>,
488+
[pub] mir: Mir(DefId) -> &'tcx RefCell<mir::Mir<'tcx>>,
470489

471490
/// Maps DefId's that have an associated Mir to the result
472491
/// of the MIR qualify_consts pass. The actual meaning of
473492
/// the value isn't known except to the pass itself.
474-
pub mir_const_qualif: Mir(DefId) -> u8,
493+
[] mir_const_qualif: Mir(DefId) -> u8,
475494

476495
/// Records the type of each closure. The def ID is the ID of the
477496
/// expression defining the closure.
478-
pub closure_kind: ItemSignature(DefId) -> ty::ClosureKind,
497+
[] closure_kind: ItemSignature(DefId) -> ty::ClosureKind,
479498

480499
/// Records the type of each closure. The def ID is the ID of the
481500
/// expression defining the closure.
482-
pub closure_type: ItemSignature(DefId) -> ty::PolyFnSig<'tcx>,
501+
[] closure_type: ItemSignature(DefId) -> ty::PolyFnSig<'tcx>,
483502

484503
/// Caches CoerceUnsized kinds for impls on custom types.
485-
pub coerce_unsized_info: ItemSignature(DefId)
504+
[] coerce_unsized_info: ItemSignature(DefId)
486505
-> ty::adjustment::CoerceUnsizedInfo,
487506

488-
pub typeck_item_bodies: typeck_item_bodies_dep_node(CrateNum) -> CompileResult,
507+
[] typeck_item_bodies: typeck_item_bodies_dep_node(CrateNum) -> CompileResult,
489508

490-
pub typeck_tables_of: TypeckTables(DefId) -> &'tcx ty::TypeckTables<'tcx>,
509+
[] typeck_tables_of: TypeckTables(DefId) -> &'tcx ty::TypeckTables<'tcx>,
491510

492-
pub coherent_trait: coherent_trait_dep_node((CrateNum, DefId)) -> (),
511+
[] coherent_trait: coherent_trait_dep_node((CrateNum, DefId)) -> (),
493512

494-
pub borrowck: BorrowCheck(DefId) -> (),
513+
[] borrowck: BorrowCheck(DefId) -> (),
495514

496515
/// Gets a complete map from all types to their inherent impls.
497516
/// Not meant to be used directly outside of coherence.
498517
/// (Defined only for LOCAL_CRATE)
499-
pub crate_inherent_impls: crate_inherent_impls_dep_node(CrateNum) -> CrateInherentImpls,
518+
[] crate_inherent_impls: crate_inherent_impls_dep_node(CrateNum) -> CrateInherentImpls,
500519

501520
/// Checks all types in the krate for overlap in their inherent impls. Reports errors.
502521
/// Not meant to be used directly outside of coherence.
503522
/// (Defined only for LOCAL_CRATE)
504-
pub crate_inherent_impls_overlap_check: crate_inherent_impls_dep_node(CrateNum) -> (),
523+
[] crate_inherent_impls_overlap_check: crate_inherent_impls_dep_node(CrateNum) -> (),
505524

506525
/// Results of evaluating const items or constants embedded in
507526
/// other items (such as enum variant explicit discriminants).
508-
pub const_eval: const_eval_dep_node((DefId, &'tcx Substs<'tcx>))
527+
[] const_eval: const_eval_dep_node((DefId, &'tcx Substs<'tcx>))
509528
-> const_val::EvalResult<'tcx>,
510529

511530
/// Performs the privacy check and computes "access levels".
512-
pub privacy_access_levels: PrivacyAccessLevels(CrateNum) -> Rc<AccessLevels>,
531+
[] privacy_access_levels: PrivacyAccessLevels(CrateNum) -> Rc<AccessLevels>,
513532

514-
pub reachable_set: reachability_dep_node(CrateNum) -> Rc<NodeSet>,
533+
[] reachable_set: reachability_dep_node(CrateNum) -> Rc<NodeSet>,
515534

516-
pub mir_shims: mir_shim_dep_node(ty::InstanceDef<'tcx>) -> &'tcx RefCell<mir::Mir<'tcx>>
535+
[] mir_shims: mir_shim_dep_node(ty::InstanceDef<'tcx>) -> &'tcx RefCell<mir::Mir<'tcx>>
517536
}
518537

519538
fn coherent_trait_dep_node((_, def_id): (CrateNum, DefId)) -> DepNode<DefId> {

src/librustc/ty/mod.rs

Lines changed: 29 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2138,6 +2138,26 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
21382138
})
21392139
}
21402140

2141+
pub fn opt_associated_item(self, def_id: DefId) -> Option<AssociatedItem> {
2142+
let is_associated_item = if let Some(node_id) = self.hir.as_local_node_id(def_id) {
2143+
match self.hir.get(node_id) {
2144+
hir_map::NodeTraitItem(_) | hir_map::NodeImplItem(_) => true,
2145+
_ => false,
2146+
}
2147+
} else {
2148+
match self.sess.cstore.describe_def(def_id).expect("no def for def-id") {
2149+
Def::AssociatedConst(_) | Def::Method(_) | Def::AssociatedTy(_) => true,
2150+
_ => false,
2151+
}
2152+
};
2153+
2154+
if is_associated_item {
2155+
Some(self.associated_item(def_id))
2156+
} else {
2157+
None
2158+
}
2159+
}
2160+
21412161
fn associated_item_from_trait_item_ref(self,
21422162
parent_def_id: DefId,
21432163
parent_vis: &hir::Visibility,
@@ -2390,7 +2410,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
23902410
None
23912411
}
23922412
} else {
2393-
self.maps.associated_item.borrow().get(&def_id).cloned()
2413+
self.opt_associated_item(def_id)
23942414
};
23952415

23962416
match item {
@@ -2411,15 +2431,13 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
24112431
if def_id.krate != LOCAL_CRATE {
24122432
return self.sess.cstore.trait_of_item(def_id);
24132433
}
2414-
match self.maps.associated_item.borrow().get(&def_id) {
2415-
Some(associated_item) => {
2434+
self.opt_associated_item(def_id)
2435+
.and_then(|associated_item| {
24162436
match associated_item.container {
24172437
TraitContainer(def_id) => Some(def_id),
24182438
ImplContainer(_) => None
24192439
}
2420-
}
2421-
None => None
2422-
}
2440+
})
24232441
}
24242442

24252443
/// Construct a parameter environment suitable for static contexts or other contexts where there
@@ -2587,11 +2605,12 @@ fn associated_item<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId)
25872605
}
25882606
}
25892607

2590-
ref r => {
2591-
panic!("unexpected container of associated items: {:?}", r)
2592-
}
2608+
_ => { }
25932609
}
2594-
panic!("associated item not found for def_id: {:?}", def_id);
2610+
2611+
span_bug!(parent_item.span,
2612+
"unexpected parent of trait or impl item or item not found: {:?}",
2613+
parent_item.node)
25952614
}
25962615

25972616
/// Calculates the Sized-constraint.

0 commit comments

Comments
 (0)