Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
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
Next Next commit
Port #[register_tool] to the new attribute parsers
Co-authored-by: Jana Dönszelmann <jana@donsz.nl>
  • Loading branch information
JonathanBrouwer and jdonszelmann committed Feb 24, 2026
commit f8b5f9c3dda7cbbef812b45d535cae35f2ee0df8
47 changes: 47 additions & 0 deletions compiler/rustc_attr_parsing/src/attributes/crate_level.rs
Original file line number Diff line number Diff line change
Expand Up @@ -347,3 +347,50 @@ impl<S: Stage> CombineAttributeParser<S> for FeatureParser {
res
}
}

pub(crate) struct RegisterToolParser;

impl<S: Stage> CombineAttributeParser<S> for RegisterToolParser {
const PATH: &[Symbol] = &[sym::register_tool];
type Item = Ident;
const CONVERT: ConvertFn<Self::Item> = AttributeKind::RegisterTool;
const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(ALL_TARGETS);
const TEMPLATE: AttributeTemplate = template!(List: &["tool1, tool2, ..."]);

fn extend(
cx: &mut AcceptContext<'_, '_, S>,
args: &ArgParser,
) -> impl IntoIterator<Item = Self::Item> {
let ArgParser::List(list) = args else {
cx.expected_list(cx.attr_span, args);
return Vec::new();
};

if list.is_empty() {
cx.warn_empty_attribute(cx.attr_span);
}

let mut res = Vec::new();

for elem in list.mixed() {
let Some(elem) = elem.meta_item() else {
cx.expected_identifier(elem.span());
continue;
};
if let Err(arg_span) = elem.args().no_args() {
cx.expected_no_args(arg_span);
continue;
}

let path = elem.path();
let Some(ident) = path.word() else {
cx.expected_identifier(path.span());
continue;
};

res.push(ident);
}

res
}
}
1 change: 1 addition & 0 deletions compiler/rustc_attr_parsing/src/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -160,6 +160,7 @@ attribute_parsers!(
Combine<FeatureParser>,
Combine<ForceTargetFeatureParser>,
Combine<LinkParser>,
Combine<RegisterToolParser>,
Combine<ReprParser>,
Combine<RustcCleanParser>,
Combine<RustcLayoutParser>,
Expand Down
3 changes: 3 additions & 0 deletions compiler/rustc_hir/src/attrs/data_structures.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1139,6 +1139,9 @@ pub enum AttributeKind {
/// Represents `#[reexport_test_harness_main]`
ReexportTestHarnessMain(Symbol),

/// Represents `#[register_tool]`
RegisterTool(ThinVec<Ident>, Span),

/// Represents [`#[repr]`](https://doc.rust-lang.org/stable/reference/type-layout.html#representations).
Repr {
reprs: ThinVec<(ReprAttr, Span)>,
Expand Down
1 change: 1 addition & 0 deletions compiler/rustc_hir/src/attrs/encode_cross_crate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,7 @@ impl AttributeKind {
ProfilerRuntime => No,
RecursionLimit { .. } => No,
ReexportTestHarnessMain(..) => No,
RegisterTool(..) => No,
Repr { .. } => No,
RustcAbi { .. } => No,
RustcAllocator => No,
Expand Down
4 changes: 2 additions & 2 deletions compiler/rustc_passes/src/check_attr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -289,6 +289,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
| AttributeKind::ProfilerRuntime
| AttributeKind::RecursionLimit { .. }
| AttributeKind::ReexportTestHarnessMain(..)
| AttributeKind::RegisterTool(..)
// handled below this loop and elsewhere
| AttributeKind::Repr { .. }
| AttributeKind::RustcAbi { .. }
Expand Down Expand Up @@ -407,8 +408,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
| sym::rustc_layout
| sym::rustc_autodiff
// crate-level attrs, are checked below
| sym::feature
| sym::register_tool,
| sym::feature,
..
] => {}
[name, rest@..] => {
Expand Down