Skip to content

Commit 54dcbd9

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 70baf4f + fc27262 commit 54dcbd9

File tree

11 files changed

+171
-123
lines changed

11 files changed

+171
-123
lines changed

src/librustc/middle/dead.rs

+7-8
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

+31-12
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
@@ -199,14 +216,16 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
199216
{
200217
let parent_def_id = self.parent_def_id(impl_def_id).unwrap();
201218

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

212231
if !use_types {

src/librustc/ty/maps.rs

+71-52
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};
@@ -138,24 +140,36 @@ pub struct CycleError<'a, 'tcx: 'a> {
138140

139141
impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
140142
pub fn report_cycle(self, CycleError { span, cycle }: CycleError) {
141-
assert!(!cycle.is_empty());
142-
143-
let mut err = struct_span_err!(self.sess, span, E0391,
144-
"unsupported cyclic reference between types/traits detected");
145-
err.span_label(span, &format!("cyclic reference"));
146-
147-
err.span_note(cycle[0].0, &format!("the cycle begins when {}...",
148-
cycle[0].1.describe(self)));
149-
150-
for &(span, ref query) in &cycle[1..] {
151-
err.span_note(span, &format!("...which then requires {}...",
152-
query.describe(self)));
153-
}
143+
// Subtle: release the refcell lock before invoking `describe()`
144+
// below by dropping `cycle`.
145+
let stack = cycle.to_vec();
146+
mem::drop(cycle);
147+
148+
assert!(!stack.is_empty());
149+
150+
// Disable naming impls with types in this path, since that
151+
// sometimes cycles itself, leading to extra cycle errors.
152+
// (And cycle errors around impls tend to occur during the
153+
// collect/coherence phases anyhow.)
154+
item_path::with_forced_impl_filename_line(|| {
155+
let mut err =
156+
struct_span_err!(self.sess, span, E0391,
157+
"unsupported cyclic reference between types/traits detected");
158+
err.span_label(span, &format!("cyclic reference"));
159+
160+
err.span_note(stack[0].0, &format!("the cycle begins when {}...",
161+
stack[0].1.describe(self)));
162+
163+
for &(span, ref query) in &stack[1..] {
164+
err.span_note(span, &format!("...which then requires {}...",
165+
query.describe(self)));
166+
}
154167

155-
err.note(&format!("...which then again requires {}, completing the cycle.",
156-
cycle[0].1.describe(self)));
168+
err.note(&format!("...which then again requires {}, completing the cycle.",
169+
stack[0].1.describe(self)));
157170

158-
err.emit();
171+
err.emit();
172+
});
159173
}
160174

161175
fn cycle_check<F, R>(self, span: Span, query: Query<'gcx>, compute: F)
@@ -267,11 +281,11 @@ impl<'tcx> QueryDescription for queries::symbol_name<'tcx> {
267281
macro_rules! define_maps {
268282
(<$tcx:tt>
269283
$($(#[$attr:meta])*
270-
pub $name:ident: $node:ident($K:ty) -> $V:ty),*) => {
284+
[$($pub:tt)*] $name:ident: $node:ident($K:ty) -> $V:ty),*) => {
271285
pub struct Maps<$tcx> {
272286
providers: IndexVec<CrateNum, Providers<$tcx>>,
273287
query_stack: RefCell<Vec<(Span, Query<$tcx>)>>,
274-
$($(#[$attr])* pub $name: RefCell<DepTrackingMap<queries::$name<$tcx>>>),*
288+
$($(#[$attr])* $($pub)* $name: RefCell<DepTrackingMap<queries::$name<$tcx>>>),*
275289
}
276290

277291
impl<$tcx> Maps<$tcx> {
@@ -328,6 +342,11 @@ macro_rules! define_maps {
328342
-> Result<R, CycleError<'a, $tcx>>
329343
where F: FnOnce(&$V) -> R
330344
{
345+
debug!("ty::queries::{}::try_get_with(key={:?}, span={:?})",
346+
stringify!($name),
347+
key,
348+
span);
349+
331350
if let Some(result) = tcx.maps.$name.borrow().get(&key) {
332351
return Ok(f(result));
333352
}
@@ -434,52 +453,52 @@ macro_rules! define_maps {
434453
// the driver creates (using several `rustc_*` crates).
435454
define_maps! { <'tcx>
436455
/// Records the type of every item.
437-
pub type_of: ItemSignature(DefId) -> Ty<'tcx>,
456+
[] type_of: ItemSignature(DefId) -> Ty<'tcx>,
438457

439458
/// Maps from the def-id of an item (trait/struct/enum/fn) to its
440459
/// associated generics and predicates.
441-
pub generics_of: ItemSignature(DefId) -> &'tcx ty::Generics,
442-
pub predicates_of: ItemSignature(DefId) -> ty::GenericPredicates<'tcx>,
460+
[] generics_of: ItemSignature(DefId) -> &'tcx ty::Generics,
461+
[] predicates_of: ItemSignature(DefId) -> ty::GenericPredicates<'tcx>,
443462

444463
/// Maps from the def-id of a trait to the list of
445464
/// super-predicates. This is a subset of the full list of
446465
/// predicates. We store these in a separate map because we must
447466
/// evaluate them even during type conversion, often before the
448467
/// full predicates are available (note that supertraits have
449468
/// additional acyclicity requirements).
450-
pub super_predicates_of: ItemSignature(DefId) -> ty::GenericPredicates<'tcx>,
469+
[] super_predicates_of: ItemSignature(DefId) -> ty::GenericPredicates<'tcx>,
451470

452471
/// To avoid cycles within the predicates of a single item we compute
453472
/// per-type-parameter predicates for resolving `T::AssocTy`.
454-
pub type_param_predicates: TypeParamPredicates((DefId, DefId))
473+
[] type_param_predicates: TypeParamPredicates((DefId, DefId))
455474
-> ty::GenericPredicates<'tcx>,
456475

457-
pub trait_def: ItemSignature(DefId) -> &'tcx ty::TraitDef,
458-
pub adt_def: ItemSignature(DefId) -> &'tcx ty::AdtDef,
459-
pub adt_destructor: AdtDestructor(DefId) -> Option<ty::Destructor>,
460-
pub adt_sized_constraint: SizedConstraint(DefId) -> &'tcx [Ty<'tcx>],
461-
pub adt_dtorck_constraint: DtorckConstraint(DefId) -> ty::DtorckConstraint<'tcx>,
476+
[] trait_def: ItemSignature(DefId) -> &'tcx ty::TraitDef,
477+
[] adt_def: ItemSignature(DefId) -> &'tcx ty::AdtDef,
478+
[] adt_destructor: AdtDestructor(DefId) -> Option<ty::Destructor>,
479+
[] adt_sized_constraint: SizedConstraint(DefId) -> &'tcx [Ty<'tcx>],
480+
[] adt_dtorck_constraint: DtorckConstraint(DefId) -> ty::DtorckConstraint<'tcx>,
462481

463482
/// True if this is a foreign item (i.e., linked via `extern { ... }`).
464-
pub is_foreign_item: IsForeignItem(DefId) -> bool,
483+
[] is_foreign_item: IsForeignItem(DefId) -> bool,
465484

466485
/// Maps from def-id of a type or region parameter to its
467486
/// (inferred) variance.
468-
pub variances_of: ItemSignature(DefId) -> Rc<Vec<ty::Variance>>,
487+
[pub] variances_of: ItemSignature(DefId) -> Rc<Vec<ty::Variance>>,
469488

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

473492
/// Maps from a trait item to the trait item "descriptor"
474-
pub associated_item: AssociatedItems(DefId) -> ty::AssociatedItem,
493+
[] associated_item: AssociatedItems(DefId) -> ty::AssociatedItem,
475494

476-
pub impl_trait_ref: ItemSignature(DefId) -> Option<ty::TraitRef<'tcx>>,
477-
pub impl_polarity: ItemSignature(DefId) -> hir::ImplPolarity,
495+
[] impl_trait_ref: ItemSignature(DefId) -> Option<ty::TraitRef<'tcx>>,
496+
[] impl_polarity: ItemSignature(DefId) -> hir::ImplPolarity,
478497

479498
/// Maps a DefId of a type to a list of its inherent impls.
480499
/// Contains implementations of methods that are inherent to a type.
481500
/// Methods in these implementations don't need to be exported.
482-
pub inherent_impls: InherentImpls(DefId) -> Rc<Vec<DefId>>,
501+
[] inherent_impls: InherentImpls(DefId) -> Rc<Vec<DefId>>,
483502

484503
/// Maps from the def-id of a function/method or const/static
485504
/// to its MIR. Mutation is done at an item granularity to
@@ -488,57 +507,57 @@ define_maps! { <'tcx>
488507
///
489508
/// Note that cross-crate MIR appears to be always borrowed
490509
/// (in the `RefCell` sense) to prevent accidental mutation.
491-
pub mir: Mir(DefId) -> &'tcx RefCell<mir::Mir<'tcx>>,
510+
[pub] mir: Mir(DefId) -> &'tcx RefCell<mir::Mir<'tcx>>,
492511

493512
/// Maps DefId's that have an associated Mir to the result
494513
/// of the MIR qualify_consts pass. The actual meaning of
495514
/// the value isn't known except to the pass itself.
496-
pub mir_const_qualif: Mir(DefId) -> u8,
515+
[] mir_const_qualif: Mir(DefId) -> u8,
497516

498517
/// Records the type of each closure. The def ID is the ID of the
499518
/// expression defining the closure.
500-
pub closure_kind: ItemSignature(DefId) -> ty::ClosureKind,
519+
[] closure_kind: ItemSignature(DefId) -> ty::ClosureKind,
501520

502521
/// Records the type of each closure. The def ID is the ID of the
503522
/// expression defining the closure.
504-
pub closure_type: ItemSignature(DefId) -> ty::PolyFnSig<'tcx>,
523+
[] closure_type: ItemSignature(DefId) -> ty::PolyFnSig<'tcx>,
505524

506525
/// Caches CoerceUnsized kinds for impls on custom types.
507-
pub coerce_unsized_info: ItemSignature(DefId)
526+
[] coerce_unsized_info: ItemSignature(DefId)
508527
-> ty::adjustment::CoerceUnsizedInfo,
509528

510-
pub typeck_item_bodies: typeck_item_bodies_dep_node(CrateNum) -> CompileResult,
529+
[] typeck_item_bodies: typeck_item_bodies_dep_node(CrateNum) -> CompileResult,
511530

512-
pub typeck_tables_of: TypeckTables(DefId) -> &'tcx ty::TypeckTables<'tcx>,
531+
[] typeck_tables_of: TypeckTables(DefId) -> &'tcx ty::TypeckTables<'tcx>,
513532

514-
pub coherent_trait: coherent_trait_dep_node((CrateNum, DefId)) -> (),
533+
[] coherent_trait: coherent_trait_dep_node((CrateNum, DefId)) -> (),
515534

516-
pub borrowck: BorrowCheck(DefId) -> (),
535+
[] borrowck: BorrowCheck(DefId) -> (),
517536

518537
/// Gets a complete map from all types to their inherent impls.
519538
/// Not meant to be used directly outside of coherence.
520539
/// (Defined only for LOCAL_CRATE)
521-
pub crate_inherent_impls: crate_inherent_impls_dep_node(CrateNum) -> CrateInherentImpls,
540+
[] crate_inherent_impls: crate_inherent_impls_dep_node(CrateNum) -> CrateInherentImpls,
522541

523542
/// Checks all types in the krate for overlap in their inherent impls. Reports errors.
524543
/// Not meant to be used directly outside of coherence.
525544
/// (Defined only for LOCAL_CRATE)
526-
pub crate_inherent_impls_overlap_check: crate_inherent_impls_dep_node(CrateNum) -> (),
545+
[] crate_inherent_impls_overlap_check: crate_inherent_impls_dep_node(CrateNum) -> (),
527546

528547
/// Results of evaluating const items or constants embedded in
529548
/// other items (such as enum variant explicit discriminants).
530-
pub const_eval: const_eval_dep_node((DefId, &'tcx Substs<'tcx>))
549+
[] const_eval: const_eval_dep_node((DefId, &'tcx Substs<'tcx>))
531550
-> const_val::EvalResult<'tcx>,
532551

533552
/// Performs the privacy check and computes "access levels".
534-
pub privacy_access_levels: PrivacyAccessLevels(CrateNum) -> Rc<AccessLevels>,
553+
[] privacy_access_levels: PrivacyAccessLevels(CrateNum) -> Rc<AccessLevels>,
535554

536-
pub reachable_set: reachability_dep_node(CrateNum) -> Rc<NodeSet>,
555+
[] reachable_set: reachability_dep_node(CrateNum) -> Rc<NodeSet>,
537556

538-
pub mir_shims: mir_shim_dep_node(ty::InstanceDef<'tcx>) -> &'tcx RefCell<mir::Mir<'tcx>>,
557+
[] mir_shims: mir_shim_dep_node(ty::InstanceDef<'tcx>) -> &'tcx RefCell<mir::Mir<'tcx>>,
539558

540-
pub def_symbol_name: SymbolName(DefId) -> ty::SymbolName,
541-
pub symbol_name: symbol_name_dep_node(ty::Instance<'tcx>) -> ty::SymbolName
559+
[] def_symbol_name: SymbolName(DefId) -> ty::SymbolName,
560+
[] symbol_name: symbol_name_dep_node(ty::Instance<'tcx>) -> ty::SymbolName
542561
}
543562

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

0 commit comments

Comments
 (0)