Skip to main content

rustc_middle/
verify_ich.rs

1use std::cell::Cell;
2
3use rustc_data_structures::fingerprint::Fingerprint;
4use rustc_query_system::ich::StableHashingContext;
5use tracing::instrument;
6
7use crate::dep_graph::{DepContext, DepGraphData, SerializedDepNodeIndex};
8
9#[inline]
10#[allow(clippy :: suspicious_else_formatting)]
{
    let __tracing_attr_span;
    let __tracing_attr_guard;
    if ::tracing::Level::DEBUG <= ::tracing::level_filters::STATIC_MAX_LEVEL
                &&
                ::tracing::Level::DEBUG <=
                    ::tracing::level_filters::LevelFilter::current() ||
            { false } {
        __tracing_attr_span =
            {
                use ::tracing::__macro_support::Callsite as _;
                static __CALLSITE: ::tracing::callsite::DefaultCallsite =
                    {
                        static META: ::tracing::Metadata<'static> =
                            {
                                ::tracing_core::metadata::Metadata::new("incremental_verify_ich",
                                    "rustc_middle::verify_ich", ::tracing::Level::DEBUG,
                                    ::tracing_core::__macro_support::Option::Some("compiler/rustc_middle/src/verify_ich.rs"),
                                    ::tracing_core::__macro_support::Option::Some(10u32),
                                    ::tracing_core::__macro_support::Option::Some("rustc_middle::verify_ich"),
                                    ::tracing_core::field::FieldSet::new(&["prev_index"],
                                        ::tracing_core::callsite::Identifier(&__CALLSITE)),
                                    ::tracing::metadata::Kind::SPAN)
                            };
                        ::tracing::callsite::DefaultCallsite::new(&META)
                    };
                let mut interest = ::tracing::subscriber::Interest::never();
                if ::tracing::Level::DEBUG <=
                                    ::tracing::level_filters::STATIC_MAX_LEVEL &&
                                ::tracing::Level::DEBUG <=
                                    ::tracing::level_filters::LevelFilter::current() &&
                            { interest = __CALLSITE.interest(); !interest.is_never() }
                        &&
                        ::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
                            interest) {
                    let meta = __CALLSITE.metadata();
                    ::tracing::Span::new(meta,
                        &{
                                #[allow(unused_imports)]
                                use ::tracing::field::{debug, display, Value};
                                let mut iter = meta.fields().iter();
                                meta.fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
                                                    ::tracing::__macro_support::Option::Some(&::tracing::field::debug(&prev_index)
                                                            as &dyn Value))])
                            })
                } else {
                    let span =
                        ::tracing::__macro_support::__disabled_span(__CALLSITE.metadata());
                    {};
                    span
                }
            };
        __tracing_attr_guard = __tracing_attr_span.enter();
    }

    #[warn(clippy :: suspicious_else_formatting)]
    {

        #[allow(unknown_lints, unreachable_code, clippy ::
        diverging_sub_expression, clippy :: empty_loop, clippy ::
        let_unit_value, clippy :: let_with_type_underscore, clippy ::
        needless_return, clippy :: unreachable)]
        if false {
            let __tracing_attr_fake_return: () = loop {};
            return __tracing_attr_fake_return;
        }
        {
            if !dep_graph_data.is_index_green(prev_index) {
                incremental_verify_ich_not_green(tcx, prev_index)
            }
            let new_hash =
                hash_result.map_or(Fingerprint::ZERO,
                    |f|
                        {
                            tcx.with_stable_hashing_context(|mut hcx|
                                    f(&mut hcx, result))
                        });
            let old_hash = dep_graph_data.prev_fingerprint_of(prev_index);
            if new_hash != old_hash {
                incremental_verify_ich_failed(tcx, prev_index,
                    &|| format_value(result));
            }
        }
    }
}#[instrument(skip(tcx, dep_graph_data, result, hash_result, format_value), level = "debug")]
11pub fn incremental_verify_ich<Tcx, V>(
12    tcx: Tcx,
13    dep_graph_data: &DepGraphData<Tcx::Deps>,
14    result: &V,
15    prev_index: SerializedDepNodeIndex,
16    hash_result: Option<fn(&mut StableHashingContext<'_>, &V) -> Fingerprint>,
17    format_value: fn(&V) -> String,
18) where
19    Tcx: DepContext,
20{
21    if !dep_graph_data.is_index_green(prev_index) {
22        incremental_verify_ich_not_green(tcx, prev_index)
23    }
24
25    let new_hash = hash_result.map_or(Fingerprint::ZERO, |f| {
26        tcx.with_stable_hashing_context(|mut hcx| f(&mut hcx, result))
27    });
28
29    let old_hash = dep_graph_data.prev_fingerprint_of(prev_index);
30
31    if new_hash != old_hash {
32        incremental_verify_ich_failed(tcx, prev_index, &|| format_value(result));
33    }
34}
35
36#[cold]
37#[inline(never)]
38fn incremental_verify_ich_not_green<Tcx>(tcx: Tcx, prev_index: SerializedDepNodeIndex)
39where
40    Tcx: DepContext,
41{
42    {
    ::core::panicking::panic_fmt(format_args!("fingerprint for green query instance not loaded from cache: {0:?}",
            tcx.dep_graph().data().unwrap().prev_node_of(prev_index)));
}panic!(
43        "fingerprint for green query instance not loaded from cache: {:?}",
44        tcx.dep_graph().data().unwrap().prev_node_of(prev_index)
45    )
46}
47
48// Note that this is marked #[cold] and intentionally takes `dyn Debug` for `result`,
49// as we want to avoid generating a bunch of different implementations for LLVM to
50// chew on (and filling up the final binary, too).
51#[cold]
52#[inline(never)]
53fn incremental_verify_ich_failed<Tcx>(
54    tcx: Tcx,
55    prev_index: SerializedDepNodeIndex,
56    result: &dyn Fn() -> String,
57) where
58    Tcx: DepContext,
59{
60    // When we emit an error message and panic, we try to debug-print the `DepNode`
61    // and query result. Unfortunately, this can cause us to run additional queries,
62    // which may result in another fingerprint mismatch while we're in the middle
63    // of processing this one. To avoid a double-panic (which kills the process
64    // before we can print out the query static), we print out a terse
65    // but 'safe' message if we detect a reentrant call to this method.
66    const INSIDE_VERIFY_PANIC: ::std::thread::LocalKey<Cell<bool>> =
    {
        const __RUST_STD_INTERNAL_INIT: Cell<bool> = { Cell::new(false) };
        unsafe {
            ::std::thread::LocalKey::new(const {
                        if ::std::mem::needs_drop::<Cell<bool>>() {
                            |_|
                                {
                                    #[thread_local]
                                    static __RUST_STD_INTERNAL_VAL:
                                        ::std::thread::local_impl::EagerStorage<Cell<bool>> =
                                        ::std::thread::local_impl::EagerStorage::new(__RUST_STD_INTERNAL_INIT);
                                    __RUST_STD_INTERNAL_VAL.get()
                                }
                        } else {
                            |_|
                                {
                                    #[thread_local]
                                    static __RUST_STD_INTERNAL_VAL: Cell<bool> =
                                        __RUST_STD_INTERNAL_INIT;
                                    &__RUST_STD_INTERNAL_VAL
                                }
                        }
                    })
        }
    };thread_local! {
67        static INSIDE_VERIFY_PANIC: Cell<bool> = const { Cell::new(false) };
68    };
69
70    let old_in_panic = INSIDE_VERIFY_PANIC.replace(true);
71
72    if old_in_panic {
73        tcx.sess().dcx().emit_err(crate::error::Reentrant);
74    } else {
75        let run_cmd = if let Some(crate_name) = &tcx.sess().opts.crate_name {
76            ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("`cargo clean -p {0}` or `cargo clean`",
                crate_name))
    })format!("`cargo clean -p {crate_name}` or `cargo clean`")
77        } else {
78            "`cargo clean`".to_string()
79        };
80
81        let dep_node = tcx.dep_graph().data().unwrap().prev_node_of(prev_index);
82        tcx.sess().dcx().emit_err(crate::error::IncrementCompilation {
83            run_cmd,
84            dep_node: ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("{0:?}", dep_node))
    })format!("{dep_node:?}"),
85        });
86        {
    ::core::panicking::panic_fmt(format_args!("Found unstable fingerprints for {1:?}: {0}",
            result(), dep_node));
};panic!("Found unstable fingerprints for {dep_node:?}: {}", result());
87    }
88
89    INSIDE_VERIFY_PANIC.set(old_in_panic);
90}