Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
ab3271f
Simplify the creation of synthetic HIR.
cjgillot May 3, 2026
8ef0219
Remove `with_deps` closure.
nnethercote Mar 31, 2026
baaab5c
Improve comment.
nnethercote Mar 31, 2026
57e0d9d
Clarify comments on `TaskDeps`.
nnethercote Mar 31, 2026
0f43788
Do not cache `lints_that_dont_need_to_run` across sessions
qaijuang May 5, 2026
c834e9f
resolve: Remove `MacroData`
petrochenkov May 6, 2026
503960c
resolve: Avoid some `Arc` cloning with syntax extensions
petrochenkov May 7, 2026
024032e
Rename the unstable integer `extend` function to `widen`
joshtriplett May 8, 2026
e35da4e
turn some long-deprecated options into errors
RalfJung Mar 28, 2026
bb4615d
adjust tests for these removed features
RalfJung Mar 28, 2026
9af2553
remove no-longer-existing options from codegen-options docs
RalfJung Mar 28, 2026
d42a92b
Reject outer attributes on `cfg_select` branches
qaijuang May 8, 2026
abafa65
Rollup merge of #156236 - petrochenkov:nomacdata, r=chenyukang
JonathanBrouwer May 8, 2026
bc8c0ed
Rollup merge of #156298 - joshtriplett:extend-to-widen, r=nia-e
JonathanBrouwer May 8, 2026
c6fbd9f
Rollup merge of #154498 - RalfJung:option-deprecations, r=fmease
JonathanBrouwer May 8, 2026
6133b7e
Rollup merge of #155734 - qaijuang:cfg-select-doc-comment, r=Jonathan…
JonathanBrouwer May 8, 2026
a71746c
Rollup merge of #156123 - cjgillot:synthetic-hir, r=JonathanBrouwer
JonathanBrouwer May 8, 2026
91d4f8b
Rollup merge of #156175 - nnethercote:dep_graph-cleanups, r=adwinwhite
JonathanBrouwer May 8, 2026
565ee37
Rollup merge of #156214 - qaijuang:fix-lints-that-dont-need-to-run-in…
JonathanBrouwer May 8, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 29 additions & 1 deletion compiler/rustc_attr_parsing/src/attributes/cfg_select.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ use rustc_ast::token::Token;
use rustc_ast::tokenstream::TokenStream;
use rustc_ast::{AttrStyle, NodeId, token};
use rustc_data_structures::fx::FxHashMap;
use rustc_errors::Diagnostic;
use rustc_errors::{Diagnostic, MultiSpan};
use rustc_feature::{AttributeTemplate, Features};
use rustc_hir::attrs::CfgEntry;
use rustc_hir::{AttrPath, Target};
Expand Down Expand Up @@ -76,8 +76,11 @@ pub fn parse_cfg_select(
lint_node_id: NodeId,
) -> Result<CfgSelectBranches, ErrorGuaranteed> {
let mut branches = CfgSelectBranches::default();
let mut branch_attr_error: Option<ErrorGuaranteed> = None;

while p.token != token::Eof {
reject_branch_outer_attrs(p, &mut branch_attr_error)?;

if p.eat_keyword(exp!(Underscore)) {
let underscore = p.prev_token;
p.expect(exp!(FatArrow)).map_err(|e| e.emit())?;
Expand Down Expand Up @@ -131,6 +134,10 @@ pub fn parse_cfg_select(
}
}

if let Some(guar) = branch_attr_error {
return Err(guar);
}

let it = branches
.reachable
.iter()
Expand All @@ -143,6 +150,27 @@ pub fn parse_cfg_select(
Ok(branches)
}

fn reject_branch_outer_attrs(
p: &mut Parser<'_>,
branch_attr_error: &mut Option<ErrorGuaranteed>,
) -> Result<(), ErrorGuaranteed> {
let Some(spans) = p.parse_cfg_select_branch_outer_attrs().map_err(|e| e.emit())? else {
return Ok(());
};

for (spans, msg) in [
(spans.doc_comments, "doc comments are not allowed on `cfg_select` branches"),
(spans.attrs, "attributes are not allowed on `cfg_select` branches"),
] {
if !spans.is_empty() {
branch_attr_error
.get_or_insert(p.dcx().struct_span_err(MultiSpan::from_spans(spans), msg).emit());
}
}

Ok(())
}

fn lint_unreachable(
p: &mut Parser<'_>,
predicates: impl Iterator<Item = CfgSelectPredicate>,
Expand Down
20 changes: 13 additions & 7 deletions compiler/rustc_expand/src/mbe/macro_rules.rs
Original file line number Diff line number Diff line change
Expand Up @@ -170,6 +170,7 @@ pub struct MacroRulesMacroExpander {
transparency: Transparency,
kinds: MacroKinds,
rules: Vec<MacroRule>,
macro_rules: bool,
}

impl MacroRulesMacroExpander {
Expand All @@ -189,6 +190,14 @@ impl MacroRulesMacroExpander {
self.kinds
}

pub fn nrules(&self) -> usize {
self.rules.len()
}

pub fn is_macro_rules(&self) -> bool {
self.macro_rules
}

pub fn expand_derive(
&self,
cx: &mut ExtCtxt<'_>,
Expand Down Expand Up @@ -714,13 +723,12 @@ pub fn compile_declarative_macro(
span: Span,
node_id: NodeId,
edition: Edition,
) -> (SyntaxExtension, usize) {
) -> SyntaxExtension {
let mk_syn_ext = |kind| {
let is_local = is_defined_in_current_crate(node_id);
SyntaxExtension::new(sess, kind, span, Vec::new(), edition, ident.name, attrs, is_local)
};
let dummy_syn_ext =
|guar| (mk_syn_ext(SyntaxExtensionKind::Bang(Arc::new(DummyBang(guar)))), 0);
let dummy_syn_ext = |guar| mk_syn_ext(SyntaxExtensionKind::Bang(Arc::new(DummyBang(guar))));

let macro_rules = macro_def.macro_rules;
let exp_sep = if macro_rules { exp!(Semi) } else { exp!(Comma) };
Expand Down Expand Up @@ -857,9 +865,6 @@ pub fn compile_declarative_macro(
return dummy_syn_ext(guar);
}

// Return the number of rules for unused rule linting, if this is a local macro.
let nrules = if is_defined_in_current_crate(node_id) { rules.len() } else { 0 };

let on_unmatch_args = find_attr!(
attrs,
OnUnmatchArgs { directive, .. } => directive.clone()
Expand All @@ -875,8 +880,9 @@ pub fn compile_declarative_macro(
on_unmatch_args,
transparency,
rules,
macro_rules,
};
(mk_syn_ext(SyntaxExtensionKind::MacroRules(Arc::new(exp))), nrules)
mk_syn_ext(SyntaxExtensionKind::MacroRules(Arc::new(exp)))
}

fn check_no_eof(sess: &Session, p: &Parser<'_>, msg: &'static str) -> Option<ErrorGuaranteed> {
Expand Down
14 changes: 14 additions & 0 deletions compiler/rustc_hir/src/hir.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1595,6 +1595,20 @@ impl<'tcx> OwnerNodes<'tcx> {
// Indexing must ensure it is an OwnerNode.
self.nodes[ItemLocalId::ZERO].node.as_owner().unwrap()
}

/// Return an instance of `OwnerNodes` suitable for definitions that have no corresponding AST.
pub fn synthetic() -> OwnerNodes<'tcx> {
OwnerNodes {
// There is no reason to bother computing a hash for a synthetic body.
// Just use a constant value.
opt_hash_including_bodies: Some(Fingerprint::ZERO),
nodes: IndexVec::from_elem_n(
ParentedNode { parent: ItemLocalId::INVALID, node: OwnerNode::Synthetic.into() },
1,
),
bodies: SortedMap::new(),
}
}
}

impl fmt::Debug for OwnerNodes<'_> {
Expand Down
3 changes: 0 additions & 3 deletions compiler/rustc_interface/src/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -578,19 +578,16 @@ fn test_codegen_options_tracking_hash() {

// Make sure that changing an [UNTRACKED] option leaves the hash unchanged.
// tidy-alphabetical-start
untracked!(ar, String::from("abc"));
untracked!(codegen_units, Some(42));
untracked!(default_linker_libraries, true);
untracked!(dlltool, Some(PathBuf::from("custom_dlltool.exe")));
untracked!(extra_filename, String::from("extra-filename"));
untracked!(incremental, Some(String::from("abc")));
untracked!(inline_threshold, Some(0xf007ba11));
// `link_arg` is omitted because it just forwards to `link_args`.
untracked!(link_args, vec![String::from("abc"), String::from("def")]);
untracked!(link_self_contained, LinkSelfContained::on());
untracked!(linker, Some(PathBuf::from("linker")));
untracked!(linker_flavor, Some(LinkerFlavorCli::Gcc));
untracked!(no_stack_check, true);
untracked!(remark, Passes::Some(vec![String::from("pass1"), String::from("pass2")]));
untracked!(rpath, true);
untracked!(save_temps, true);
Expand Down
24 changes: 12 additions & 12 deletions compiler/rustc_middle/src/dep_graph/graph.rs
Original file line number Diff line number Diff line change
Expand Up @@ -331,16 +331,15 @@ impl DepGraphData {
format!("forcing query with already existing `DepNode`: {dep_node:?}")
});

let with_deps = |task_deps| with_deps(task_deps, op);
let (result, edges) = if tcx.is_eval_always(dep_node.kind) {
(with_deps(TaskDepsRef::EvalAlways), EdgesVec::new())
(with_deps(TaskDepsRef::EvalAlways, op), EdgesVec::new())
} else {
let task_deps = Lock::new(TaskDeps::new(
#[cfg(debug_assertions)]
Some(dep_node),
0,
));
(with_deps(TaskDepsRef::Allow(&task_deps)), task_deps.into_inner().reads)
(with_deps(TaskDepsRef::Allow(&task_deps), op), task_deps.into_inner().reads)
};

let dep_node_index =
Expand Down Expand Up @@ -396,10 +395,10 @@ impl DepGraphData {
}
_ => {
// The dep node indices are hashed here instead of hashing the dep nodes of the
// dependencies. These indices may refer to different nodes per session, but this isn't
// a problem here because we that ensure the final dep node hash is per session only by
// combining it with the per session random number `anon_id_seed`. This hash only need
// to map the dependencies to a single value on a per session basis.
// dependencies. These indices may refer to different nodes per session, but this
// isn't a problem here because we that ensure the final dep node hash is per
// session only by combining it with the per session `anon_id_seed`. This hash only
// need to map the dependencies to a single value on a per session basis.
let mut hasher = StableHasher::new();
reads.hash(&mut hasher);

Expand Down Expand Up @@ -1223,13 +1222,14 @@ pub struct TaskDeps {
#[cfg(debug_assertions)]
node: Option<DepNode>,

/// A vector of `DepNodeIndex`, basically.
/// A vector of `DepNodeIndex`, basically. Contains no duplicates.
reads: EdgesVec,

/// When adding new edges to `reads` in `DepGraph::read_index` we need to determine if the edge
/// has been seen before. If the number of elements in `reads` is small, we just do a linear
/// scan. If the number is higher, a hashset has better perf. This field is that hashset. It's
/// only used if the number of elements in `reads` exceeds `LINEAR_SCAN_MAX`.
/// When adding a new edge to `reads` in `DepGraph::read_index` we must determine if the edge
/// has been seen before. We just do a linear scan of `reads` if its length is less than or
/// equal to `LINEAR_SCAN_MAX`. Otherwise, we use this hashset for better performance. Note:
/// `reads` is always the canonical edges representation; this field is just to speed up the
/// seen-before test.
read_set: FxHashSet<DepNodeIndex>,
}

Expand Down
3 changes: 3 additions & 0 deletions compiler/rustc_middle/src/queries.rs
Original file line number Diff line number Diff line change
Expand Up @@ -565,6 +565,9 @@ rustc_queries! {

query lints_that_dont_need_to_run(_: ()) -> &'tcx UnordSet<LintId> {
arena_cache
// This depends on the lint store, which includes internal lints when the
// untracked `-Zunstable-options` flag is set.
eval_always
desc { "Computing all lints that are explicitly enabled or with a default level greater than Allow" }
}

Expand Down
19 changes: 2 additions & 17 deletions compiler/rustc_middle/src/ty/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -627,23 +627,8 @@ impl<'tcx> TyCtxtFeed<'tcx, LocalDefId> {
// Fills in all the important parts needed by HIR queries
pub fn feed_hir(&self) {
self.local_def_id_to_hir_id(HirId::make_owner(self.def_id()));

let node = hir::OwnerNode::Synthetic;
let bodies = Default::default();
let attrs = hir::AttributeMap::EMPTY;

let rustc_middle::hir::Hashes { opt_hash_including_bodies, .. } =
self.tcx.hash_owner_nodes(node, &bodies, &attrs.map, attrs.define_opaque);
let node = node.into();
self.opt_hir_owner_nodes(Some(self.tcx.arena.alloc(hir::OwnerNodes {
opt_hash_including_bodies,
nodes: IndexVec::from_elem_n(
hir::ParentedNode { parent: hir::ItemLocalId::INVALID, node },
1,
),
bodies,
})));
self.feed_owner_id().hir_attr_map(attrs);
self.opt_hir_owner_nodes(Some(self.tcx.arena.alloc(hir::OwnerNodes::synthetic())));
self.feed_owner_id().hir_attr_map(hir::AttributeMap::EMPTY);
}
}

Expand Down
38 changes: 37 additions & 1 deletion compiler/rustc_parse/src/parser/cfg_select.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,18 @@
use rustc_ast::token;
use rustc_ast::tokenstream::{TokenStream, TokenTree};
use rustc_ast::util::classify;
use rustc_ast::{AttrKind, token};
use rustc_errors::PResult;
use rustc_span::Span;

use crate::exp;
use crate::parser::{AttrWrapper, ForceCollect, Parser, Restrictions, Trailing, UsePreAttrPos};

#[derive(Default)]
pub struct CfgSelectBranchAttrSpans {
pub attrs: Vec<Span>,
pub doc_comments: Vec<Span>,
}

impl<'a> Parser<'a> {
/// Parses a `TokenTree` consisting either of `{ /* ... */ }` optionally followed by a comma
/// (and strip the braces and the optional comma) or an expression followed by a comma
Expand Down Expand Up @@ -36,4 +43,33 @@ impl<'a> Parser<'a> {
}
Ok(TokenStream::from_ast(&expr))
}

/// Parses outer attributes before a `cfg_select!` branch for recovery.
pub fn parse_cfg_select_branch_outer_attrs(
&mut self,
) -> PResult<'a, Option<CfgSelectBranchAttrSpans>> {
let attrs = self.parse_outer_attributes()?;
if attrs.is_empty() {
return Ok(None);
}

let mut spans = CfgSelectBranchAttrSpans::default();
for attr in attrs.take_for_recovery(self.psess) {
match attr.kind {
AttrKind::Normal(..) => spans.attrs.push(attr.span),
// `parse_outer_attributes` already emitted E0753 for inner doc comments before
// recovering them as outer doc-comment attributes.
AttrKind::DocComment(comment_kind, _)
if self.span_to_snippet(attr.span).ok().is_some_and(
|snippet| match comment_kind {
token::CommentKind::Line => snippet.starts_with("//!"),
token::CommentKind::Block => snippet.starts_with("/*!"),
},
) => {}
AttrKind::DocComment(..) => spans.doc_comments.push(attr.span),
}
}

Ok(Some(spans))
}
}
32 changes: 16 additions & 16 deletions compiler/rustc_resolve/src/build_reduced_graph.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ use rustc_ast::{
TyAlias,
};
use rustc_attr_parsing::AttributeParser;
use rustc_expand::base::ResolverExpand;
use rustc_expand::base::{ResolverExpand, SyntaxExtension, SyntaxExtensionKind};
use rustc_hir::Attribute;
use rustc_hir::attrs::{AttributeKind, MacroUseArgs};
use rustc_hir::def::{self, *};
Expand All @@ -37,9 +37,8 @@ use crate::macros::{MacroRulesDecl, MacroRulesScope, MacroRulesScopeRef};
use crate::ref_mut::CmCell;
use crate::{
BindingKey, Decl, DeclData, DeclKind, DelayedVisResolutionError, ExternModule,
ExternPreludeEntry, Finalize, IdentKey, LocalModule, MacroData, Module, ModuleKind,
ModuleOrUniformRoot, ParentScope, PathResult, Res, Resolver, Segment, SyntaxExtension, Used,
VisResolutionError, errors,
ExternPreludeEntry, Finalize, IdentKey, LocalModule, Module, ModuleKind, ModuleOrUniformRoot,
ParentScope, PathResult, Res, Resolver, Segment, Used, VisResolutionError, errors,
};

impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
Expand Down Expand Up @@ -208,28 +207,28 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
}

/// Gets the `SyntaxExtension` corresponding to `res`.
pub(crate) fn get_macro(&self, res: Res) -> Option<&Arc<SyntaxExtension>> {
pub(crate) fn get_macro(&self, res: Res) -> Option<&'ra Arc<SyntaxExtension>> {
match res {
Res::Def(DefKind::Macro(..), def_id) => Some(&self.get_macro_by_def_id(def_id).ext),
Res::NonMacroAttr(_) => Some(&self.non_macro_attr),
Res::Def(DefKind::Macro(..), def_id) => Some(self.get_macro_by_def_id(def_id)),
Res::NonMacroAttr(_) => Some(self.non_macro_attr),
_ => None,
}
}

pub(crate) fn get_macro_by_def_id(&self, def_id: DefId) -> &'ra MacroData {
pub(crate) fn get_macro_by_def_id(&self, def_id: DefId) -> &'ra Arc<SyntaxExtension> {
// Local macros are always compiled.
match def_id.as_local() {
Some(local_def_id) => self.local_macro_map[&local_def_id],
None => *self.extern_macro_map.borrow_mut().entry(def_id).or_insert_with(|| {
None => self.extern_macro_map.borrow_mut().entry(def_id).or_insert_with(|| {
let loaded_macro = self.cstore().load_macro_untracked(self.tcx, def_id);
let macro_data = match loaded_macro {
let ext = match loaded_macro {
LoadedMacro::MacroDef { def, ident, attrs, span, edition } => {
self.compile_macro(&def, ident, &attrs, span, ast::DUMMY_NODE_ID, edition)
}
LoadedMacro::ProcMacro(ext) => MacroData::new(Arc::new(ext)),
LoadedMacro::ProcMacro(ext) => ext,
};

self.arenas.alloc_macro(macro_data)
self.arenas.alloc_macro(ext)
}),
}
}
Expand Down Expand Up @@ -1277,8 +1276,10 @@ impl<'a, 'ra, 'tcx> DefCollector<'a, 'ra, 'tcx> {
fn insert_unused_macro(&mut self, ident: Ident, def_id: LocalDefId, node_id: NodeId) {
if !ident.as_str().starts_with('_') {
self.r.unused_macros.insert(def_id, (node_id, ident));
let nrules = self.r.local_macro_map[&def_id].nrules;
self.r.unused_macro_rules.insert(node_id, (def_id, DenseBitSet::new_filled(nrules)));
if let SyntaxExtensionKind::MacroRules(mr) = &self.r.local_macro_map[&def_id].kind {
let value = (def_id, DenseBitSet::new_filled(mr.nrules()));
self.r.unused_macro_rules.insert(node_id, value);
}
}
}

Expand All @@ -1299,8 +1300,7 @@ impl<'a, 'ra, 'tcx> DefCollector<'a, 'ra, 'tcx> {
Some((macro_kind, ident, span)) => {
let macro_kinds = macro_kind.into();
let res = Res::Def(DefKind::Macro(macro_kinds), def_id.to_def_id());
let macro_data = MacroData::new(self.r.dummy_ext(macro_kind));
self.r.new_local_macro(def_id, macro_data);
self.r.local_macro_map.insert(def_id, self.r.dummy_ext(macro_kind));
self.r.proc_macro_stubs.insert(def_id);
(res, ident, span, false)
}
Expand Down
Loading
Loading