mirror of https://github.com/rust-lang/rust.git
Auto merge of #126409 - pacak:incr-uplorry, r=michaelwoerister
Trying to address an incremental compilation issues This pull request contains two independent changes, one makes it so when `try_force_from_dep_node` fails to recover a query - it marks the node as "red" instead of "green" and the second one makes Debug impl for `DepNode` less panicky if it encounters something from the previous compilation that doesn't map to anything in the current one. I'm not 100% confident that this is the correct approach, but so far I managed to find a bunch of comments suggesting that some things are allowed to fail in a certain way and changes I made are allowing for those things to fail this way and it fixes all the small reproducers I managed to find. Compilation panic this pull request avoids is caused by an automatically generated code on an associated type and it is not happening if something else marks it as outdated first (or close like that, but scenario is quite obscure). Fixes https://github.com/rust-lang/rust/issues/107226 Fixes https://github.com/rust-lang/rust/issues/125367
This commit is contained in:
commit
1d96de2a20
|
@ -377,22 +377,17 @@ impl Definitions {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub fn local_def_path_hash_to_def_id(
|
/// Returns `None` if the `DefPathHash` does not correspond to a `LocalDefId`
|
||||||
&self,
|
/// in the current compilation session. This can legitimately happen if the
|
||||||
hash: DefPathHash,
|
/// `DefPathHash` is from a `DefId` in an upstream crate or, during incr. comp.,
|
||||||
err_msg: &dyn std::fmt::Debug,
|
/// if the `DefPathHash` is from a previous compilation session and
|
||||||
) -> LocalDefId {
|
/// the def-path does not exist anymore.
|
||||||
|
pub fn local_def_path_hash_to_def_id(&self, hash: DefPathHash) -> Option<LocalDefId> {
|
||||||
debug_assert!(hash.stable_crate_id() == self.table.stable_crate_id);
|
debug_assert!(hash.stable_crate_id() == self.table.stable_crate_id);
|
||||||
#[cold]
|
|
||||||
#[inline(never)]
|
|
||||||
fn err(err_msg: &dyn std::fmt::Debug) -> ! {
|
|
||||||
panic!("{err_msg:?}")
|
|
||||||
}
|
|
||||||
self.table
|
self.table
|
||||||
.def_path_hash_to_index
|
.def_path_hash_to_index
|
||||||
.get(&hash.local_hash())
|
.get(&hash.local_hash())
|
||||||
.map(|local_def_index| LocalDefId { local_def_index })
|
.map(|local_def_index| LocalDefId { local_def_index })
|
||||||
.unwrap_or_else(|| err(err_msg))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn def_path_hash_to_def_index_map(&self) -> &DefPathHashMap {
|
pub fn def_path_hash_to_def_index_map(&self) -> &DefPathHashMap {
|
||||||
|
|
|
@ -194,10 +194,7 @@ impl DepNodeExt for DepNode {
|
||||||
/// has been removed.
|
/// has been removed.
|
||||||
fn extract_def_id(&self, tcx: TyCtxt<'_>) -> Option<DefId> {
|
fn extract_def_id(&self, tcx: TyCtxt<'_>) -> Option<DefId> {
|
||||||
if tcx.fingerprint_style(self.kind) == FingerprintStyle::DefPathHash {
|
if tcx.fingerprint_style(self.kind) == FingerprintStyle::DefPathHash {
|
||||||
Some(tcx.def_path_hash_to_def_id(
|
tcx.def_path_hash_to_def_id(DefPathHash(self.hash.into()))
|
||||||
DefPathHash(self.hash.into()),
|
|
||||||
&("Failed to extract DefId", self.kind, self.hash),
|
|
||||||
))
|
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
@ -390,12 +387,7 @@ impl<'tcx> DepNodeParams<TyCtxt<'tcx>> for HirId {
|
||||||
if tcx.fingerprint_style(dep_node.kind) == FingerprintStyle::HirId {
|
if tcx.fingerprint_style(dep_node.kind) == FingerprintStyle::HirId {
|
||||||
let (local_hash, local_id) = Fingerprint::from(dep_node.hash).split();
|
let (local_hash, local_id) = Fingerprint::from(dep_node.hash).split();
|
||||||
let def_path_hash = DefPathHash::new(tcx.stable_crate_id(LOCAL_CRATE), local_hash);
|
let def_path_hash = DefPathHash::new(tcx.stable_crate_id(LOCAL_CRATE), local_hash);
|
||||||
let def_id = tcx
|
let def_id = tcx.def_path_hash_to_def_id(def_path_hash)?.expect_local();
|
||||||
.def_path_hash_to_def_id(
|
|
||||||
def_path_hash,
|
|
||||||
&("Failed to extract HirId", dep_node.kind, dep_node.hash),
|
|
||||||
)
|
|
||||||
.expect_local();
|
|
||||||
let local_id = local_id
|
let local_id = local_id
|
||||||
.as_u64()
|
.as_u64()
|
||||||
.try_into()
|
.try_into()
|
||||||
|
|
|
@ -733,10 +733,10 @@ impl<'a, 'tcx> SpanDecoder for CacheDecoder<'a, 'tcx> {
|
||||||
// If we get to this point, then all of the query inputs were green,
|
// If we get to this point, then all of the query inputs were green,
|
||||||
// which means that the definition with this hash is guaranteed to
|
// which means that the definition with this hash is guaranteed to
|
||||||
// still exist in the current compilation session.
|
// still exist in the current compilation session.
|
||||||
self.tcx.def_path_hash_to_def_id(
|
match self.tcx.def_path_hash_to_def_id(def_path_hash) {
|
||||||
def_path_hash,
|
Some(r) => r,
|
||||||
&("Failed to convert DefPathHash", def_path_hash),
|
None => panic!("Failed to convert DefPathHash {def_path_hash:?}"),
|
||||||
)
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn decode_attr_id(&mut self) -> rustc_span::AttrId {
|
fn decode_attr_id(&mut self) -> rustc_span::AttrId {
|
||||||
|
|
|
@ -1677,11 +1677,7 @@ impl<'tcx> TyCtxt<'tcx> {
|
||||||
/// Converts a `DefPathHash` to its corresponding `DefId` in the current compilation
|
/// Converts a `DefPathHash` to its corresponding `DefId` in the current compilation
|
||||||
/// session, if it still exists. This is used during incremental compilation to
|
/// session, if it still exists. This is used during incremental compilation to
|
||||||
/// turn a deserialized `DefPathHash` into its current `DefId`.
|
/// turn a deserialized `DefPathHash` into its current `DefId`.
|
||||||
pub fn def_path_hash_to_def_id(
|
pub fn def_path_hash_to_def_id(self, hash: DefPathHash) -> Option<DefId> {
|
||||||
self,
|
|
||||||
hash: DefPathHash,
|
|
||||||
err_msg: &dyn std::fmt::Debug,
|
|
||||||
) -> DefId {
|
|
||||||
debug!("def_path_hash_to_def_id({:?})", hash);
|
debug!("def_path_hash_to_def_id({:?})", hash);
|
||||||
|
|
||||||
let stable_crate_id = hash.stable_crate_id();
|
let stable_crate_id = hash.stable_crate_id();
|
||||||
|
@ -1689,13 +1685,9 @@ impl<'tcx> TyCtxt<'tcx> {
|
||||||
// If this is a DefPathHash from the local crate, we can look up the
|
// If this is a DefPathHash from the local crate, we can look up the
|
||||||
// DefId in the tcx's `Definitions`.
|
// DefId in the tcx's `Definitions`.
|
||||||
if stable_crate_id == self.stable_crate_id(LOCAL_CRATE) {
|
if stable_crate_id == self.stable_crate_id(LOCAL_CRATE) {
|
||||||
self.untracked
|
Some(self.untracked.definitions.read().local_def_path_hash_to_def_id(hash)?.to_def_id())
|
||||||
.definitions
|
|
||||||
.read()
|
|
||||||
.local_def_path_hash_to_def_id(hash, err_msg)
|
|
||||||
.to_def_id()
|
|
||||||
} else {
|
} else {
|
||||||
self.def_path_hash_to_def_id_extern(hash, stable_crate_id)
|
Some(self.def_path_hash_to_def_id_extern(hash, stable_crate_id))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -51,20 +51,24 @@ pub trait DepContext: Copy {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Try to force a dep node to execute and see if it's green.
|
/// Try to force a dep node to execute and see if it's green.
|
||||||
|
///
|
||||||
|
/// Returns true if the query has actually been forced. It is valid that a query
|
||||||
|
/// fails to be forced, e.g. when the query key cannot be reconstructed from the
|
||||||
|
/// dep-node or when the query kind outright does not support it.
|
||||||
#[inline]
|
#[inline]
|
||||||
#[instrument(skip(self, frame), level = "debug")]
|
#[instrument(skip(self, frame), level = "debug")]
|
||||||
fn try_force_from_dep_node(self, dep_node: DepNode, frame: Option<&MarkFrame<'_>>) -> bool {
|
fn try_force_from_dep_node(self, dep_node: DepNode, frame: Option<&MarkFrame<'_>>) -> bool {
|
||||||
let cb = self.dep_kind_info(dep_node.kind);
|
let cb = self.dep_kind_info(dep_node.kind);
|
||||||
if let Some(f) = cb.force_from_dep_node {
|
if let Some(f) = cb.force_from_dep_node {
|
||||||
if let Err(value) = panic::catch_unwind(panic::AssertUnwindSafe(|| {
|
match panic::catch_unwind(panic::AssertUnwindSafe(|| f(self, dep_node))) {
|
||||||
f(self, dep_node);
|
Err(value) => {
|
||||||
})) {
|
if !value.is::<rustc_errors::FatalErrorMarker>() {
|
||||||
if !value.is::<rustc_errors::FatalErrorMarker>() {
|
print_markframe_trace(self.dep_graph(), frame);
|
||||||
print_markframe_trace(self.dep_graph(), frame);
|
}
|
||||||
|
panic::resume_unwind(value)
|
||||||
}
|
}
|
||||||
panic::resume_unwind(value)
|
Ok(query_has_been_forced) => query_has_been_forced,
|
||||||
}
|
}
|
||||||
true
|
|
||||||
} else {
|
} else {
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,40 @@
|
||||||
|
// If it is impossible to find query arguments just from the hash
|
||||||
|
// compiler should treat the node as red
|
||||||
|
|
||||||
|
// In this test prior to fixing compiler was having problems figuring out
|
||||||
|
// drop impl for T inside of m
|
||||||
|
|
||||||
|
//@ revisions:cfail1 cfail2
|
||||||
|
//@ compile-flags: --crate-type=lib
|
||||||
|
//@ build-pass
|
||||||
|
|
||||||
|
pub trait P {
|
||||||
|
type A;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct S;
|
||||||
|
|
||||||
|
impl P for S {
|
||||||
|
type A = C;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct T<D: P>(D::A, Z<D>);
|
||||||
|
|
||||||
|
struct Z<D: P>(D::A, String);
|
||||||
|
|
||||||
|
impl<D: P> T<D> {
|
||||||
|
pub fn i() -> Self {
|
||||||
|
loop {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
enum C {
|
||||||
|
#[cfg(cfail1)]
|
||||||
|
Up(()),
|
||||||
|
#[cfg(cfail2)]
|
||||||
|
Lorry(()),
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn m() {
|
||||||
|
T::<S>::i();
|
||||||
|
}
|
Loading…
Reference in New Issue