From ab3271f8ea8b45366627931a59b5fc0df683d95d Mon Sep 17 00:00:00 2001 From: Camille Gillot Date: Sun, 3 May 2026 22:58:16 +0000 Subject: [PATCH 01/12] Simplify the creation of synthetic HIR. --- compiler/rustc_hir/src/hir.rs | 14 ++++++++++++++ compiler/rustc_middle/src/ty/context.rs | 19 ++----------------- 2 files changed, 16 insertions(+), 17 deletions(-) diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs index 2f18b09cf1ae8..7747d9920a321 100644 --- a/compiler/rustc_hir/src/hir.rs +++ b/compiler/rustc_hir/src/hir.rs @@ -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<'_> { diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index 6c68a83f9357a..34130a4813b61 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -623,23 +623,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); } } From 8ef02190911975fdae692fd18c7cc625929a7461 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Tue, 31 Mar 2026 20:58:10 +1100 Subject: [PATCH 02/12] Remove `with_deps` closure. The code is simpler with it gone. --- compiler/rustc_middle/src/dep_graph/graph.rs | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/compiler/rustc_middle/src/dep_graph/graph.rs b/compiler/rustc_middle/src/dep_graph/graph.rs index a219809541cc1..2d0d24153351e 100644 --- a/compiler/rustc_middle/src/dep_graph/graph.rs +++ b/compiler/rustc_middle/src/dep_graph/graph.rs @@ -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 = From baaab5c6637add082eced59f49faa6a16198ac2d Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Tue, 31 Mar 2026 20:58:26 +1100 Subject: [PATCH 03/12] Improve comment. By removing "random number", which is no longer true. And also wrapping the overly long lines. --- compiler/rustc_middle/src/dep_graph/graph.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/compiler/rustc_middle/src/dep_graph/graph.rs b/compiler/rustc_middle/src/dep_graph/graph.rs index 2d0d24153351e..c75ebd6d81b2d 100644 --- a/compiler/rustc_middle/src/dep_graph/graph.rs +++ b/compiler/rustc_middle/src/dep_graph/graph.rs @@ -395,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); From 57e0d9dc5bb91532f9560239759030be834e12ed Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Tue, 31 Mar 2026 21:11:50 +1100 Subject: [PATCH 04/12] Clarify comments on `TaskDeps`. To make clear some things I wasn't sure about. --- compiler/rustc_middle/src/dep_graph/graph.rs | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/compiler/rustc_middle/src/dep_graph/graph.rs b/compiler/rustc_middle/src/dep_graph/graph.rs index c75ebd6d81b2d..a042e2eea5919 100644 --- a/compiler/rustc_middle/src/dep_graph/graph.rs +++ b/compiler/rustc_middle/src/dep_graph/graph.rs @@ -1222,13 +1222,14 @@ pub struct TaskDeps { #[cfg(debug_assertions)] node: Option, - /// 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, } From 0f437887c6ed84e0ce80ec233164dd2a91deb618 Mon Sep 17 00:00:00 2001 From: Qai Juang <237468078+qaijuang@users.noreply.github.com> Date: Tue, 5 May 2026 19:17:53 -0400 Subject: [PATCH 05/12] Do not cache `lints_that_dont_need_to_run` across sessions --- compiler/rustc_middle/src/queries.rs | 3 +++ tests/incremental/commandline-args.rs | 7 ++++++- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/compiler/rustc_middle/src/queries.rs b/compiler/rustc_middle/src/queries.rs index f0c367beefd65..d4cbe7c15cec7 100644 --- a/compiler/rustc_middle/src/queries.rs +++ b/compiler/rustc_middle/src/queries.rs @@ -566,6 +566,9 @@ rustc_queries! { query lints_that_dont_need_to_run(_: ()) -> &'tcx UnordSet { 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" } } diff --git a/tests/incremental/commandline-args.rs b/tests/incremental/commandline-args.rs index eb7c8b6daf05d..b5ea59688d85a 100644 --- a/tests/incremental/commandline-args.rs +++ b/tests/incremental/commandline-args.rs @@ -1,7 +1,7 @@ // Test that changing a tracked commandline argument invalidates // the cache while changing an untracked one doesn't. -//@ revisions:rpass1 rpass2 rpass3 rpass4 +//@ revisions:rpass1 rpass2 rpass3 rpass4 rpass5 //@ compile-flags: -Z query-dep-graph #![feature(rustc_attrs)] @@ -9,6 +9,7 @@ #![rustc_partition_codegened(module="commandline_args", cfg="rpass2")] #![rustc_partition_reused(module="commandline_args", cfg="rpass3")] #![rustc_partition_codegened(module="commandline_args", cfg="rpass4")] +#![rustc_partition_reused(module="commandline_args", cfg="rpass5")] // Between revisions 1 and 2, we are changing the debuginfo-level, which should // invalidate the cache. Between revisions 2 and 3, we are adding `--diagnostic-width` @@ -18,6 +19,10 @@ //@[rpass2] compile-flags: -C debuginfo=2 //@[rpass3] compile-flags: -C debuginfo=2 --diagnostic-width=80 //@[rpass4] compile-flags: -C debuginfo=2 --diagnostic-width=80 --remap-path-prefix=/home/bors/r=src +// Regression test for https://github.com/rust-lang/rust/issues/156182. +// `-Zunstable-options` enables internal lints, so the lint store changes without +// changing the incremental command-line hash. +//@[rpass5] compile-flags: -C debuginfo=2 --diagnostic-width=80 --remap-path-prefix=/home/bors/r=src -Zunstable-options //@ ignore-backends: gcc pub fn main() { From c834e9fcbdadc829333f17037acaf3d75c725374 Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Wed, 6 May 2026 13:38:10 +0300 Subject: [PATCH 06/12] resolve: Remove `MacroData` All the necessary data can be taken from `SyntaxExtension` instead. --- compiler/rustc_expand/src/mbe/macro_rules.rs | 20 ++++++++----- .../rustc_resolve/src/build_reduced_graph.rs | 28 ++++++++--------- compiler/rustc_resolve/src/def_collector.rs | 13 ++++---- compiler/rustc_resolve/src/diagnostics.rs | 8 ++--- compiler/rustc_resolve/src/ident.rs | 2 +- compiler/rustc_resolve/src/imports.rs | 5 +++- compiler/rustc_resolve/src/lib.rs | 30 +++++++------------ compiler/rustc_resolve/src/macros.rs | 13 ++++---- 8 files changed, 60 insertions(+), 59 deletions(-) diff --git a/compiler/rustc_expand/src/mbe/macro_rules.rs b/compiler/rustc_expand/src/mbe/macro_rules.rs index cb22ad136645b..5bf50804ab1e8 100644 --- a/compiler/rustc_expand/src/mbe/macro_rules.rs +++ b/compiler/rustc_expand/src/mbe/macro_rules.rs @@ -170,6 +170,7 @@ pub struct MacroRulesMacroExpander { transparency: Transparency, kinds: MacroKinds, rules: Vec, + macro_rules: bool, } impl MacroRulesMacroExpander { @@ -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<'_>, @@ -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) }; @@ -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() @@ -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 { diff --git a/compiler/rustc_resolve/src/build_reduced_graph.rs b/compiler/rustc_resolve/src/build_reduced_graph.rs index c37838706301a..f96fcb454a174 100644 --- a/compiler/rustc_resolve/src/build_reduced_graph.rs +++ b/compiler/rustc_resolve/src/build_reduced_graph.rs @@ -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, *}; @@ -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> { @@ -210,26 +209,26 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { /// Gets the `SyntaxExtension` corresponding to `res`. pub(crate) fn get_macro(&self, res: Res) -> Option<&Arc> { match res { - Res::Def(DefKind::Macro(..), def_id) => Some(&self.get_macro_by_def_id(def_id).ext), + 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 { // 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(Arc::new(ext)) }), } } @@ -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); + } } } @@ -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.new_local_macro(def_id, self.r.dummy_ext(macro_kind)); self.r.proc_macro_stubs.insert(def_id); (res, ident, span, false) } diff --git a/compiler/rustc_resolve/src/def_collector.rs b/compiler/rustc_resolve/src/def_collector.rs index 0040ddbf5e24a..b18aa1a233e8e 100644 --- a/compiler/rustc_resolve/src/def_collector.rs +++ b/compiler/rustc_resolve/src/def_collector.rs @@ -1,4 +1,5 @@ use std::mem; +use std::sync::Arc; use rustc_ast::visit::FnKind; use rustc_ast::*; @@ -117,7 +118,7 @@ impl<'a, 'ra, 'tcx> visit::Visitor<'a> for DefCollector<'a, 'ra, 'tcx> { fn visit_item(&mut self, i: &'a Item) { // Pick the def data. This need not be unique, but the more // information we encapsulate into, the better - let mut opt_macro_data = None; + let mut opt_syn_ext = None; let def_kind = match &i.kind { ItemKind::Impl(i) => DefKind::Impl { of_trait: i.of_trait.is_some() }, ItemKind::ForeignMod(..) => DefKind::ForeignMod, @@ -165,9 +166,9 @@ impl<'a, 'ra, 'tcx> visit::Visitor<'a> for DefCollector<'a, 'ra, 'tcx> { }, ); - let macro_data = self.r.compile_macro(def, *ident, &attrs, i.span, i.id, edition); - let macro_kinds = macro_data.ext.macro_kinds(); - opt_macro_data = Some(macro_data); + let ext = self.r.compile_macro(def, *ident, &attrs, i.span, i.id, edition); + let macro_kinds = ext.macro_kinds(); + opt_syn_ext = Some(ext); DefKind::Macro(macro_kinds) } ItemKind::GlobalAsm(..) => DefKind::GlobalAsm, @@ -185,8 +186,8 @@ impl<'a, 'ra, 'tcx> visit::Visitor<'a> for DefCollector<'a, 'ra, 'tcx> { }; let feed = self.create_def(i.id, i.kind.ident().map(|ident| ident.name), def_kind, i.span); - if let Some(macro_data) = opt_macro_data { - self.r.new_local_macro(feed.def_id(), macro_data); + if let Some(ext) = opt_syn_ext { + self.r.new_local_macro(feed.def_id(), Arc::new(ext)); } self.with_parent(feed.def_id(), |this| { diff --git a/compiler/rustc_resolve/src/diagnostics.rs b/compiler/rustc_resolve/src/diagnostics.rs index c082455380ce7..9cdf79ca57d87 100644 --- a/compiler/rustc_resolve/src/diagnostics.rs +++ b/compiler/rustc_resolve/src/diagnostics.rs @@ -1742,7 +1742,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { if let Some((def_id, unused_ident)) = unused_macro { let scope = self.local_macro_def_scopes[&def_id]; let parent_nearest = parent_scope.module.nearest_parent_mod(); - let unused_macro_kinds = self.local_macro_map[def_id].ext.macro_kinds(); + let unused_macro_kinds = self.local_macro_map[def_id].macro_kinds(); if !unused_macro_kinds.contains(macro_kind.into()) { match macro_kind { MacroKind::Bang => { @@ -1860,13 +1860,13 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { let mut all_attrs: UnordMap> = UnordMap::default(); // We're collecting these in a hashmap, and handle ordering the output further down. #[allow(rustc::potential_query_instability)] - for (def_id, data) in self + for (def_id, ext) in self .local_macro_map .iter() - .map(|(local_id, data)| (local_id.to_def_id(), data)) + .map(|(local_id, ext)| (local_id.to_def_id(), ext)) .chain(self.extern_macro_map.borrow().iter().map(|(id, d)| (*id, d))) { - for helper_attr in &data.ext.helper_attrs { + for helper_attr in &ext.helper_attrs { let item_name = self.tcx.item_name(def_id); all_attrs.entry(*helper_attr).or_default().push(item_name); if helper_attr == &ident.name { diff --git a/compiler/rustc_resolve/src/ident.rs b/compiler/rustc_resolve/src/ident.rs index 1c43ca431d8bf..b33b77d43999d 100644 --- a/compiler/rustc_resolve/src/ident.rs +++ b/compiler/rustc_resolve/src/ident.rs @@ -271,7 +271,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { // The macro is a proc macro derive && let Some(def_id) = module.expansion.expn_data().macro_def_id { - let ext = &self.get_macro_by_def_id(def_id).ext; + let ext = self.get_macro_by_def_id(def_id); if ext.builtin_name.is_none() && ext.macro_kinds() == MacroKinds::DERIVE && parent.expansion.outer_expn_is_descendant_of(**ctxt) diff --git a/compiler/rustc_resolve/src/imports.rs b/compiler/rustc_resolve/src/imports.rs index 1b9e5d2a2daa6..b16347af7ba0c 100644 --- a/compiler/rustc_resolve/src/imports.rs +++ b/compiler/rustc_resolve/src/imports.rs @@ -12,6 +12,7 @@ use rustc_errors::codes::*; use rustc_errors::{ Applicability, BufferedEarlyLint, Diagnostic, MultiSpan, pluralize, struct_span_code_err, }; +use rustc_expand::base::SyntaxExtensionKind; use rustc_hir::Attribute; use rustc_hir::attrs::AttributeKind; use rustc_hir::attrs::diagnostic::{CustomDiagnostic, Directive, FormatArgs}; @@ -1656,7 +1657,9 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { match decl.kind { // exclude decl_macro DeclKind::Def(Res::Def(DefKind::Macro(_), def_id)) - if self.get_macro_by_def_id(def_id).macro_rules => + if let SyntaxExtensionKind::MacroRules(mr) = + &self.get_macro_by_def_id(def_id).kind + && mr.is_macro_rules() => { err.subdiagnostic(ConsiderAddingMacroExport { span: decl.span }); err.subdiagnostic(ConsiderMarkingAsPubCrate { vis_span: import.vis_span }); diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs index 4352e10462901..be08dd445c680 100644 --- a/compiler/rustc_resolve/src/lib.rs +++ b/compiler/rustc_resolve/src/lib.rs @@ -1265,18 +1265,6 @@ struct DeriveData { has_derive_copy: bool, } -struct MacroData { - ext: Arc, - nrules: usize, - macro_rules: bool, -} - -impl MacroData { - fn new(ext: Arc) -> MacroData { - MacroData { ext, nrules: 0, macro_rules: false } - } -} - pub struct ResolverOutputs<'tcx> { pub global_ctxt: ResolverGlobalCtxt, pub ast_lowering: ResolverAstLowering<'tcx>, @@ -1396,9 +1384,9 @@ pub struct Resolver<'ra, 'tcx> { registered_tools: &'tcx RegisteredTools, macro_use_prelude: FxIndexMap>, /// Eagerly populated map of all local macro definitions. - local_macro_map: FxHashMap = default::fx_hash_map(), + local_macro_map: FxHashMap> = default::fx_hash_map(), /// Lazily populated cache of macro definitions loaded from external crates. - extern_macro_map: CacheRefCell>, + extern_macro_map: CacheRefCell>>, dummy_ext_bang: Arc, dummy_ext_derive: Arc, non_macro_attr: Arc, @@ -1520,7 +1508,7 @@ pub struct ResolverArenas<'ra> { imports: TypedArena>, name_resolutions: TypedArena>>, ast_paths: TypedArena, - macros: TypedArena, + macros: TypedArena>, dropless: DroplessArena, } @@ -1599,8 +1587,8 @@ impl<'ra> ResolverArenas<'ra> { fn alloc_ast_paths(&'ra self, paths: &[ast::Path]) -> &'ra [ast::Path] { self.ast_paths.alloc_from_iter(paths.iter().cloned()) } - fn alloc_macro(&'ra self, macro_data: MacroData) -> &'ra MacroData { - self.macros.alloc(macro_data) + fn alloc_macro(&'ra self, ext: Arc) -> &'ra Arc { + self.macros.alloc(ext) } fn alloc_pattern_spans(&'ra self, spans: impl Iterator) -> &'ra [Span] { self.dropless.alloc_from_iter(spans) @@ -1888,8 +1876,12 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { module } - fn new_local_macro(&mut self, def_id: LocalDefId, macro_data: MacroData) -> &'ra MacroData { - let mac = self.arenas.alloc_macro(macro_data); + fn new_local_macro( + &mut self, + def_id: LocalDefId, + ext: Arc, + ) -> &'ra Arc { + let mac = self.arenas.alloc_macro(ext); self.local_macro_map.insert(def_id, mac); mac } diff --git a/compiler/rustc_resolve/src/macros.rs b/compiler/rustc_resolve/src/macros.rs index d20907f53f66a..05874d76183e4 100644 --- a/compiler/rustc_resolve/src/macros.rs +++ b/compiler/rustc_resolve/src/macros.rs @@ -43,7 +43,7 @@ use crate::hygiene::Macros20NormalizedSyntaxContext; use crate::imports::Import; use crate::{ BindingKey, CacheCell, CmResolver, Decl, DeclKind, DeriveData, Determinacy, Finalize, IdentKey, - InvocationParent, MacroData, ModuleKind, ModuleOrUniformRoot, ParentScope, PathResult, Res, + InvocationParent, ModuleKind, ModuleOrUniformRoot, ParentScope, PathResult, Res, ResolutionError, Resolver, ScopeSet, Segment, Used, }; @@ -360,8 +360,8 @@ impl<'ra, 'tcx> ResolverExpand for Resolver<'ra, 'tcx> { if unused_arms.is_empty() { continue; } - let m = &self.local_macro_map[&def_id]; - let SyntaxExtensionKind::MacroRules(ref m) = m.ext.kind else { + let ext = self.local_macro_map[&def_id]; + let SyntaxExtensionKind::MacroRules(ref m) = ext.kind else { continue; }; for arm_i in unused_arms.iter() { @@ -1229,8 +1229,8 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { span: Span, node_id: NodeId, edition: Edition, - ) -> MacroData { - let (mut ext, mut nrules) = compile_declarative_macro( + ) -> SyntaxExtension { + let mut ext = compile_declarative_macro( self.tcx.sess, self.tcx.features(), macro_def, @@ -1247,13 +1247,12 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { // The macro is a built-in, replace its expander function // while still taking everything else from the source code. ext.kind = builtin_ext_kind.clone(); - nrules = 0; } else { self.dcx().emit_err(errors::CannotFindBuiltinMacroWithName { span, ident }); } } - MacroData { ext: Arc::new(ext), nrules, macro_rules: macro_def.macro_rules } + ext } fn path_accessible( From 503960c9a57b95352a00e257bc2c8cebdecdb927 Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Thu, 7 May 2026 15:29:52 +0300 Subject: [PATCH 07/12] resolve: Avoid some `Arc` cloning with syntax extensions Clone only on interface boundaries with `rustc_expand` --- .../rustc_resolve/src/build_reduced_graph.rs | 8 ++--- compiler/rustc_resolve/src/def_collector.rs | 3 +- compiler/rustc_resolve/src/lib.rs | 34 +++++++------------ compiler/rustc_resolve/src/macros.rs | 16 ++++----- 4 files changed, 25 insertions(+), 36 deletions(-) diff --git a/compiler/rustc_resolve/src/build_reduced_graph.rs b/compiler/rustc_resolve/src/build_reduced_graph.rs index f96fcb454a174..61da931df4d5d 100644 --- a/compiler/rustc_resolve/src/build_reduced_graph.rs +++ b/compiler/rustc_resolve/src/build_reduced_graph.rs @@ -207,10 +207,10 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { } /// Gets the `SyntaxExtension` corresponding to `res`. - pub(crate) fn get_macro(&self, res: Res) -> Option<&Arc> { + pub(crate) fn get_macro(&self, res: Res) -> Option<&'ra Arc> { match res { Res::Def(DefKind::Macro(..), def_id) => Some(self.get_macro_by_def_id(def_id)), - Res::NonMacroAttr(_) => Some(&self.non_macro_attr), + Res::NonMacroAttr(_) => Some(self.non_macro_attr), _ => None, } } @@ -228,7 +228,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { LoadedMacro::ProcMacro(ext) => ext, }; - self.arenas.alloc_macro(Arc::new(ext)) + self.arenas.alloc_macro(ext) }), } } @@ -1300,7 +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()); - self.r.new_local_macro(def_id, self.r.dummy_ext(macro_kind)); + 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) } diff --git a/compiler/rustc_resolve/src/def_collector.rs b/compiler/rustc_resolve/src/def_collector.rs index b18aa1a233e8e..b5f46052f03e3 100644 --- a/compiler/rustc_resolve/src/def_collector.rs +++ b/compiler/rustc_resolve/src/def_collector.rs @@ -1,5 +1,4 @@ use std::mem; -use std::sync::Arc; use rustc_ast::visit::FnKind; use rustc_ast::*; @@ -187,7 +186,7 @@ impl<'a, 'ra, 'tcx> visit::Visitor<'a> for DefCollector<'a, 'ra, 'tcx> { let feed = self.create_def(i.id, i.kind.ident().map(|ident| ident.name), def_kind, i.span); if let Some(ext) = opt_syn_ext { - self.r.new_local_macro(feed.def_id(), Arc::new(ext)); + self.r.local_macro_map.insert(feed.def_id(), self.r.arenas.alloc_macro(ext)); } self.with_parent(feed.def_id(), |this| { diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs index be08dd445c680..e5038f2d7f2b9 100644 --- a/compiler/rustc_resolve/src/lib.rs +++ b/compiler/rustc_resolve/src/lib.rs @@ -1387,9 +1387,9 @@ pub struct Resolver<'ra, 'tcx> { local_macro_map: FxHashMap> = default::fx_hash_map(), /// Lazily populated cache of macro definitions loaded from external crates. extern_macro_map: CacheRefCell>>, - dummy_ext_bang: Arc, - dummy_ext_derive: Arc, - non_macro_attr: Arc, + dummy_ext_bang: &'ra Arc, + dummy_ext_derive: &'ra Arc, + non_macro_attr: &'ra Arc, local_macro_def_scopes: FxHashMap> = default::fx_hash_map(), ast_transform_scopes: FxHashMap> = default::fx_hash_map(), unused_macros: FxIndexMap, @@ -1587,8 +1587,8 @@ impl<'ra> ResolverArenas<'ra> { fn alloc_ast_paths(&'ra self, paths: &[ast::Path]) -> &'ra [ast::Path] { self.ast_paths.alloc_from_iter(paths.iter().cloned()) } - fn alloc_macro(&'ra self, ext: Arc) -> &'ra Arc { - self.macros.alloc(ext) + fn alloc_macro(&'ra self, ext: SyntaxExtension) -> &'ra Arc { + self.macros.alloc(Arc::new(ext)) } fn alloc_pattern_spans(&'ra self, spans: impl Iterator) -> &'ra [Span] { self.dropless.alloc_from_iter(spans) @@ -1807,9 +1807,9 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { registered_tools, macro_use_prelude: Default::default(), extern_macro_map: Default::default(), - dummy_ext_bang: Arc::new(SyntaxExtension::dummy_bang(edition)), - dummy_ext_derive: Arc::new(SyntaxExtension::dummy_derive(edition)), - non_macro_attr: Arc::new(SyntaxExtension::non_macro_attr(edition)), + dummy_ext_bang: arenas.alloc_macro(SyntaxExtension::dummy_bang(edition)), + dummy_ext_derive: arenas.alloc_macro(SyntaxExtension::dummy_derive(edition)), + non_macro_attr: arenas.alloc_macro(SyntaxExtension::non_macro_attr(edition)), unused_macros: Default::default(), unused_macro_rules: Default::default(), single_segment_macro_resolutions: Default::default(), @@ -1876,16 +1876,6 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { module } - fn new_local_macro( - &mut self, - def_id: LocalDefId, - ext: Arc, - ) -> &'ra Arc { - let mac = self.arenas.alloc_macro(ext); - self.local_macro_map.insert(def_id, mac); - mac - } - fn next_node_id(&mut self) -> NodeId { let start = self.next_node_id; let next = start.as_u32().checked_add(1).expect("input too large; ran out of NodeIds"); @@ -1980,11 +1970,11 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { CStore::from_tcx_mut(self.tcx) } - fn dummy_ext(&self, macro_kind: MacroKind) -> Arc { + fn dummy_ext(&self, macro_kind: MacroKind) -> &'ra Arc { match macro_kind { - MacroKind::Bang => Arc::clone(&self.dummy_ext_bang), - MacroKind::Derive => Arc::clone(&self.dummy_ext_derive), - MacroKind::Attr => Arc::clone(&self.non_macro_attr), + MacroKind::Bang => self.dummy_ext_bang, + MacroKind::Derive => self.dummy_ext_derive, + MacroKind::Attr => self.non_macro_attr, } } diff --git a/compiler/rustc_resolve/src/macros.rs b/compiler/rustc_resolve/src/macros.rs index 05874d76183e4..f4464138ef1fc 100644 --- a/compiler/rustc_resolve/src/macros.rs +++ b/compiler/rustc_resolve/src/macros.rs @@ -335,7 +335,7 @@ impl<'ra, 'tcx> ResolverExpand for Resolver<'ra, 'tcx> { ) }); - Ok(ext) + Ok(Arc::clone(ext)) } fn record_macro_rule_usage(&mut self, id: NodeId, rule_i: usize) { @@ -404,7 +404,7 @@ impl<'ra, 'tcx> ResolverExpand for Resolver<'ra, 'tcx> { let parent_scope = self.invocation_parent_scopes[&expn_id]; for (i, resolution) in entry.resolutions.iter_mut().enumerate() { if resolution.exts.is_none() { - resolution.exts = Some( + resolution.exts = Some(Arc::clone( match self.cm().resolve_derive_macro_path( &resolution.path, &parent_scope, @@ -431,7 +431,7 @@ impl<'ra, 'tcx> ResolverExpand for Resolver<'ra, 'tcx> { return Err(Indeterminate); } }, - ); + )); } } // Sort helpers in a stable way independent from the derive resolution order. @@ -573,7 +573,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { deleg_impl: Option<(LocalDefId, Span)>, invoc_in_mod_inert_attr: Option, suggestion_span: Option, - ) -> Result<(Arc, Res), Indeterminate> { + ) -> Result<(&'ra Arc, Res), Indeterminate> { let (ext, res) = match self.cm().resolve_macro_or_delegation_path( path, kind, @@ -765,7 +765,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { parent_scope: &ParentScope<'ra>, force: bool, ignore_import: Option>, - ) -> Result<(Option>, Res), Determinacy> { + ) -> Result<(Option<&'r Arc>, Res), Determinacy> { self.resolve_macro_or_delegation_path( path, MacroKind::Derive, @@ -788,7 +788,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { invoc_in_mod_inert_attr: Option<(LocalDefId, NodeId)>, ignore_import: Option>, suggestion_span: Option, - ) -> Result<(Option>, Res), Determinacy> { + ) -> Result<(Option<&'ra Arc>, Res), Determinacy> { let path_span = ast_path.span; let mut path = Segment::from_path(ast_path); @@ -872,7 +872,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { Some((impl_def_id, star_span)) => match res { Res::Def(DefKind::Trait, def_id) => { let edition = self.tcx.sess.edition(); - Some(Arc::new(SyntaxExtension::glob_delegation( + Some(self.arenas.alloc_macro(SyntaxExtension::glob_delegation( def_id, impl_def_id, star_span, @@ -881,7 +881,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { } _ => None, }, - None => self.get_macro(res).map(Arc::clone), + None => self.get_macro(res), }; Ok((ext, res)) } From 024032e66b391eda3a66d9eaa5d6e470f32663da Mon Sep 17 00:00:00 2001 From: Josh Triplett Date: Thu, 7 May 2026 20:30:26 -0700 Subject: [PATCH 08/12] Rename the unstable integer `extend` function to `widen` MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This is consistent with our use of `widening` elsewhere. Suggested-by: Gabriel Bjørnager Jensen --- library/core/src/num/int_macros.rs | 38 +++++++++++++------------- library/core/src/num/traits.rs | 24 ++++++++-------- library/core/src/num/uint_macros.rs | 36 ++++++++++++------------ tests/ui/imports/issue-114682-3.stderr | 6 +--- 4 files changed, 50 insertions(+), 54 deletions(-) diff --git a/library/core/src/num/int_macros.rs b/library/core/src/num/int_macros.rs index deda734263ae4..bed73ddaec5b3 100644 --- a/library/core/src/num/int_macros.rs +++ b/library/core/src/num/int_macros.rs @@ -4036,14 +4036,14 @@ macro_rules! int_impl { /// # Examples /// /// ``` - /// #![feature(integer_extend_truncate)] + /// #![feature(integer_widen_truncate)] #[doc = concat!("assert_eq!(120i8, 120", stringify!($SelfT), ".truncate());")] #[doc = concat!("assert_eq!(-120i8, (-120", stringify!($SelfT), ").truncate());")] /// assert_eq!(120i8, 376i32.truncate()); /// ``` #[must_use = "this returns the truncated value and does not modify the original"] - #[unstable(feature = "integer_extend_truncate", issue = "154330")] - #[rustc_const_unstable(feature = "integer_extend_truncate", issue = "154330")] + #[unstable(feature = "integer_widen_truncate", issue = "154330")] + #[rustc_const_unstable(feature = "integer_widen_truncate", issue = "154330")] #[inline] pub const fn truncate(self) -> Target where Self: [const] traits::TruncateTarget @@ -4057,15 +4057,15 @@ macro_rules! int_impl { /// # Examples /// /// ``` - /// #![feature(integer_extend_truncate)] + /// #![feature(integer_widen_truncate)] #[doc = concat!("assert_eq!(120i8, 120", stringify!($SelfT), ".saturating_truncate());")] #[doc = concat!("assert_eq!(-120i8, (-120", stringify!($SelfT), ").saturating_truncate());")] /// assert_eq!(127i8, 376i32.saturating_truncate()); /// assert_eq!(-128i8, (-1000i32).saturating_truncate()); /// ``` #[must_use = "this returns the truncated value and does not modify the original"] - #[unstable(feature = "integer_extend_truncate", issue = "154330")] - #[rustc_const_unstable(feature = "integer_extend_truncate", issue = "154330")] + #[unstable(feature = "integer_widen_truncate", issue = "154330")] + #[rustc_const_unstable(feature = "integer_widen_truncate", issue = "154330")] #[inline] pub const fn saturating_truncate(self) -> Target where Self: [const] traits::TruncateTarget @@ -4079,15 +4079,15 @@ macro_rules! int_impl { /// # Examples /// /// ``` - /// #![feature(integer_extend_truncate)] + /// #![feature(integer_widen_truncate)] #[doc = concat!("assert_eq!(Some(120i8), 120", stringify!($SelfT), ".checked_truncate());")] #[doc = concat!("assert_eq!(Some(-120i8), (-120", stringify!($SelfT), ").checked_truncate());")] /// assert_eq!(None, 376i32.checked_truncate::()); /// assert_eq!(None, (-1000i32).checked_truncate::()); /// ``` #[must_use = "this returns the truncated value and does not modify the original"] - #[unstable(feature = "integer_extend_truncate", issue = "154330")] - #[rustc_const_unstable(feature = "integer_extend_truncate", issue = "154330")] + #[unstable(feature = "integer_widen_truncate", issue = "154330")] + #[rustc_const_unstable(feature = "integer_widen_truncate", issue = "154330")] #[inline] pub const fn checked_truncate(self) -> Option where Self: [const] traits::TruncateTarget @@ -4095,23 +4095,23 @@ macro_rules! int_impl { traits::TruncateTarget::internal_checked_truncate(self) } - /// Extend to an integer of the same size or larger, preserving its value. + /// Widen to an integer of the same size or larger, preserving its value. /// /// # Examples /// /// ``` - /// #![feature(integer_extend_truncate)] - #[doc = concat!("assert_eq!(120i128, 120i8.extend());")] - #[doc = concat!("assert_eq!(-120i128, (-120i8).extend());")] + /// #![feature(integer_widen_truncate)] + #[doc = concat!("assert_eq!(120i128, 120i8.widen());")] + #[doc = concat!("assert_eq!(-120i128, (-120i8).widen());")] /// ``` - #[must_use = "this returns the extended value and does not modify the original"] - #[unstable(feature = "integer_extend_truncate", issue = "154330")] - #[rustc_const_unstable(feature = "integer_extend_truncate", issue = "154330")] + #[must_use = "this returns the widened value and does not modify the original"] + #[unstable(feature = "integer_widen_truncate", issue = "154330")] + #[rustc_const_unstable(feature = "integer_widen_truncate", issue = "154330")] #[inline] - pub const fn extend(self) -> Target - where Self: [const] traits::ExtendTarget + pub const fn widen(self) -> Target + where Self: [const] traits::WidenTarget { - traits::ExtendTarget::internal_extend(self) + traits::WidenTarget::internal_widen(self) } } } diff --git a/library/core/src/num/traits.rs b/library/core/src/num/traits.rs index 92217a4817b49..08012ebf1adb4 100644 --- a/library/core/src/num/traits.rs +++ b/library/core/src/num/traits.rs @@ -3,7 +3,7 @@ /// Trait for types that this type can be truncated to #[unstable(feature = "num_internals", reason = "internal implementation detail", issue = "none")] -#[rustc_const_unstable(feature = "integer_extend_truncate", issue = "154330")] +#[rustc_const_unstable(feature = "integer_widen_truncate", issue = "154330")] pub const trait TruncateTarget: crate::sealed::Sealed { #[doc(hidden)] fn internal_truncate(self) -> Target; @@ -15,12 +15,12 @@ pub const trait TruncateTarget: crate::sealed::Sealed { fn internal_checked_truncate(self) -> Option; } -/// Trait for types that this type can be truncated to +/// Trait for types that this type can be widened to #[unstable(feature = "num_internals", reason = "internal implementation detail", issue = "none")] -#[rustc_const_unstable(feature = "integer_extend_truncate", issue = "154330")] -pub const trait ExtendTarget: crate::sealed::Sealed { +#[rustc_const_unstable(feature = "integer_widen_truncate", issue = "154330")] +pub const trait WidenTarget: crate::sealed::Sealed { #[doc(hidden)] - fn internal_extend(self) -> Target; + fn internal_widen(self) -> Target; } macro_rules! impl_truncate { @@ -40,7 +40,7 @@ macro_rules! impl_truncate { ); #[unstable(feature = "num_internals", reason = "internal implementation detail", issue = "none")] - #[rustc_const_unstable(feature = "integer_extend_truncate", issue = "154330")] + #[rustc_const_unstable(feature = "integer_widen_truncate", issue = "154330")] impl const TruncateTarget<$to> for $from { #[inline] fn internal_truncate(self) -> $to { @@ -70,12 +70,12 @@ macro_rules! impl_truncate { )+)*}; } -macro_rules! impl_extend { +macro_rules! impl_widen { ($($from:ty => $($to:ty),+;)*) => {$($( const _: () = assert!( size_of::<$from>() <= size_of::<$to>(), concat!( - "cannot extend ", + "cannot widen ", stringify!($from), " to ", stringify!($to), @@ -87,9 +87,9 @@ macro_rules! impl_extend { ); #[unstable(feature = "num_internals", reason = "internal implementation detail", issue = "none")] - #[rustc_const_unstable(feature = "integer_extend_truncate", issue = "154330")] - impl const ExtendTarget<$to> for $from { - fn internal_extend(self) -> $to { + #[rustc_const_unstable(feature = "integer_widen_truncate", issue = "154330")] + impl const WidenTarget<$to> for $from { + fn internal_widen(self) -> $to { self as _ } } @@ -112,7 +112,7 @@ impl_truncate! { isize => isize, i16, i8; } -impl_extend! { +impl_widen! { u8 => u8, u16, u32, u64, u128, usize; u16 => u16, u32, u64, u128, usize; u32 => u32, u64, u128; diff --git a/library/core/src/num/uint_macros.rs b/library/core/src/num/uint_macros.rs index 93f9524dc13d2..cf029c2947a44 100644 --- a/library/core/src/num/uint_macros.rs +++ b/library/core/src/num/uint_macros.rs @@ -4220,13 +4220,13 @@ macro_rules! uint_impl { /// # Examples /// /// ``` - /// #![feature(integer_extend_truncate)] + /// #![feature(integer_widen_truncate)] #[doc = concat!("assert_eq!(120u8, 120", stringify!($SelfT), ".truncate());")] /// assert_eq!(120u8, 376u32.truncate()); /// ``` #[must_use = "this returns the truncated value and does not modify the original"] - #[unstable(feature = "integer_extend_truncate", issue = "154330")] - #[rustc_const_unstable(feature = "integer_extend_truncate", issue = "154330")] + #[unstable(feature = "integer_widen_truncate", issue = "154330")] + #[rustc_const_unstable(feature = "integer_widen_truncate", issue = "154330")] #[inline] pub const fn truncate(self) -> Target where Self: [const] traits::TruncateTarget @@ -4240,13 +4240,13 @@ macro_rules! uint_impl { /// # Examples /// /// ``` - /// #![feature(integer_extend_truncate)] + /// #![feature(integer_widen_truncate)] #[doc = concat!("assert_eq!(120u8, 120", stringify!($SelfT), ".saturating_truncate());")] /// assert_eq!(255u8, 376u32.saturating_truncate()); /// ``` #[must_use = "this returns the truncated value and does not modify the original"] - #[unstable(feature = "integer_extend_truncate", issue = "154330")] - #[rustc_const_unstable(feature = "integer_extend_truncate", issue = "154330")] + #[unstable(feature = "integer_widen_truncate", issue = "154330")] + #[rustc_const_unstable(feature = "integer_widen_truncate", issue = "154330")] #[inline] pub const fn saturating_truncate(self) -> Target where Self: [const] traits::TruncateTarget @@ -4260,13 +4260,13 @@ macro_rules! uint_impl { /// # Examples /// /// ``` - /// #![feature(integer_extend_truncate)] + /// #![feature(integer_widen_truncate)] #[doc = concat!("assert_eq!(Some(120u8), 120", stringify!($SelfT), ".checked_truncate());")] /// assert_eq!(None, 376u32.checked_truncate::()); /// ``` #[must_use = "this returns the truncated value and does not modify the original"] - #[unstable(feature = "integer_extend_truncate", issue = "154330")] - #[rustc_const_unstable(feature = "integer_extend_truncate", issue = "154330")] + #[unstable(feature = "integer_widen_truncate", issue = "154330")] + #[rustc_const_unstable(feature = "integer_widen_truncate", issue = "154330")] #[inline] pub const fn checked_truncate(self) -> Option where Self: [const] traits::TruncateTarget @@ -4274,22 +4274,22 @@ macro_rules! uint_impl { traits::TruncateTarget::internal_checked_truncate(self) } - /// Extend to an integer of the same size or larger, preserving its value. + /// Widen to an integer of the same size or larger, preserving its value. /// /// # Examples /// /// ``` - /// #![feature(integer_extend_truncate)] - #[doc = concat!("assert_eq!(120u128, 120u8.extend());")] + /// #![feature(integer_widen_truncate)] + #[doc = concat!("assert_eq!(120u128, 120u8.widen());")] /// ``` - #[must_use = "this returns the extended value and does not modify the original"] - #[unstable(feature = "integer_extend_truncate", issue = "154330")] - #[rustc_const_unstable(feature = "integer_extend_truncate", issue = "154330")] + #[must_use = "this returns the widened value and does not modify the original"] + #[unstable(feature = "integer_widen_truncate", issue = "154330")] + #[rustc_const_unstable(feature = "integer_widen_truncate", issue = "154330")] #[inline] - pub const fn extend(self) -> Target - where Self: [const] traits::ExtendTarget + pub const fn widen(self) -> Target + where Self: [const] traits::WidenTarget { - traits::ExtendTarget::internal_extend(self) + traits::WidenTarget::internal_widen(self) } } } diff --git a/tests/ui/imports/issue-114682-3.stderr b/tests/ui/imports/issue-114682-3.stderr index 0b8c8d3ae7972..6af7a4e026140 100644 --- a/tests/ui/imports/issue-114682-3.stderr +++ b/tests/ui/imports/issue-114682-3.stderr @@ -5,17 +5,13 @@ LL | fn ext(&self) {} | --- the method is available for `u8` here ... LL | a.ext(); - | ^^^ + | ^^^ method not found in `u8` | = help: items from traits can only be used if the trait is in scope help: trait `SettingsExt` which provides `ext` is implemented but not in scope; perhaps you want to import it | LL + use auto::SettingsExt; | -help: there is a method `extend` with a similar name - | -LL | a.extend(); - | +++ error: aborting due to 1 previous error From e35da4efa18c9a6ecc969aa28087ab63db5637a9 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sat, 28 Mar 2026 10:03:02 +0100 Subject: [PATCH 09/12] turn some long-deprecated options into errors --- compiler/rustc_interface/src/tests.rs | 3 --- compiler/rustc_session/src/options.rs | 23 ++++++++++------------- 2 files changed, 10 insertions(+), 16 deletions(-) diff --git a/compiler/rustc_interface/src/tests.rs b/compiler/rustc_interface/src/tests.rs index a7e0dd2ac39c0..0109da422e7d1 100644 --- a/compiler/rustc_interface/src/tests.rs +++ b/compiler/rustc_interface/src/tests.rs @@ -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); diff --git a/compiler/rustc_session/src/options.rs b/compiler/rustc_session/src/options.rs index 4767b0cfbe868..047358758d3f8 100644 --- a/compiler/rustc_session/src/options.rs +++ b/compiler/rustc_session/src/options.rs @@ -653,6 +653,7 @@ type OptionDescrs = &'static [OptionDesc]; /// Indicates whether a removed option should warn or error. enum RemovedOption { + #[allow(unused)] // we might want deprecated options that warn again in the future Warn, Err, } @@ -2037,10 +2038,9 @@ options! { // - src/doc/rustc/src/codegen-options/index.md // tidy-alphabetical-start - #[rustc_lint_opt_deny_field_access("documented to do nothing")] - ar: String = (String::new(), parse_string, [UNTRACKED], - "this option is deprecated and does nothing", - removed: Warn), + ar: () = ((), parse_ignore, [UNTRACKED], + "this option has been removed", + removed: Err), #[rustc_lint_opt_deny_field_access("use `Session::code_model` instead of this field")] code_model: Option = (None, parse_code_model, [TRACKED], "choose the code model to use (`rustc --print code-models` for details)"), @@ -2075,11 +2075,10 @@ options! { help: bool = (false, parse_no_value, [UNTRACKED], "Print codegen options"), incremental: Option = (None, parse_opt_string, [UNTRACKED], "enable incremental compilation"), - #[rustc_lint_opt_deny_field_access("documented to do nothing")] - inline_threshold: Option = (None, parse_opt_number, [UNTRACKED], - "this option is deprecated and does nothing \ + inline_threshold: () = ((), parse_ignore, [UNTRACKED], + "this option has been removed \ (consider using `-Cllvm-args=--inline-threshold=...`)", - removed: Warn), + removed: Err), #[rustc_lint_opt_deny_field_access("use `Session::instrument_coverage` instead of this field")] instrument_coverage: InstrumentCoverage = (InstrumentCoverage::No, parse_instrument_coverage, [TRACKED], "instrument the generated code to support LLVM source-based code coverage reports \ @@ -2117,10 +2116,9 @@ options! { "give an empty list of passes to the pass manager"), no_redzone: Option = (None, parse_opt_bool, [TRACKED], "disable the use of the redzone"), - #[rustc_lint_opt_deny_field_access("documented to do nothing")] - no_stack_check: bool = (false, parse_no_value, [UNTRACKED], - "this option is deprecated and does nothing", - removed: Warn), + no_stack_check: () = ((), parse_ignore, [UNTRACKED], + "this option has been removed", + removed: Err), no_vectorize_loops: bool = (false, parse_no_value, [TRACKED], "disable loop vectorization optimization passes"), no_vectorize_slp: bool = (false, parse_no_value, [TRACKED], @@ -2154,7 +2152,6 @@ options! { "set rpath values in libs/exes (default: no)"), save_temps: bool = (false, parse_bool, [UNTRACKED], "save all temporary output files during compilation (default: no)"), - #[rustc_lint_opt_deny_field_access("documented to do nothing")] soft_float: () = ((), parse_ignore, [UNTRACKED], "this option has been removed \ (use a corresponding *eabi target instead)", From bb4615d68a3ee3fb30e41681654d86cc3f44884c Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sat, 28 Mar 2026 10:13:13 +0100 Subject: [PATCH 10/12] adjust tests for these removed features --- tests/ui/compile-flags/removed_ar.rs | 5 +++++ tests/ui/compile-flags/removed_ar.stderr | 2 ++ tests/ui/deprecation/deprecated_ar.rs | 6 ------ tests/ui/deprecation/deprecated_ar.stderr | 2 -- .../deprecated_inline_threshold.bad_val.stderr | 4 ---- .../deprecated_inline_threshold.good_val.stderr | 2 -- .../deprecated_inline_threshold.no_val.stderr | 4 ---- .../ui/deprecation/deprecated_inline_threshold.rs | 14 -------------- tests/ui/deprecation/deprecated_no_stack_check.rs | 6 ------ .../deprecation/deprecated_no_stack_check.stderr | 11 ----------- .../deprecation/deprecated_no_stack_check_opt.rs | 6 ------ .../deprecated_no_stack_check_opt.stderr | 2 -- 12 files changed, 7 insertions(+), 57 deletions(-) create mode 100644 tests/ui/compile-flags/removed_ar.rs create mode 100644 tests/ui/compile-flags/removed_ar.stderr delete mode 100644 tests/ui/deprecation/deprecated_ar.rs delete mode 100644 tests/ui/deprecation/deprecated_ar.stderr delete mode 100644 tests/ui/deprecation/deprecated_inline_threshold.bad_val.stderr delete mode 100644 tests/ui/deprecation/deprecated_inline_threshold.good_val.stderr delete mode 100644 tests/ui/deprecation/deprecated_inline_threshold.no_val.stderr delete mode 100644 tests/ui/deprecation/deprecated_inline_threshold.rs delete mode 100644 tests/ui/deprecation/deprecated_no_stack_check.rs delete mode 100644 tests/ui/deprecation/deprecated_no_stack_check.stderr delete mode 100644 tests/ui/deprecation/deprecated_no_stack_check_opt.rs delete mode 100644 tests/ui/deprecation/deprecated_no_stack_check_opt.stderr diff --git a/tests/ui/compile-flags/removed_ar.rs b/tests/ui/compile-flags/removed_ar.rs new file mode 100644 index 0000000000000..0aaa3f9c2459d --- /dev/null +++ b/tests/ui/compile-flags/removed_ar.rs @@ -0,0 +1,5 @@ +//@ compile-flags: -Car=foo + +fn main() {} + +//~? ERROR `-C ar`: this option has been removed diff --git a/tests/ui/compile-flags/removed_ar.stderr b/tests/ui/compile-flags/removed_ar.stderr new file mode 100644 index 0000000000000..2f025d52b8eed --- /dev/null +++ b/tests/ui/compile-flags/removed_ar.stderr @@ -0,0 +1,2 @@ +error: `-C ar`: this option has been removed + diff --git a/tests/ui/deprecation/deprecated_ar.rs b/tests/ui/deprecation/deprecated_ar.rs deleted file mode 100644 index 00862d2c00a23..0000000000000 --- a/tests/ui/deprecation/deprecated_ar.rs +++ /dev/null @@ -1,6 +0,0 @@ -//@ check-pass -//@ compile-flags: -Car=foo - -fn main() {} - -//~? WARN `-C ar`: this option is deprecated and does nothing diff --git a/tests/ui/deprecation/deprecated_ar.stderr b/tests/ui/deprecation/deprecated_ar.stderr deleted file mode 100644 index de776c674996a..0000000000000 --- a/tests/ui/deprecation/deprecated_ar.stderr +++ /dev/null @@ -1,2 +0,0 @@ -warning: `-C ar`: this option is deprecated and does nothing - diff --git a/tests/ui/deprecation/deprecated_inline_threshold.bad_val.stderr b/tests/ui/deprecation/deprecated_inline_threshold.bad_val.stderr deleted file mode 100644 index 2e7a99010ae9b..0000000000000 --- a/tests/ui/deprecation/deprecated_inline_threshold.bad_val.stderr +++ /dev/null @@ -1,4 +0,0 @@ -warning: `-C inline-threshold`: this option is deprecated and does nothing (consider using `-Cllvm-args=--inline-threshold=...`) - -error: incorrect value `asd` for codegen option `inline-threshold` - a number was expected - diff --git a/tests/ui/deprecation/deprecated_inline_threshold.good_val.stderr b/tests/ui/deprecation/deprecated_inline_threshold.good_val.stderr deleted file mode 100644 index 2d6f3652d252e..0000000000000 --- a/tests/ui/deprecation/deprecated_inline_threshold.good_val.stderr +++ /dev/null @@ -1,2 +0,0 @@ -warning: `-C inline-threshold`: this option is deprecated and does nothing (consider using `-Cllvm-args=--inline-threshold=...`) - diff --git a/tests/ui/deprecation/deprecated_inline_threshold.no_val.stderr b/tests/ui/deprecation/deprecated_inline_threshold.no_val.stderr deleted file mode 100644 index 8006b15497902..0000000000000 --- a/tests/ui/deprecation/deprecated_inline_threshold.no_val.stderr +++ /dev/null @@ -1,4 +0,0 @@ -warning: `-C inline-threshold`: this option is deprecated and does nothing (consider using `-Cllvm-args=--inline-threshold=...`) - -error: codegen option `inline-threshold` requires a number (`-C inline-threshold=`) - diff --git a/tests/ui/deprecation/deprecated_inline_threshold.rs b/tests/ui/deprecation/deprecated_inline_threshold.rs deleted file mode 100644 index 284a6d6798e45..0000000000000 --- a/tests/ui/deprecation/deprecated_inline_threshold.rs +++ /dev/null @@ -1,14 +0,0 @@ -//@ revisions: good_val bad_val no_val -// -//@[good_val] compile-flags: -Cinline-threshold=666 -//@[good_val] check-pass -//@[bad_val] compile-flags: -Cinline-threshold=asd -//@[no_val] compile-flags: -Cinline-threshold - -fn main() {} - -//[good_val]~? WARN `-C inline-threshold`: this option is deprecated and does nothing -//[bad_val]~? WARN `-C inline-threshold`: this option is deprecated and does nothing -//[bad_val]~? ERROR incorrect value `asd` for codegen option `inline-threshold` -//[no_val]~? WARN `-C inline-threshold`: this option is deprecated and does nothing -//[no_val]~? ERROR codegen option `inline-threshold` requires a number diff --git a/tests/ui/deprecation/deprecated_no_stack_check.rs b/tests/ui/deprecation/deprecated_no_stack_check.rs deleted file mode 100644 index 8e1f5bbf045a5..0000000000000 --- a/tests/ui/deprecation/deprecated_no_stack_check.rs +++ /dev/null @@ -1,6 +0,0 @@ -#![deny(warnings)] -#![feature(no_stack_check)] -//~^ ERROR: feature has been removed [E0557] -fn main() { - -} diff --git a/tests/ui/deprecation/deprecated_no_stack_check.stderr b/tests/ui/deprecation/deprecated_no_stack_check.stderr deleted file mode 100644 index 33788661d7300..0000000000000 --- a/tests/ui/deprecation/deprecated_no_stack_check.stderr +++ /dev/null @@ -1,11 +0,0 @@ -error[E0557]: feature has been removed - --> $DIR/deprecated_no_stack_check.rs:2:12 - | -LL | #![feature(no_stack_check)] - | ^^^^^^^^^^^^^^ feature has been removed - | - = note: removed in 1.0.0; see for more information - -error: aborting due to 1 previous error - -For more information about this error, try `rustc --explain E0557`. diff --git a/tests/ui/deprecation/deprecated_no_stack_check_opt.rs b/tests/ui/deprecation/deprecated_no_stack_check_opt.rs deleted file mode 100644 index e014c7e80affc..0000000000000 --- a/tests/ui/deprecation/deprecated_no_stack_check_opt.rs +++ /dev/null @@ -1,6 +0,0 @@ -//@ check-pass -//@ compile-flags: -Cno-stack-check - -fn main() {} - -//~? WARN `-C no-stack-check`: this option is deprecated and does nothing diff --git a/tests/ui/deprecation/deprecated_no_stack_check_opt.stderr b/tests/ui/deprecation/deprecated_no_stack_check_opt.stderr deleted file mode 100644 index 17efba787f070..0000000000000 --- a/tests/ui/deprecation/deprecated_no_stack_check_opt.stderr +++ /dev/null @@ -1,2 +0,0 @@ -warning: `-C no-stack-check`: this option is deprecated and does nothing - From 9af2553ba0ba23b0e2c2f05d73e3fe1f2b767eae Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sat, 28 Mar 2026 13:05:12 +0100 Subject: [PATCH 11/12] remove no-longer-existing options from codegen-options docs --- src/doc/rustc/src/codegen-options/index.md | 14 -------------- 1 file changed, 14 deletions(-) diff --git a/src/doc/rustc/src/codegen-options/index.md b/src/doc/rustc/src/codegen-options/index.md index 7af10298470ee..3c7577b9135e6 100644 --- a/src/doc/rustc/src/codegen-options/index.md +++ b/src/doc/rustc/src/codegen-options/index.md @@ -3,10 +3,6 @@ All of these options are passed to `rustc` via the `-C` flag, short for "codegen." You can see a version of this list for your exact compiler by running `rustc -C help`. -## ar - -This option is deprecated and does nothing. - ## code-model This option lets you choose which code model to use. \ @@ -194,12 +190,6 @@ incremental files will be stored. Using incremental compilation inhibits certain optimizations (for example by increasing the amount of codegen units) and is therefore not recommended for release builds. -## inline-threshold - -This option is deprecated and does nothing. - -Consider using `-Cllvm-args=--inline-threshold=...`. - ## instrument-coverage This option enables instrumentation-based code coverage support. See the @@ -443,10 +433,6 @@ of the following values: The default behaviour, if the flag is not specified, depends on the target. -## no-stack-check - -This option is deprecated and does nothing. - ## no-vectorize-loops This flag disables [loop From d42a92b18d07bd39aafd3f281013ee24fabca1ed Mon Sep 17 00:00:00 2001 From: Qai Juang <237468078+qaijuang@users.noreply.github.com> Date: Fri, 8 May 2026 09:14:09 +0000 Subject: [PATCH 12/12] Reject outer attributes on `cfg_select` branches * Lint doc comments in cfg_select branches * test with multi-line doc comment Co-authored-by: Copilot * Reject outer attributes on `cfg_select` branches * address nits and gotchas Co-authored-by: Copilot * one more test Co-authored-by: Copilot * avoid snapshotting and classify recovered doc comments directly --- .../src/attributes/cfg_select.rs | 30 +++++++- compiler/rustc_parse/src/parser/cfg_select.rs | 38 +++++++++- tests/ui/macros/cfg_select.rs | 49 +++++++++++++ tests/ui/macros/cfg_select.stderr | 72 ++++++++++++++++++- 4 files changed, 185 insertions(+), 4 deletions(-) diff --git a/compiler/rustc_attr_parsing/src/attributes/cfg_select.rs b/compiler/rustc_attr_parsing/src/attributes/cfg_select.rs index 918fd0a4582b7..f6b49fe6880ed 100644 --- a/compiler/rustc_attr_parsing/src/attributes/cfg_select.rs +++ b/compiler/rustc_attr_parsing/src/attributes/cfg_select.rs @@ -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}; @@ -76,8 +76,11 @@ pub fn parse_cfg_select( lint_node_id: NodeId, ) -> Result { let mut branches = CfgSelectBranches::default(); + let mut branch_attr_error: Option = 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())?; @@ -131,6 +134,10 @@ pub fn parse_cfg_select( } } + if let Some(guar) = branch_attr_error { + return Err(guar); + } + let it = branches .reachable .iter() @@ -143,6 +150,27 @@ pub fn parse_cfg_select( Ok(branches) } +fn reject_branch_outer_attrs( + p: &mut Parser<'_>, + branch_attr_error: &mut Option, +) -> 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, diff --git a/compiler/rustc_parse/src/parser/cfg_select.rs b/compiler/rustc_parse/src/parser/cfg_select.rs index b12209f0b92ee..a4aeb919b106a 100644 --- a/compiler/rustc_parse/src/parser/cfg_select.rs +++ b/compiler/rustc_parse/src/parser/cfg_select.rs @@ -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, + pub doc_comments: Vec, +} + 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 @@ -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> { + 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)) + } } diff --git a/tests/ui/macros/cfg_select.rs b/tests/ui/macros/cfg_select.rs index 113cff38a3a93..9fd92ad668c2b 100644 --- a/tests/ui/macros/cfg_select.rs +++ b/tests/ui/macros/cfg_select.rs @@ -202,3 +202,52 @@ cfg_select! { //~^ ERROR expected one of `(`, `::`, `=>`, or `=`, found `!` //~| WARN unexpected `cfg` condition name } + +// Regression test for https://github.com/rust-lang/rust/issues/155701. +cfg_select! { + /// doc comment + //~^ ERROR doc comments are not allowed on `cfg_select` branches + debug_assertions => {} + /// doc comment + //~^ ERROR doc comments are not allowed on `cfg_select` branches + _ => {} +} + +cfg_select! { + #[cfg(false)] + //~^ ERROR attributes are not allowed on `cfg_select` branches + debug_assertions => {} + _ => {} +} + +cfg_select! { + #![cfg(false)] + //~^ ERROR an inner attribute is not permitted in this context + debug_assertions => {} + _ => {} +} + +cfg_select! { + //! inner doc comment + //~^ ERROR expected outer doc comment + debug_assertions => {} + _ => {} +} + +cfg_select! { + debug_assertions => {} + /// line1 + //~^ ERROR doc comments are not allowed on `cfg_select` branches + // line2 + /// line3 + _ => {} +} + +cfg_select! { + /// outer doc comment + //~^ ERROR doc comments are not allowed on `cfg_select` branches + //! inner doc comment + //~^ ERROR expected outer doc comment + debug_assertions => {} + _ => {} +} diff --git a/tests/ui/macros/cfg_select.stderr b/tests/ui/macros/cfg_select.stderr index e20028a29d527..b8fbe103d2cf1 100644 --- a/tests/ui/macros/cfg_select.stderr +++ b/tests/ui/macros/cfg_select.stderr @@ -55,6 +55,74 @@ error: expected one of `(`, `::`, `=>`, or `=`, found `!` LL | cfg!() => {} | ^ expected one of `(`, `::`, `=>`, or `=` +error: doc comments are not allowed on `cfg_select` branches + --> $DIR/cfg_select.rs:208:5 + | +LL | /// doc comment + | ^^^^^^^^^^^^^^^ + +error: doc comments are not allowed on `cfg_select` branches + --> $DIR/cfg_select.rs:211:5 + | +LL | /// doc comment + | ^^^^^^^^^^^^^^^ + +error: attributes are not allowed on `cfg_select` branches + --> $DIR/cfg_select.rs:217:5 + | +LL | #[cfg(false)] + | ^^^^^^^^^^^^^ + +error: an inner attribute is not permitted in this context + --> $DIR/cfg_select.rs:224:5 + | +LL | #![cfg(false)] + | ^^^^^^^^^^^^^^ + | + = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files + = note: outer attributes, like `#[test]`, annotate the item following them + +error[E0753]: expected outer doc comment + --> $DIR/cfg_select.rs:231:5 + | +LL | //! inner doc comment + | ^^^^^^^^^^^^^^^^^^^^^ + | + = note: inner doc comments like this (starting with `//!` or `/*!`) can only appear before items +help: you might have meant to write a regular comment + | +LL - //! inner doc comment +LL + // inner doc comment + | + +error: doc comments are not allowed on `cfg_select` branches + --> $DIR/cfg_select.rs:239:5 + | +LL | /// line1 + | ^^^^^^^^^ +... +LL | /// line3 + | ^^^^^^^^^ + +error[E0753]: expected outer doc comment + --> $DIR/cfg_select.rs:249:5 + | +LL | //! inner doc comment + | ^^^^^^^^^^^^^^^^^^^^^ + | + = note: inner doc comments like this (starting with `//!` or `/*!`) can only appear before items +help: you might have meant to write a regular comment + | +LL - //! inner doc comment +LL + // inner doc comment + | + +error: doc comments are not allowed on `cfg_select` branches + --> $DIR/cfg_select.rs:247:5 + | +LL | /// outer doc comment + | ^^^^^^^^^^^^^^^^^^^^^ + warning: unreachable configuration predicate --> $DIR/cfg_select.rs:136:5 | @@ -115,7 +183,7 @@ LL | cfg!() => {} = help: to expect this configuration use `--check-cfg=cfg(cfg)` = note: see for more information about checking conditional configuration -error: aborting due to 9 previous errors; 7 warnings emitted +error: aborting due to 17 previous errors; 7 warnings emitted -Some errors have detailed explanations: E0537, E0539. +Some errors have detailed explanations: E0537, E0539, E0753. For more information about an error, try `rustc --explain E0537`.