Only allow feeding a value to newly created definitions.
This commit is contained in:
parent
9f2c6b0b09
commit
731c002b27
6 changed files with 47 additions and 33 deletions
|
@ -497,7 +497,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
||||||
self.tcx.hir().def_key(self.local_def_id(node_id)),
|
self.tcx.hir().def_key(self.local_def_id(node_id)),
|
||||||
);
|
);
|
||||||
|
|
||||||
let def_id = self.tcx.create_def(parent, data);
|
let def_id = self.tcx.create_def(parent, data).def_id;
|
||||||
|
|
||||||
debug!("create_def: def_id_to_node_id[{:?}] <-> {:?}", def_id, node_id);
|
debug!("create_def: def_id_to_node_id[{:?}] <-> {:?}", def_id, node_id);
|
||||||
self.resolver.node_id_to_def_id.insert(node_id, def_id);
|
self.resolver.node_id_to_def_id.insert(node_id, def_id);
|
||||||
|
|
|
@ -368,10 +368,6 @@ impl Definitions {
|
||||||
LocalDefId { local_def_index: self.table.allocate(key, def_path_hash) }
|
LocalDefId { local_def_index: self.table.allocate(key, def_path_hash) }
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn iter_local_def_id(&self) -> impl Iterator<Item = LocalDefId> + '_ {
|
|
||||||
self.table.def_path_hashes.indices().map(|local_def_index| LocalDefId { local_def_index })
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub fn local_def_path_hash_to_def_id(
|
pub fn local_def_path_hash_to_def_id(
|
||||||
&self,
|
&self,
|
||||||
|
@ -389,6 +385,10 @@ impl Definitions {
|
||||||
pub fn def_path_hash_to_def_index_map(&self) -> &DefPathHashMap {
|
pub fn def_path_hash_to_def_index_map(&self) -> &DefPathHashMap {
|
||||||
&self.table.def_path_hash_to_index
|
&self.table.def_path_hash_to_index
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn num_definitions(&self) -> usize {
|
||||||
|
self.table.def_path_hashes.len()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Copy, Clone, PartialEq, Debug)]
|
#[derive(Copy, Clone, PartialEq, Debug)]
|
||||||
|
|
|
@ -30,8 +30,10 @@
|
||||||
#![feature(core_intrinsics)]
|
#![feature(core_intrinsics)]
|
||||||
#![feature(discriminant_kind)]
|
#![feature(discriminant_kind)]
|
||||||
#![feature(exhaustive_patterns)]
|
#![feature(exhaustive_patterns)]
|
||||||
|
#![feature(generators)]
|
||||||
#![feature(get_mut_unchecked)]
|
#![feature(get_mut_unchecked)]
|
||||||
#![feature(if_let_guard)]
|
#![feature(if_let_guard)]
|
||||||
|
#![feature(iter_from_generator)]
|
||||||
#![feature(negative_impls)]
|
#![feature(negative_impls)]
|
||||||
#![feature(never_type)]
|
#![feature(never_type)]
|
||||||
#![feature(extern_types)]
|
#![feature(extern_types)]
|
||||||
|
|
|
@ -165,7 +165,6 @@ rustc_queries! {
|
||||||
}
|
}
|
||||||
cache_on_disk_if { key.is_local() }
|
cache_on_disk_if { key.is_local() }
|
||||||
separate_provide_extern
|
separate_provide_extern
|
||||||
feedable
|
|
||||||
}
|
}
|
||||||
|
|
||||||
query collect_trait_impl_trait_tys(key: DefId)
|
query collect_trait_impl_trait_tys(key: DefId)
|
||||||
|
|
|
@ -53,6 +53,7 @@ use rustc_hir::{
|
||||||
use rustc_index::vec::{Idx, IndexVec};
|
use rustc_index::vec::{Idx, IndexVec};
|
||||||
use rustc_macros::HashStable;
|
use rustc_macros::HashStable;
|
||||||
use rustc_middle::mir::FakeReadCause;
|
use rustc_middle::mir::FakeReadCause;
|
||||||
|
use rustc_query_system::dep_graph::DepNodeIndex;
|
||||||
use rustc_query_system::ich::StableHashingContext;
|
use rustc_query_system::ich::StableHashingContext;
|
||||||
use rustc_serialize::opaque::{FileEncodeResult, FileEncoder};
|
use rustc_serialize::opaque::{FileEncodeResult, FileEncoder};
|
||||||
use rustc_session::config::{CrateType, OutputFilenames};
|
use rustc_session::config::{CrateType, OutputFilenames};
|
||||||
|
@ -1009,6 +1010,14 @@ pub struct FreeRegionInfo {
|
||||||
pub is_impl_item: bool,
|
pub is_impl_item: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Copy, Clone)]
|
||||||
|
pub struct TyCtxtFeed<'tcx> {
|
||||||
|
pub tcx: TyCtxt<'tcx>,
|
||||||
|
pub def_id: LocalDefId,
|
||||||
|
/// This struct should only be created by `create_def`.
|
||||||
|
_priv: (),
|
||||||
|
}
|
||||||
|
|
||||||
/// The central data structure of the compiler. It stores references
|
/// The central data structure of the compiler. It stores references
|
||||||
/// to the various **arenas** and also houses the results of the
|
/// to the various **arenas** and also houses the results of the
|
||||||
/// various **compiler queries** that have been performed. See the
|
/// various **compiler queries** that have been performed. See the
|
||||||
|
@ -1471,12 +1480,15 @@ impl<'tcx> TyCtxt<'tcx> {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Create a new definition within the incr. comp. engine.
|
/// Create a new definition within the incr. comp. engine.
|
||||||
pub fn create_def(self, parent: LocalDefId, data: hir::definitions::DefPathData) -> LocalDefId {
|
pub fn create_def(
|
||||||
|
self,
|
||||||
|
parent: LocalDefId,
|
||||||
|
data: hir::definitions::DefPathData,
|
||||||
|
) -> TyCtxtFeed<'tcx> {
|
||||||
// This function modifies `self.definitions` using a side-effect.
|
// This function modifies `self.definitions` using a side-effect.
|
||||||
// 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.
|
||||||
// Depending on the forever-red node will tell the graph that the calling query
|
// Depending on the forever-red node will tell the graph that the calling query
|
||||||
// needs to be re-evaluated.
|
// needs to be re-evaluated.
|
||||||
use rustc_query_system::dep_graph::DepNodeIndex;
|
|
||||||
self.dep_graph.read_index(DepNodeIndex::FOREVER_RED_NODE);
|
self.dep_graph.read_index(DepNodeIndex::FOREVER_RED_NODE);
|
||||||
|
|
||||||
// The following call has the side effect of modifying the tables inside `definitions`.
|
// The following call has the side effect of modifying the tables inside `definitions`.
|
||||||
|
@ -1493,23 +1505,38 @@ impl<'tcx> TyCtxt<'tcx> {
|
||||||
// This is fine because:
|
// This is fine because:
|
||||||
// - those queries are `eval_always` so we won't miss their result changing;
|
// - those queries are `eval_always` so we won't miss their result changing;
|
||||||
// - this write will have happened before these queries are called.
|
// - this write will have happened before these queries are called.
|
||||||
self.definitions.write().create_def(parent, data)
|
let def_id = self.definitions.write().create_def(parent, data);
|
||||||
|
|
||||||
|
TyCtxtFeed { tcx: self, def_id, _priv: () }
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn iter_local_def_id(self) -> impl Iterator<Item = LocalDefId> + 'tcx {
|
pub fn iter_local_def_id(self) -> impl Iterator<Item = LocalDefId> + 'tcx {
|
||||||
// Create a dependency to the crate to be sure we re-execute this when the amount of
|
// Create a dependency to the red node to be sure we re-execute this when the amount of
|
||||||
// definitions change.
|
// definitions change.
|
||||||
self.ensure().hir_crate(());
|
self.dep_graph.read_index(DepNodeIndex::FOREVER_RED_NODE);
|
||||||
// Leak a read lock once we start iterating on definitions, to prevent adding new ones
|
|
||||||
// while iterating. If some query needs to add definitions, it should be `ensure`d above.
|
let definitions = &self.definitions;
|
||||||
let definitions = self.definitions.leak();
|
std::iter::from_generator(|| {
|
||||||
definitions.iter_local_def_id()
|
let mut i = 0;
|
||||||
|
|
||||||
|
// Recompute the number of definitions each time, because our caller may be creating
|
||||||
|
// new ones.
|
||||||
|
while i < { definitions.read().num_definitions() } {
|
||||||
|
let local_def_index = rustc_span::def_id::DefIndex::from_usize(i);
|
||||||
|
yield LocalDefId { local_def_index };
|
||||||
|
i += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Leak a read lock once we finish iterating on definitions, to prevent adding new ones.
|
||||||
|
definitions.leak();
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn def_path_table(self) -> &'tcx rustc_hir::definitions::DefPathTable {
|
pub fn def_path_table(self) -> &'tcx rustc_hir::definitions::DefPathTable {
|
||||||
// Create a dependency to the crate to be sure we re-execute this when the amount of
|
// Create a dependency to the crate to be sure we re-execute this when the amount of
|
||||||
// definitions change.
|
// definitions change.
|
||||||
self.ensure().hir_crate(());
|
self.dep_graph.read_index(DepNodeIndex::FOREVER_RED_NODE);
|
||||||
|
|
||||||
// Leak a read lock once we start iterating on definitions, to prevent adding new ones
|
// Leak a read lock once we start iterating on definitions, to prevent adding new ones
|
||||||
// while iterating. If some query needs to add definitions, it should be `ensure`d above.
|
// while iterating. If some query needs to add definitions, it should be `ensure`d above.
|
||||||
let definitions = self.definitions.leak();
|
let definitions = self.definitions.leak();
|
||||||
|
|
|
@ -28,6 +28,7 @@ use crate::traits::query::{
|
||||||
};
|
};
|
||||||
use crate::traits::specialization_graph;
|
use crate::traits::specialization_graph;
|
||||||
use crate::traits::{self, ImplSource};
|
use crate::traits::{self, ImplSource};
|
||||||
|
use crate::ty::context::TyCtxtFeed;
|
||||||
use crate::ty::fast_reject::SimplifiedType;
|
use crate::ty::fast_reject::SimplifiedType;
|
||||||
use crate::ty::layout::TyAndLayout;
|
use crate::ty::layout::TyAndLayout;
|
||||||
use crate::ty::subst::{GenericArg, SubstsRef};
|
use crate::ty::subst::{GenericArg, SubstsRef};
|
||||||
|
@ -85,11 +86,6 @@ pub struct TyCtxtEnsure<'tcx> {
|
||||||
pub tcx: TyCtxt<'tcx>,
|
pub tcx: TyCtxt<'tcx>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Copy, Clone)]
|
|
||||||
pub struct TyCtxtFeed<'tcx> {
|
|
||||||
pub tcx: TyCtxt<'tcx>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'tcx> TyCtxt<'tcx> {
|
impl<'tcx> TyCtxt<'tcx> {
|
||||||
/// Returns a transparent wrapper for `TyCtxt`, which ensures queries
|
/// Returns a transparent wrapper for `TyCtxt`, which ensures queries
|
||||||
/// are executed instead of just returning their results.
|
/// are executed instead of just returning their results.
|
||||||
|
@ -98,12 +94,6 @@ impl<'tcx> TyCtxt<'tcx> {
|
||||||
TyCtxtEnsure { tcx: self }
|
TyCtxtEnsure { tcx: self }
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns a transparent wrapper for `TyCtxt`, for setting a result into a query.
|
|
||||||
#[inline(always)]
|
|
||||||
pub fn feed(self) -> TyCtxtFeed<'tcx> {
|
|
||||||
TyCtxtFeed { tcx: self }
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Returns a transparent wrapper for `TyCtxt` which uses
|
/// Returns a transparent wrapper for `TyCtxt` which uses
|
||||||
/// `span` as the location of queries performed through it.
|
/// `span` as the location of queries performed through it.
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
|
@ -355,12 +345,8 @@ macro_rules! define_feedable {
|
||||||
impl<'tcx> TyCtxtFeed<'tcx> {
|
impl<'tcx> TyCtxtFeed<'tcx> {
|
||||||
$($(#[$attr])*
|
$($(#[$attr])*
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub fn $name(
|
pub fn $name(self, value: $V) -> query_stored::$name<'tcx> {
|
||||||
self,
|
let key = self.def_id.into_query_param();
|
||||||
key: query_helper_param_ty!($($K)*),
|
|
||||||
value: $V,
|
|
||||||
) -> query_stored::$name<'tcx> {
|
|
||||||
let key = key.into_query_param();
|
|
||||||
opt_remap_env_constness!([$($modifiers)*][key]);
|
opt_remap_env_constness!([$($modifiers)*][key]);
|
||||||
|
|
||||||
let tcx = self.tcx;
|
let tcx = self.tcx;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue