Create a forever red node and use it to force side effects.
This commit is contained in:
parent
682f57656e
commit
15530a1c84
@ -20,12 +20,6 @@ rustc_queries! {
|
|||||||
desc { "trigger a delay span bug" }
|
desc { "trigger a delay span bug" }
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Create a new definition within the incr. comp. engine.
|
|
||||||
query register_def(_: ty::RawLocalDefId) -> LocalDefId {
|
|
||||||
eval_always
|
|
||||||
desc { "register a DefId with the incr. comp. engine" }
|
|
||||||
}
|
|
||||||
|
|
||||||
query resolutions(_: ()) -> &'tcx ty::ResolverOutputs {
|
query resolutions(_: ()) -> &'tcx ty::ResolverOutputs {
|
||||||
eval_always
|
eval_always
|
||||||
no_hash
|
no_hash
|
||||||
|
@ -123,9 +123,6 @@ impl<'tcx> Interner for TyCtxt<'tcx> {
|
|||||||
type PlaceholderRegion = ty::PlaceholderRegion;
|
type PlaceholderRegion = ty::PlaceholderRegion;
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, HashStable)]
|
|
||||||
pub struct RawLocalDefId(LocalDefId);
|
|
||||||
|
|
||||||
/// A type that is not publicly constructable. This prevents people from making [`TyKind::Error`]s
|
/// A type that is not publicly constructable. This prevents people from making [`TyKind::Error`]s
|
||||||
/// except through the error-reporting functions on a [`tcx`][TyCtxt].
|
/// except through the error-reporting functions on a [`tcx`][TyCtxt].
|
||||||
#[derive(Copy, Clone, Debug, Eq, Hash, PartialEq, PartialOrd, Ord)]
|
#[derive(Copy, Clone, Debug, Eq, Hash, PartialEq, PartialOrd, Ord)]
|
||||||
@ -1477,23 +1474,15 @@ impl<'tcx> TyCtxt<'tcx> {
|
|||||||
let def_id = self.definitions.write().create_def(parent, data);
|
let def_id = self.definitions.write().create_def(parent, data);
|
||||||
|
|
||||||
// We need to ensure that these side effects are re-run by the incr. comp. engine.
|
// We need to ensure that these side effects are re-run by the incr. comp. engine.
|
||||||
// When the incr. comp. engine considers marking this query as green, eval_always requires
|
use rustc_query_system::dep_graph::DepNodeIndex;
|
||||||
// we run the function to run. To invoke it, the parameter cannot be reconstructed from
|
self.dep_graph.read_index(DepNodeIndex::FOREVER_RED_NODE);
|
||||||
// the DepNode, so the caller query is run. Luckily, we are inside the caller query,
|
|
||||||
// therefore the definition is properly created.
|
|
||||||
debug_assert!({
|
|
||||||
use rustc_query_system::dep_graph::{DepContext, DepNodeParams};
|
|
||||||
self.is_eval_always(crate::dep_graph::DepKind::register_def)
|
|
||||||
&& !<RawLocalDefId as DepNodeParams<TyCtxt<'_>>>::fingerprint_style()
|
|
||||||
.reconstructible()
|
|
||||||
});
|
|
||||||
|
|
||||||
// Any LocalDefId which is used within queries, either as key or result, either:
|
// Any LocalDefId which is used within queries, either as key or result, either:
|
||||||
// - has been created before the construction of the TyCtxt;
|
// - has been created before the construction of the TyCtxt;
|
||||||
// - has been created by this call to `register_def`.
|
// - has been created by this call to `create_def`.
|
||||||
// As a consequence, this LocalDefId is always re-created before it is needed by the incr.
|
// As a consequence, this LocalDefId is always re-created before it is needed by the incr.
|
||||||
// comp. engine itself.
|
// comp. engine itself.
|
||||||
self.register_def(RawLocalDefId(def_id))
|
def_id
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn iter_local_def_id(self) -> impl Iterator<Item = LocalDefId> + 'tcx {
|
pub fn iter_local_def_id(self) -> impl Iterator<Item = LocalDefId> + 'tcx {
|
||||||
@ -3033,5 +3022,4 @@ pub fn provide(providers: &mut ty::query::Providers) {
|
|||||||
// We want to check if the panic handler was defined in this crate
|
// We want to check if the panic handler was defined in this crate
|
||||||
tcx.lang_items().panic_impl().map_or(false, |did| did.is_local())
|
tcx.lang_items().panic_impl().map_or(false, |did| did.is_local())
|
||||||
};
|
};
|
||||||
providers.register_def = |_, raw_id| raw_id.0;
|
|
||||||
}
|
}
|
||||||
|
@ -72,8 +72,8 @@ pub use self::consts::{
|
|||||||
pub use self::context::{
|
pub use self::context::{
|
||||||
tls, CanonicalUserType, CanonicalUserTypeAnnotation, CanonicalUserTypeAnnotations,
|
tls, CanonicalUserType, CanonicalUserTypeAnnotation, CanonicalUserTypeAnnotations,
|
||||||
CtxtInterners, DelaySpanBugEmitted, FreeRegionInfo, GeneratorDiagnosticData,
|
CtxtInterners, DelaySpanBugEmitted, FreeRegionInfo, GeneratorDiagnosticData,
|
||||||
GeneratorInteriorTypeCause, GlobalCtxt, Lift, OnDiskCache, RawLocalDefId, TyCtxt,
|
GeneratorInteriorTypeCause, GlobalCtxt, Lift, OnDiskCache, TyCtxt, TypeckResults, UserType,
|
||||||
TypeckResults, UserType, UserTypeAnnotationIndex,
|
UserTypeAnnotationIndex,
|
||||||
};
|
};
|
||||||
pub use self::instance::{Instance, InstanceDef};
|
pub use self::instance::{Instance, InstanceDef};
|
||||||
pub use self::list::List;
|
pub use self::list::List;
|
||||||
|
@ -39,17 +39,6 @@ impl Key for () {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Key for ty::RawLocalDefId {
|
|
||||||
#[inline(always)]
|
|
||||||
fn query_crate_is_local(&self) -> bool {
|
|
||||||
true
|
|
||||||
}
|
|
||||||
|
|
||||||
fn default_span(&self, _: TyCtxt<'_>) -> Span {
|
|
||||||
DUMMY_SP
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'tcx> Key for ty::InstanceDef<'tcx> {
|
impl<'tcx> Key for ty::InstanceDef<'tcx> {
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn query_crate_is_local(&self) -> bool {
|
fn query_crate_is_local(&self) -> bool {
|
||||||
|
@ -43,6 +43,7 @@ rustc_index::newtype_index! {
|
|||||||
impl DepNodeIndex {
|
impl DepNodeIndex {
|
||||||
pub const INVALID: DepNodeIndex = DepNodeIndex::MAX;
|
pub const INVALID: DepNodeIndex = DepNodeIndex::MAX;
|
||||||
pub const SINGLETON_DEPENDENCYLESS_ANON_NODE: DepNodeIndex = DepNodeIndex::from_u32(0);
|
pub const SINGLETON_DEPENDENCYLESS_ANON_NODE: DepNodeIndex = DepNodeIndex::from_u32(0);
|
||||||
|
pub const FOREVER_RED_NODE: DepNodeIndex = DepNodeIndex::from_u32(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
impl std::convert::From<DepNodeIndex> for QueryInvocationId {
|
impl std::convert::From<DepNodeIndex> for QueryInvocationId {
|
||||||
@ -124,6 +125,8 @@ impl<K: DepKind> DepGraph<K> {
|
|||||||
record_stats,
|
record_stats,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
let colors = DepNodeColorMap::new(prev_graph_node_count);
|
||||||
|
|
||||||
// Instantiate a dependy-less node only once for anonymous queries.
|
// Instantiate a dependy-less node only once for anonymous queries.
|
||||||
let _green_node_index = current.intern_new_node(
|
let _green_node_index = current.intern_new_node(
|
||||||
profiler,
|
profiler,
|
||||||
@ -133,6 +136,18 @@ impl<K: DepKind> DepGraph<K> {
|
|||||||
);
|
);
|
||||||
debug_assert_eq!(_green_node_index, DepNodeIndex::SINGLETON_DEPENDENCYLESS_ANON_NODE);
|
debug_assert_eq!(_green_node_index, DepNodeIndex::SINGLETON_DEPENDENCYLESS_ANON_NODE);
|
||||||
|
|
||||||
|
// Instantiate a dependy-less red node only once for anonymous queries.
|
||||||
|
let (_red_node_index, _prev_and_index) = current.intern_node(
|
||||||
|
profiler,
|
||||||
|
&prev_graph,
|
||||||
|
DepNode { kind: DepKind::NULL, hash: Fingerprint::ZERO.into() },
|
||||||
|
smallvec![],
|
||||||
|
None,
|
||||||
|
false,
|
||||||
|
);
|
||||||
|
debug_assert_eq!(_red_node_index, DepNodeIndex::FOREVER_RED_NODE);
|
||||||
|
debug_assert!(matches!(_prev_and_index, None | Some((_, DepNodeColor::Red))));
|
||||||
|
|
||||||
DepGraph {
|
DepGraph {
|
||||||
data: Some(Lrc::new(DepGraphData {
|
data: Some(Lrc::new(DepGraphData {
|
||||||
previous_work_products: prev_work_products,
|
previous_work_products: prev_work_products,
|
||||||
@ -140,7 +155,7 @@ impl<K: DepKind> DepGraph<K> {
|
|||||||
current,
|
current,
|
||||||
processed_side_effects: Default::default(),
|
processed_side_effects: Default::default(),
|
||||||
previous: prev_graph,
|
previous: prev_graph,
|
||||||
colors: DepNodeColorMap::new(prev_graph_node_count),
|
colors,
|
||||||
debug_loaded_from_disk: Default::default(),
|
debug_loaded_from_disk: Default::default(),
|
||||||
})),
|
})),
|
||||||
virtual_dep_node_index: Lrc::new(AtomicU32::new(0)),
|
virtual_dep_node_index: Lrc::new(AtomicU32::new(0)),
|
||||||
@ -965,6 +980,9 @@ impl<K: DepKind> CurrentDepGraph<K> {
|
|||||||
let nanos = duration.as_secs() * 1_000_000_000 + duration.subsec_nanos() as u64;
|
let nanos = duration.as_secs() * 1_000_000_000 + duration.subsec_nanos() as u64;
|
||||||
let mut stable_hasher = StableHasher::new();
|
let mut stable_hasher = StableHasher::new();
|
||||||
nanos.hash(&mut stable_hasher);
|
nanos.hash(&mut stable_hasher);
|
||||||
|
let anon_id_seed = stable_hasher.finish();
|
||||||
|
// We rely on the fact that `anon_id_seed` is not zero when creating static nodes.
|
||||||
|
debug_assert_ne!(anon_id_seed, Fingerprint::ZERO);
|
||||||
|
|
||||||
#[cfg(debug_assertions)]
|
#[cfg(debug_assertions)]
|
||||||
let forbidden_edge = match env::var("RUST_FORBID_DEP_GRAPH_EDGE") {
|
let forbidden_edge = match env::var("RUST_FORBID_DEP_GRAPH_EDGE") {
|
||||||
@ -1000,7 +1018,7 @@ impl<K: DepKind> CurrentDepGraph<K> {
|
|||||||
)
|
)
|
||||||
}),
|
}),
|
||||||
prev_index_to_index: Lock::new(IndexVec::from_elem_n(None, prev_graph_node_count)),
|
prev_index_to_index: Lock::new(IndexVec::from_elem_n(None, prev_graph_node_count)),
|
||||||
anon_id_seed: stable_hasher.finish(),
|
anon_id_seed,
|
||||||
#[cfg(debug_assertions)]
|
#[cfg(debug_assertions)]
|
||||||
forbidden_edge,
|
forbidden_edge,
|
||||||
total_read_count: AtomicU64::new(0),
|
total_read_count: AtomicU64::new(0),
|
||||||
|
Loading…
x
Reference in New Issue
Block a user