diff --git a/compiler/rustc_ast_lowering/src/expr.rs b/compiler/rustc_ast_lowering/src/expr.rs index 5e0ab80c6ac9f..aa5afbc0c450a 100644 --- a/compiler/rustc_ast_lowering/src/expr.rs +++ b/compiler/rustc_ast_lowering/src/expr.rs @@ -160,7 +160,8 @@ impl<'hir> LoweringContext<'_, 'hir> { self.lower_expr_if(cond, then, else_opt.as_deref()) } ExprKind::While(cond, body, opt_label) => self.with_loop_scope(e.id, |this| { - let span = this.mark_span_with_reason(DesugaringKind::WhileLoop, e.span, None); + let span = + this.tcx.mark_span_with_reason(DesugaringKind::WhileLoop, e.span, None); this.lower_expr_while_in_loop_scope(span, cond, body, *opt_label) }), ExprKind::Loop(body, opt_label, span) => self.with_loop_scope(e.id, |this| { @@ -448,7 +449,7 @@ impl<'hir> LoweringContext<'_, 'hir> { _ => { let cond = self.lower_expr(cond); let reason = DesugaringKind::CondTemporary; - let span_block = self.mark_span_with_reason(reason, cond.span, None); + let span_block = self.tcx.mark_span_with_reason(reason, cond.span, None); self.expr_drop_temps(span_block, cond) } } @@ -501,7 +502,7 @@ impl<'hir> LoweringContext<'_, 'hir> { // Final expression of the block (if present) or `()` with span at the end of block let (try_span, tail_expr) = if let Some(expr) = block.expr.take() { ( - this.mark_span_with_reason( + this.tcx.mark_span_with_reason( DesugaringKind::TryBlock, expr.span, this.allow_try_trait.clone(), @@ -509,7 +510,7 @@ impl<'hir> LoweringContext<'_, 'hir> { expr, ) } else { - let try_span = this.mark_span_with_reason( + let try_span = this.tcx.mark_span_with_reason( DesugaringKind::TryBlock, this.tcx.sess.source_map().end_point(body.span), this.allow_try_trait.clone(), @@ -519,7 +520,7 @@ impl<'hir> LoweringContext<'_, 'hir> { }; let ok_wrapped_span = - this.mark_span_with_reason(DesugaringKind::TryBlock, tail_expr.span, None); + this.tcx.mark_span_with_reason(DesugaringKind::TryBlock, tail_expr.span, None); // `::std::ops::Try::from_output($tail_expr)` block.expr = Some(this.wrap_in_try_constructor( @@ -591,8 +592,11 @@ impl<'hir> LoweringContext<'_, 'hir> { let output = ret_ty.unwrap_or_else(|| hir::FnRetTy::DefaultReturn(self.lower_span(span))); // Resume argument type: `ResumeTy` - let unstable_span = - self.mark_span_with_reason(DesugaringKind::Async, span, self.allow_gen_future.clone()); + let unstable_span = self.tcx.mark_span_with_reason( + DesugaringKind::Async, + span, + self.allow_gen_future.clone(), + ); let resume_ty = hir::QPath::LangItem(hir::LangItem::ResumeTy, unstable_span, None); let input_ty = hir::Ty { hir_id: self.next_id(), @@ -661,7 +665,7 @@ impl<'hir> LoweringContext<'_, 'hir> { && attrs.into_iter().any(|attr| attr.has_name(sym::track_caller)) { let unstable_span = - self.mark_span_with_reason(DesugaringKind::Async, span, self.allow_gen_future.clone()); + self.tcx.mark_span_with_reason(DesugaringKind::Async, span, self.allow_gen_future.clone()); self.lower_attrs( inner_hir_id, &[Attribute { @@ -707,8 +711,8 @@ impl<'hir> LoweringContext<'_, 'hir> { }); } } - let span = self.mark_span_with_reason(DesugaringKind::Await, await_kw_span, None); - let gen_future_span = self.mark_span_with_reason( + let span = self.tcx.mark_span_with_reason(DesugaringKind::Await, await_kw_span, None); + let gen_future_span = self.tcx.mark_span_with_reason( DesugaringKind::Await, full_span, self.allow_gen_future.clone(), @@ -1466,9 +1470,9 @@ impl<'hir> LoweringContext<'_, 'hir> { let head = self.lower_expr_mut(head); let pat = self.lower_pat(pat); let for_span = - self.mark_span_with_reason(DesugaringKind::ForLoop, self.lower_span(e.span), None); - let head_span = self.mark_span_with_reason(DesugaringKind::ForLoop, head.span, None); - let pat_span = self.mark_span_with_reason(DesugaringKind::ForLoop, pat.span, None); + self.tcx.mark_span_with_reason(DesugaringKind::ForLoop, self.lower_span(e.span), None); + let head_span = self.tcx.mark_span_with_reason(DesugaringKind::ForLoop, head.span, None); + let pat_span = self.tcx.mark_span_with_reason(DesugaringKind::ForLoop, pat.span, None); // `None => break` let none_arm = { @@ -1562,13 +1566,13 @@ impl<'hir> LoweringContext<'_, 'hir> { /// } /// ``` fn lower_expr_try(&mut self, span: Span, sub_expr: &Expr) -> hir::ExprKind<'hir> { - let unstable_span = self.mark_span_with_reason( + let unstable_span = self.tcx.mark_span_with_reason( DesugaringKind::QuestionMark, span, self.allow_try_trait.clone(), ); let try_span = self.tcx.sess.source_map().end_point(span); - let try_span = self.mark_span_with_reason( + let try_span = self.tcx.mark_span_with_reason( DesugaringKind::QuestionMark, try_span, self.allow_try_trait.clone(), @@ -1659,10 +1663,13 @@ impl<'hir> LoweringContext<'_, 'hir> { let (yeeted_span, yeeted_expr) = if let Some(sub_expr) = sub_expr { (sub_expr.span, self.lower_expr(sub_expr)) } else { - (self.mark_span_with_reason(DesugaringKind::YeetExpr, span, None), self.expr_unit(span)) + ( + self.tcx.mark_span_with_reason(DesugaringKind::YeetExpr, span, None), + self.expr_unit(span), + ) }; - let unstable_span = self.mark_span_with_reason( + let unstable_span = self.tcx.mark_span_with_reason( DesugaringKind::YeetExpr, span, self.allow_try_trait.clone(), diff --git a/compiler/rustc_ast_lowering/src/item.rs b/compiler/rustc_ast_lowering/src/item.rs index 08ee3761bac2b..9254401307e76 100644 --- a/compiler/rustc_ast_lowering/src/item.rs +++ b/compiler/rustc_ast_lowering/src/item.rs @@ -1071,7 +1071,8 @@ impl<'hir> LoweringContext<'_, 'hir> { } }; - let desugared_span = this.mark_span_with_reason(DesugaringKind::Async, span, None); + let desugared_span = + this.tcx.mark_span_with_reason(DesugaringKind::Async, span, None); // Construct a parameter representing `__argN: ` to replace the parameter of the // async function. @@ -1160,7 +1161,7 @@ impl<'hir> LoweringContext<'_, 'hir> { // Transform into `drop-temps { }`, an expression: let desugared_span = - this.mark_span_with_reason(DesugaringKind::Async, user_body.span, None); + this.tcx.mark_span_with_reason(DesugaringKind::Async, user_body.span, None); let user_body = this.expr_drop_temps(desugared_span, this.arena.alloc(user_body)); diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index 8d4f96639efbd..94eb9eefc050f 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -762,19 +762,6 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { self.tcx.sess.diagnostic() } - /// Reuses the span but adds information like the kind of the desugaring and features that are - /// allowed inside this span. - fn mark_span_with_reason( - &self, - reason: DesugaringKind, - span: Span, - allow_internal_unstable: Option>, - ) -> Span { - self.tcx.with_stable_hashing_context(|hcx| { - span.mark_with_reason(allow_internal_unstable, reason, self.tcx.sess.edition(), hcx) - }) - } - /// Intercept all spans entering HIR. /// Mark a span as relative to the current owning item. fn lower_span(&self, span: Span) -> Span { @@ -1529,7 +1516,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { // desugaring that explicitly states that we don't want to track that. // Not tracking it makes lints in rustc and clippy very fragile, as // frequently opened issues show. - let opaque_ty_span = self.mark_span_with_reason(DesugaringKind::OpaqueTy, span, None); + let opaque_ty_span = self.tcx.mark_span_with_reason(DesugaringKind::OpaqueTy, span, None); let opaque_ty_def_id = self.create_def( self.current_hir_id_owner.def_id, @@ -1893,7 +1880,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { ) -> hir::FnRetTy<'hir> { let span = output.span(); - let opaque_ty_span = self.mark_span_with_reason(DesugaringKind::Async, span, None); + let opaque_ty_span = self.tcx.mark_span_with_reason(DesugaringKind::Async, span, None); let fn_def_id = self.local_def_id(fn_node_id); diff --git a/compiler/rustc_data_structures/src/fingerprint.rs b/compiler/rustc_data_structures/src/fingerprint.rs index 9995c08345c2a..a507d2687c538 100644 --- a/compiler/rustc_data_structures/src/fingerprint.rs +++ b/compiler/rustc_data_structures/src/fingerprint.rs @@ -196,6 +196,10 @@ impl Decodable for Fingerprint { #[derive(Eq, PartialEq, Ord, PartialOrd, Debug, Clone, Copy, Hash)] pub struct PackedFingerprint(Fingerprint); +impl PackedFingerprint { + pub const ZERO: PackedFingerprint = PackedFingerprint(Fingerprint::ZERO); +} + impl std::fmt::Display for PackedFingerprint { #[inline] fn fmt(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { diff --git a/compiler/rustc_expand/src/expand.rs b/compiler/rustc_expand/src/expand.rs index ce0093c7d4c0e..8522e38c813a9 100644 --- a/compiler/rustc_expand/src/expand.rs +++ b/compiler/rustc_expand/src/expand.rs @@ -486,7 +486,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> { .map(|(path, item, _exts, is_const)| { // FIXME: Consider using the derive resolutions (`_exts`) // instead of enqueuing the derives to be resolved again later. - let expn_id = LocalExpnId::fresh_empty(); + let expn_id = LocalExpnId::reserve_expn_id(); derive_invocations.push(( Invocation { kind: InvocationKind::Derive { path, item, is_const }, @@ -1548,7 +1548,7 @@ impl<'a, 'b> InvocationCollector<'a, 'b> { } fn collect(&mut self, fragment_kind: AstFragmentKind, kind: InvocationKind) -> AstFragment { - let expn_id = LocalExpnId::fresh_empty(); + let expn_id = LocalExpnId::reserve_expn_id(); let vis = kind.placeholder_visibility(); self.invocations.push(( Invocation { diff --git a/compiler/rustc_middle/src/dep_graph/mod.rs b/compiler/rustc_middle/src/dep_graph/mod.rs index 0ddbe7d1c2922..71e9a80f308df 100644 --- a/compiler/rustc_middle/src/dep_graph/mod.rs +++ b/compiler/rustc_middle/src/dep_graph/mod.rs @@ -16,6 +16,7 @@ pub(crate) use dep_node::{make_compile_codegen_unit, make_compile_mono_item}; pub type DepGraph = rustc_query_system::dep_graph::DepGraph; +pub type CurrentDepNode = rustc_query_system::dep_graph::CurrentDepNode; pub type TaskDeps = rustc_query_system::dep_graph::TaskDeps; pub type TaskDepsRef<'a> = rustc_query_system::dep_graph::TaskDepsRef<'a, DepKind>; pub type DepGraphQuery = rustc_query_system::dep_graph::DepGraphQuery; @@ -48,12 +49,13 @@ impl rustc_query_system::dep_graph::DepKind for DepKind { write!(f, ")") } - fn with_deps(task_deps: TaskDepsRef<'_>, op: OP) -> R + fn with_deps(current_node: CurrentDepNode, task_deps: TaskDepsRef<'_>, op: OP) -> R where OP: FnOnce() -> R, { ty::tls::with_context(|icx| { - let icx = ty::tls::ImplicitCtxt { task_deps, ..icx.clone() }; + let icx = + ty::tls::ImplicitCtxt { current_node: ¤t_node, task_deps, ..icx.clone() }; ty::tls::enter_context(&icx, op) }) diff --git a/compiler/rustc_middle/src/query/on_disk_cache.rs b/compiler/rustc_middle/src/query/on_disk_cache.rs index 220118ae5ccb8..f99db91364cb0 100644 --- a/compiler/rustc_middle/src/query/on_disk_cache.rs +++ b/compiler/rustc_middle/src/query/on_disk_cache.rs @@ -630,20 +630,7 @@ impl<'a, 'tcx> Decodable> for ExpnId { let data: ExpnData = decoder .with_position(pos.to_usize(), |decoder| decode_tagged(decoder, TAG_EXPN_DATA)); - let expn_id = rustc_span::hygiene::register_local_expn_id(data, hash); - - #[cfg(debug_assertions)] - { - use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; - let local_hash = decoder.tcx.with_stable_hashing_context(|mut hcx| { - let mut hasher = StableHasher::new(); - expn_id.expn_data().hash_stable(&mut hcx, &mut hasher); - hasher.finish() - }); - debug_assert_eq!(hash.local_hash(), local_hash); - } - - expn_id + rustc_span::hygiene::register_local_expn_id(data, hash) } else { let index_guess = decoder.foreign_expn_data[&hash]; decoder.tcx.cstore_untracked().expn_hash_to_expn_id( diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index 2bde55bc4fd31..296a80af24bdb 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -5,7 +5,7 @@ pub mod tls; use crate::arena::Arena; -use crate::dep_graph::{DepGraph, DepKindStruct}; +use crate::dep_graph::{CurrentDepNode, DepGraph, DepKindStruct, DepNode}; use crate::infer::canonical::CanonicalVarInfo; use crate::lint::struct_lint_level; use crate::metadata::ModChild; @@ -65,6 +65,7 @@ use rustc_session::Limit; use rustc_session::Session; use rustc_span::def_id::{DefPathHash, StableCrateId}; use rustc_span::symbol::{kw, sym, Ident, Symbol}; +use rustc_span::{DesugaringKind, ExpnData, ExpnKind, LocalExpnId}; use rustc_span::{Span, DUMMY_SP}; use rustc_target::abi::{FieldIdx, Layout, LayoutS, TargetDataLayout, VariantIdx}; use rustc_target::spec::abi; @@ -547,7 +548,12 @@ impl<'tcx> GlobalCtxt<'tcx> { where F: FnOnce(TyCtxt<'tcx>) -> R, { - let icx = tls::ImplicitCtxt::new(self); + let current_node = if self.dep_graph.is_fully_enabled() { + CurrentDepNode::Untracked + } else { + CurrentDepNode::regular(DepNode::NULL) + }; + let icx = tls::ImplicitCtxt::new(self, ¤t_node); tls::enter_context(&icx, || f(icx.tcx)) } } @@ -901,6 +907,50 @@ impl<'tcx> TyCtxt<'tcx> { } } +impl<'tcx> TyCtxt<'tcx> { + #[instrument(level = "trace", skip(self), ret)] + pub fn create_expn(self, expn_data: ExpnData) -> LocalExpnId { + tls::with_related_context(self, |icx| { + let CurrentDepNode::Regular { dep_node, expn_disambiguators } = icx.current_node else { + bug!("creating an expansion outside of a query") + }; + self.with_stable_hashing_context(|ctx| { + LocalExpnId::create_untracked_expn(expn_data, dep_node, ctx, &expn_disambiguators) + }) + }) + } + + /// Fill an empty expansion. This method must not be used outside of the resolver. + #[inline] + #[instrument(level = "trace", skip(self))] + pub fn finalize_expn(self, expn_id: LocalExpnId, expn_data: ExpnData) { + tls::with_related_context(self, |icx| { + let CurrentDepNode::Regular { dep_node, expn_disambiguators } = icx.current_node else { + bug!("creating an expansion outside of a query") + }; + self.with_stable_hashing_context(|ctx| { + expn_id.set_untracked_expn_data(expn_data, dep_node, ctx, &expn_disambiguators) + }) + }); + } + + /// Reuses the span but adds information like the kind of the desugaring and features that are + /// allowed inside this span. + pub fn mark_span_with_reason( + self, + reason: DesugaringKind, + span: Span, + allow_internal_unstable: Option>, + ) -> Span { + let edition = self.sess.edition(); + let mut expn_data = + ExpnData::default(ExpnKind::Desugaring(reason), span, edition, None, None); + expn_data.allow_internal_unstable = allow_internal_unstable; + let expn_id = self.create_expn(expn_data); + span.fresh_expansion(expn_id) + } +} + impl<'tcx> TyCtxtAt<'tcx> { /// Create a new definition within the incr. comp. engine. pub fn create_def( diff --git a/compiler/rustc_middle/src/ty/context/tls.rs b/compiler/rustc_middle/src/ty/context/tls.rs index 9de77b9fda11a..4e9c6f1c6eda6 100644 --- a/compiler/rustc_middle/src/ty/context/tls.rs +++ b/compiler/rustc_middle/src/ty/context/tls.rs @@ -1,6 +1,6 @@ use super::{GlobalCtxt, TyCtxt}; -use crate::dep_graph::TaskDepsRef; +use crate::dep_graph::{CurrentDepNode, TaskDepsRef}; use crate::query::plumbing::QueryJobId; use rustc_data_structures::sync::{self, Lock}; use rustc_errors::Diagnostic; @@ -31,19 +31,24 @@ pub struct ImplicitCtxt<'a, 'tcx> { /// Used to prevent queries from calling too deeply. pub query_depth: usize, + /// The DepNode of the query being executed. This is updated by the dep-graph. This is used to + /// know which query created an expansion. + pub current_node: &'a CurrentDepNode, + /// The current dep graph task. This is used to add dependencies to queries /// when executing them. pub task_deps: TaskDepsRef<'a>, } impl<'a, 'tcx> ImplicitCtxt<'a, 'tcx> { - pub fn new(gcx: &'tcx GlobalCtxt<'tcx>) -> Self { + pub fn new(gcx: &'tcx GlobalCtxt<'tcx>, current_node: &'a CurrentDepNode) -> Self { let tcx = TyCtxt { gcx }; ImplicitCtxt { tcx, query: None, diagnostics: None, query_depth: 0, + current_node, task_deps: TaskDepsRef::Ignore, } } diff --git a/compiler/rustc_query_impl/src/plumbing.rs b/compiler/rustc_query_impl/src/plumbing.rs index 244f0e84b43d9..284848500db2d 100644 --- a/compiler/rustc_query_impl/src/plumbing.rs +++ b/compiler/rustc_query_impl/src/plumbing.rs @@ -142,6 +142,7 @@ impl QueryContext for QueryCtxt<'_> { query: Some(token), diagnostics, query_depth: current_icx.query_depth + depth_limit as usize, + current_node: current_icx.current_node, task_deps: current_icx.task_deps, }; diff --git a/compiler/rustc_query_system/src/dep_graph/dep_node.rs b/compiler/rustc_query_system/src/dep_graph/dep_node.rs index 9e1ca6ab515d8..36bf4171b7b68 100644 --- a/compiler/rustc_query_system/src/dep_graph/dep_node.rs +++ b/compiler/rustc_query_system/src/dep_graph/dep_node.rs @@ -58,6 +58,8 @@ pub struct DepNode { } impl DepNode { + pub const NULL: DepNode = DepNode { kind: K::NULL, hash: PackedFingerprint::ZERO }; + /// Creates a new, parameterless DepNode. This method will assert /// that the DepNode corresponding to the given DepKind actually /// does not require any parameters. diff --git a/compiler/rustc_query_system/src/dep_graph/graph.rs b/compiler/rustc_query_system/src/dep_graph/graph.rs index c0d7386dd6adb..9960d608ebff6 100644 --- a/compiler/rustc_query_system/src/dep_graph/graph.rs +++ b/compiler/rustc_query_system/src/dep_graph/graph.rs @@ -18,7 +18,7 @@ use std::sync::atomic::Ordering::Relaxed; use super::query::DepGraphQuery; use super::serialized::{GraphEncoder, SerializedDepGraph, SerializedDepNodeIndex}; -use super::{DepContext, DepKind, DepNode, HasDepContext, WorkProductId}; +use super::{CurrentDepNode, DepContext, DepKind, DepNode, HasDepContext, WorkProductId}; use crate::ich::StableHashingContext; use crate::query::{QueryContext, QuerySideEffects}; @@ -218,7 +218,7 @@ impl DepGraph { where OP: FnOnce() -> R, { - K::with_deps(TaskDepsRef::Ignore, op) + K::with_deps(CurrentDepNode::Untracked, TaskDepsRef::Ignore, op) } /// Used to wrap the deserialization of a query result from disk, @@ -271,7 +271,7 @@ impl DepGraph { where OP: FnOnce() -> R, { - K::with_deps(TaskDepsRef::Forbid, op) + K::with_deps(CurrentDepNode::Untracked, TaskDepsRef::Forbid, op) } #[inline(always)] @@ -354,7 +354,8 @@ impl DepGraphData { - dep-node: {key:?}" ); - let with_deps = |task_deps| K::with_deps(task_deps, || task(cx, arg)); + let with_deps = + |task_deps| K::with_deps(CurrentDepNode::regular(key), task_deps, || task(cx, arg)); let (result, edges) = if cx.dep_context().is_eval_always(key.kind) { (with_deps(TaskDepsRef::EvalAlways), smallvec![]) } else { @@ -414,7 +415,7 @@ impl DepGraphData { debug_assert!(!cx.is_eval_always(dep_kind)); let task_deps = Lock::new(TaskDeps::default()); - let result = K::with_deps(TaskDepsRef::Allow(&task_deps), op); + let result = K::with_deps(CurrentDepNode::Anonymous, TaskDepsRef::Allow(&task_deps), op); let task_deps = task_deps.into_inner(); let task_deps = task_deps.reads; diff --git a/compiler/rustc_query_system/src/dep_graph/mod.rs b/compiler/rustc_query_system/src/dep_graph/mod.rs index 40e7131987fab..ba1382f8ce866 100644 --- a/compiler/rustc_query_system/src/dep_graph/mod.rs +++ b/compiler/rustc_query_system/src/dep_graph/mod.rs @@ -14,6 +14,9 @@ pub use serialized::{SerializedDepGraph, SerializedDepNodeIndex}; use crate::ich::StableHashingContext; use rustc_data_structures::profiling::SelfProfilerRef; +use rustc_data_structures::stable_hasher::Hash64; +use rustc_data_structures::sync::Lock; +use rustc_data_structures::unhash::UnhashMap; use rustc_serialize::{opaque::FileEncoder, Encodable}; use rustc_session::Session; @@ -137,6 +140,23 @@ impl FingerprintStyle { } } +pub enum CurrentDepNode { + Regular { + dep_node: DepNode, + /// Disambiguation map for expansions created while executing + /// the query with this `DepNode`. + expn_disambiguators: Lock>, + }, + Anonymous, + Untracked, +} + +impl CurrentDepNode { + pub fn regular(dep_node: DepNode) -> CurrentDepNode { + CurrentDepNode::Regular { dep_node, expn_disambiguators: Default::default() } + } +} + /// Describe the different families of dependency nodes. pub trait DepKind: Copy + fmt::Debug + Eq + Hash + Send + Encodable + 'static { /// DepKind to use when incr. comp. is turned off. @@ -149,7 +169,7 @@ pub trait DepKind: Copy + fmt::Debug + Eq + Hash + Send + Encodable fn debug_node(node: &DepNode, f: &mut fmt::Formatter<'_>) -> fmt::Result; /// Execute the operation with provided dependencies. - fn with_deps(deps: TaskDepsRef<'_, Self>, op: OP) -> R + fn with_deps(node: CurrentDepNode, deps: TaskDepsRef<'_, Self>, op: OP) -> R where OP: FnOnce() -> R; diff --git a/compiler/rustc_query_system/src/query/plumbing.rs b/compiler/rustc_query_system/src/query/plumbing.rs index 730e4c8d30db3..cd9ef8d1f71cb 100644 --- a/compiler/rustc_query_system/src/query/plumbing.rs +++ b/compiler/rustc_query_system/src/query/plumbing.rs @@ -2,8 +2,8 @@ //! generate the actual methods on tcx which find and execute the provider, //! manage the caches, and so forth. +use crate::dep_graph::{CurrentDepNode, DepGraphData, HasDepContext, TaskDepsRef}; use crate::dep_graph::{DepContext, DepKind, DepNode, DepNodeIndex, DepNodeParams}; -use crate::dep_graph::{DepGraphData, HasDepContext}; use crate::ich::StableHashingContext; use crate::query::caches::QueryCache; #[cfg(parallel_compiler)] @@ -629,8 +629,12 @@ where // recompute. let prof_timer = qcx.dep_context().profiler().query_provider(); - // The dep-graph for this computation is already in-place. - let result = qcx.dep_context().dep_graph().with_ignore(|| query.compute(qcx, *key)); + // The dep-graph for this computation is already in-place, but any side effect due to this + // query needs to know our DepNode. + let result = + Qcx::DepKind::with_deps(CurrentDepNode::regular(*dep_node), TaskDepsRef::Ignore, || { + query.compute(qcx, *key) + }); prof_timer.finish_with_query_invocation_id(dep_node_index.into()); @@ -676,7 +680,6 @@ pub(crate) fn incremental_verify_ich( }); 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)); } diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs index fd977e8e254a2..5525983fd33a5 100644 --- a/compiler/rustc_resolve/src/lib.rs +++ b/compiler/rustc_resolve/src/lib.rs @@ -51,7 +51,6 @@ use rustc_middle::query::Providers; use rustc_middle::span_bug; use rustc_middle::ty::{self, MainDefinition, RegisteredTools, TyCtxt}; use rustc_middle::ty::{ResolverGlobalCtxt, ResolverOutputs}; -use rustc_query_system::ich::StableHashingContext; use rustc_session::lint::LintBuffer; use rustc_span::hygiene::{ExpnId, LocalExpnId, MacroKind, SyntaxContext, Transparency}; use rustc_span::symbol::{kw, sym, Ident, Symbol}; @@ -1445,10 +1444,6 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { ResolverOutputs { global_ctxt, ast_lowering } } - fn create_stable_hashing_context(&self) -> StableHashingContext<'_> { - StableHashingContext::new(self.tcx.sess, self.tcx.untracked()) - } - fn crate_loader(&mut self, f: impl FnOnce(&mut CrateLoader<'_, '_>) -> T) -> T { f(&mut CrateLoader::new( self.tcx, diff --git a/compiler/rustc_resolve/src/macros.rs b/compiler/rustc_resolve/src/macros.rs index df5c16a9375fb..65be61a7108f7 100644 --- a/compiler/rustc_resolve/src/macros.rs +++ b/compiler/rustc_resolve/src/macros.rs @@ -217,17 +217,14 @@ impl<'a, 'tcx> ResolverExpand for Resolver<'a, 'tcx> { ) -> LocalExpnId { let parent_module = parent_module_id.map(|module_id| self.local_def_id(module_id).to_def_id()); - let expn_id = LocalExpnId::fresh( - ExpnData::allow_unstable( - ExpnKind::AstPass(pass), - call_site, - self.tcx.sess.edition(), - features.into(), - None, - parent_module, - ), - self.create_stable_hashing_context(), - ); + let expn_id = self.tcx.create_expn(ExpnData::allow_unstable( + ExpnKind::AstPass(pass), + call_site, + self.tcx.sess.edition(), + features.into(), + None, + parent_module, + )); let parent_scope = parent_module.map_or(self.empty_module, |def_id| self.expect_module(def_id)); @@ -290,7 +287,8 @@ impl<'a, 'tcx> ResolverExpand for Resolver<'a, 'tcx> { let span = invoc.span(); let def_id = res.opt_def_id(); - invoc_id.set_expn_data( + self.tcx.finalize_expn( + invoc_id, ext.expn_data( parent_scope.expansion, span, @@ -298,7 +296,6 @@ impl<'a, 'tcx> ResolverExpand for Resolver<'a, 'tcx> { def_id, def_id.map(|def_id| self.macro_def_scope(def_id).nearest_parent_mod()), ), - self.create_stable_hashing_context(), ); Ok(ext) diff --git a/compiler/rustc_span/src/hygiene.rs b/compiler/rustc_span/src/hygiene.rs index b219fde4da9a1..1e4b1de23516b 100644 --- a/compiler/rustc_span/src/hygiene.rs +++ b/compiler/rustc_span/src/hygiene.rs @@ -180,7 +180,9 @@ impl LocalExpnId { ExpnIndex::from_u32(self.as_u32()) } - pub fn fresh_empty() -> LocalExpnId { + /// Create a new expansions without any information. This method must not be used outside of + /// the resolver. + pub fn reserve_expn_id() -> LocalExpnId { HygieneData::with(|data| { let expn_id = data.local_expn_data.push(None); let _eid = data.local_expn_hashes.push(ExpnHash(Fingerprint::ZERO)); @@ -189,19 +191,51 @@ impl LocalExpnId { }) } - pub fn fresh(mut expn_data: ExpnData, ctx: impl HashStableContext) -> LocalExpnId { + /// This method is an implementation detail of `TyCtxt::create_expn`. + pub fn create_untracked_expn( + mut expn_data: ExpnData, + hash_extra: impl Hash + Copy, + ctx: impl HashStableContext, + disambiguation_map: &Lock>, + ) -> LocalExpnId { debug_assert_eq!(expn_data.parent.krate, LOCAL_CRATE); - let expn_hash = update_disambiguator(&mut expn_data, ctx); + let expn_hash = update_disambiguator(&mut expn_data, hash_extra, ctx, disambiguation_map); HygieneData::with(|data| { let expn_id = data.local_expn_data.push(Some(expn_data)); let _eid = data.local_expn_hashes.push(expn_hash); debug_assert_eq!(expn_id, _eid); - let _old_id = data.expn_hash_to_expn_id.insert(expn_hash, expn_id.to_expn_id()); - debug_assert!(_old_id.is_none()); + let old_id = data.expn_hash_to_expn_id.insert(expn_hash, expn_id.to_expn_id()); + if old_id.is_some() { + panic!("Hash collision while creating expansion. Cannot continue."); + } expn_id }) } + /// Implementation detail of `TyCtxt::finalize_expn`. + #[inline] + pub fn set_untracked_expn_data( + self, + mut expn_data: ExpnData, + hash_extra: impl Hash + Copy, + ctx: impl HashStableContext, + disambiguation_map: &Lock>, + ) { + debug_assert_eq!(expn_data.parent.krate, LOCAL_CRATE); + let expn_hash = update_disambiguator(&mut expn_data, hash_extra, ctx, disambiguation_map); + HygieneData::with(|data| { + let old_expn_data = &mut data.local_expn_data[self]; + assert!(old_expn_data.is_none(), "expansion data is reset for an expansion ID"); + *old_expn_data = Some(expn_data); + debug_assert_eq!(data.local_expn_hashes[self].0, Fingerprint::ZERO); + data.local_expn_hashes[self] = expn_hash; + let old_id = data.expn_hash_to_expn_id.insert(expn_hash, self.to_expn_id()); + if old_id.is_some() { + panic!("Hash collision while creating expansion. Cannot continue."); + } + }); + } + #[inline] pub fn expn_hash(self) -> ExpnHash { HygieneData::with(|data| data.local_expn_hash(self)) @@ -217,21 +251,6 @@ impl LocalExpnId { ExpnId { krate: LOCAL_CRATE, local_id: self.as_raw() } } - #[inline] - pub fn set_expn_data(self, mut expn_data: ExpnData, ctx: impl HashStableContext) { - debug_assert_eq!(expn_data.parent.krate, LOCAL_CRATE); - let expn_hash = update_disambiguator(&mut expn_data, ctx); - HygieneData::with(|data| { - let old_expn_data = &mut data.local_expn_data[self]; - assert!(old_expn_data.is_none(), "expansion data is reset for an expansion ID"); - *old_expn_data = Some(expn_data); - debug_assert_eq!(data.local_expn_hashes[self].0, Fingerprint::ZERO); - data.local_expn_hashes[self] = expn_hash; - let _old_id = data.expn_hash_to_expn_id.insert(expn_hash, self.to_expn_id()); - debug_assert!(_old_id.is_none()); - }); - } - #[inline] pub fn is_descendant_of(self, ancestor: LocalExpnId) -> bool { self.to_expn_id().is_descendant_of(ancestor.to_expn_id()) @@ -344,12 +363,6 @@ pub struct HygieneData { expn_hash_to_expn_id: UnhashMap, syntax_context_data: Vec, syntax_context_map: FxHashMap<(SyntaxContext, ExpnId, Transparency), SyntaxContext>, - /// Maps the `local_hash` of an `ExpnData` to the next disambiguator value. - /// This is used by `update_disambiguator` to keep track of which `ExpnData`s - /// would have collisions without a disambiguator. - /// The keys of this map are always computed with `ExpnData.disambiguator` - /// set to 0. - expn_data_disambiguators: FxHashMap, } impl HygieneData { @@ -378,7 +391,6 @@ impl HygieneData { dollar_crate_name: kw::DollarCrate, }], syntax_context_map: FxHashMap::default(), - expn_data_disambiguators: FxHashMap::default(), } } @@ -885,23 +897,6 @@ impl Span { )) }) } - - /// Reuses the span but adds information like the kind of the desugaring and features that are - /// allowed inside this span. - pub fn mark_with_reason( - self, - allow_internal_unstable: Option>, - reason: DesugaringKind, - edition: Edition, - ctx: impl HashStableContext, - ) -> Span { - let expn_data = ExpnData { - allow_internal_unstable, - ..ExpnData::default(ExpnKind::Desugaring(reason), self, edition, None, None) - }; - let expn_id = LocalExpnId::fresh(expn_data, ctx); - self.fresh_expansion(expn_id) - } } /// A subset of properties from both macro definition and macro call available through global data. @@ -1039,9 +1034,10 @@ impl ExpnData { } #[inline] - fn hash_expn(&self, ctx: &mut impl HashStableContext) -> Hash64 { + fn hash_expn(&self, hash_extra: impl Hash, ctx: &mut impl HashStableContext) -> Hash64 { let mut hasher = StableHasher::new(); self.hash_stable(ctx, &mut hasher); + hash_extra.hash(&mut hasher); hasher.finish() } } @@ -1255,8 +1251,10 @@ pub fn register_local_expn_id(data: ExpnData, hash: ExpnHash) -> ExpnId { let expn_id = expn_id.to_expn_id(); - let _old_id = hygiene_data.expn_hash_to_expn_id.insert(hash, expn_id); - debug_assert!(_old_id.is_none()); + let old_id = hygiene_data.expn_hash_to_expn_id.insert(hash, expn_id); + if old_id.is_some() { + panic!("Hash collision while creating expansion. Cannot continue."); + } expn_id }) } @@ -1275,8 +1273,10 @@ pub fn register_expn_id( debug_assert!(_old_data.is_none()); let _old_hash = hygiene_data.foreign_expn_hashes.insert(expn_id, hash); debug_assert!(_old_hash.is_none()); - let _old_id = hygiene_data.expn_hash_to_expn_id.insert(hash, expn_id); - debug_assert!(_old_id.is_none()); + let old_id = hygiene_data.expn_hash_to_expn_id.insert(hash, expn_id); + if old_id.is_some() { + panic!("Hash collision while creating expansion. Cannot continue."); + } }); expn_id } @@ -1460,36 +1460,40 @@ impl Decodable for SyntaxContext { /// `set_expn_data`). It is *not* called for foreign `ExpnId`s deserialized /// from another crate's metadata - since `ExpnHash` includes the stable crate id, /// collisions are only possible between `ExpnId`s within the same crate. -fn update_disambiguator(expn_data: &mut ExpnData, mut ctx: impl HashStableContext) -> ExpnHash { +fn update_disambiguator( + expn_data: &mut ExpnData, + hash_extra: impl Hash + Copy, + mut ctx: impl HashStableContext, + disambiguation_map: &Lock>, +) -> ExpnHash { // This disambiguator should not have been set yet. assert_eq!(expn_data.disambiguator, 0, "Already set disambiguator for ExpnData: {expn_data:?}"); assert_default_hashing_controls(&ctx, "ExpnData (disambiguator)"); - let mut expn_hash = expn_data.hash_expn(&mut ctx); + let mut expn_hash = expn_data.hash_expn(hash_extra, &mut ctx); + debug!(?expn_hash); - let disambiguator = HygieneData::with(|data| { + let disambiguator = { // If this is the first ExpnData with a given hash, then keep our // disambiguator at 0 (the default u32 value) - let disambig = data.expn_data_disambiguators.entry(expn_hash).or_default(); + let mut disambiguation_map = disambiguation_map.lock(); + let disambig = disambiguation_map.entry(expn_hash).or_default(); let disambiguator = *disambig; *disambig += 1; disambiguator - }); + }; if disambiguator != 0 { debug!("Set disambiguator for expn_data={:?} expn_hash={:?}", expn_data, expn_hash); expn_data.disambiguator = disambiguator; - expn_hash = expn_data.hash_expn(&mut ctx); + expn_hash = expn_data.hash_expn(hash_extra, &mut ctx); // Verify that the new disambiguator makes the hash unique - #[cfg(debug_assertions)] - HygieneData::with(|data| { - assert_eq!( - data.expn_data_disambiguators.get(&expn_hash), - None, - "Hash collision after disambiguator update!", - ); - }); + debug_assert_eq!( + disambiguation_map.lock().get(&expn_hash), + None, + "Hash collision after disambiguator update!", + ); } ExpnHash::new(ctx.def_path_hash(LOCAL_CRATE.as_def_id()).stable_crate_id(), expn_hash) diff --git a/src/librustdoc/passes/lint/check_code_block_syntax.rs b/src/librustdoc/passes/lint/check_code_block_syntax.rs index f489f5081daa2..e242db95bffce 100644 --- a/src/librustdoc/passes/lint/check_code_block_syntax.rs +++ b/src/librustdoc/passes/lint/check_code_block_syntax.rs @@ -7,7 +7,7 @@ use rustc_errors::{ }; use rustc_parse::parse_stream_from_source_str; use rustc_session::parse::ParseSess; -use rustc_span::hygiene::{AstPass, ExpnData, ExpnKind, LocalExpnId}; +use rustc_span::hygiene::{AstPass, ExpnData, ExpnKind}; use rustc_span::source_map::{FilePathMapping, SourceMap}; use rustc_span::{FileName, InnerSpan, DUMMY_SP}; @@ -47,7 +47,7 @@ fn check_rust_syntax( let edition = code_block.lang_string.edition.unwrap_or_else(|| cx.tcx.sess.edition()); let expn_data = ExpnData::default(ExpnKind::AstPass(AstPass::TestHarness), DUMMY_SP, edition, None, None); - let expn_id = cx.tcx.with_stable_hashing_context(|hcx| LocalExpnId::fresh(expn_data, hcx)); + let expn_id = cx.tcx.create_expn(expn_data); let span = DUMMY_SP.fresh_expansion(expn_id); let is_empty = rustc_driver::catch_fatal_errors(|| {