Skip to content

Commit 66173bb

Browse files
authored
Rollup merge of rust-lang#152988 - JonathanBrouwer:register-tool, r=jdonszelmann
Port `#[register_tool]` to the new attribute system For rust-lang#131229 (comment) Rebase of rust-lang#146702 r? @jdonszelmann
2 parents 598d4c8 + 436315d commit 66173bb

12 files changed

Lines changed: 100 additions & 42 deletions

File tree

compiler/rustc_attr_parsing/src/attributes/crate_level.rs

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -301,3 +301,50 @@ impl<S: Stage> NoArgsAttributeParser<S> for DefaultLibAllocatorParser {
301301
const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Crate)]);
302302
const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::DefaultLibAllocator;
303303
}
304+
305+
pub(crate) struct RegisterToolParser;
306+
307+
impl<S: Stage> CombineAttributeParser<S> for RegisterToolParser {
308+
const PATH: &[Symbol] = &[sym::register_tool];
309+
type Item = Ident;
310+
const CONVERT: ConvertFn<Self::Item> = AttributeKind::RegisterTool;
311+
const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(ALL_TARGETS);
312+
const TEMPLATE: AttributeTemplate = template!(List: &["tool1, tool2, ..."]);
313+
314+
fn extend(
315+
cx: &mut AcceptContext<'_, '_, S>,
316+
args: &ArgParser,
317+
) -> impl IntoIterator<Item = Self::Item> {
318+
let ArgParser::List(list) = args else {
319+
cx.expected_list(cx.attr_span, args);
320+
return Vec::new();
321+
};
322+
323+
if list.is_empty() {
324+
cx.warn_empty_attribute(cx.attr_span);
325+
}
326+
327+
let mut res = Vec::new();
328+
329+
for elem in list.mixed() {
330+
let Some(elem) = elem.meta_item() else {
331+
cx.expected_identifier(elem.span());
332+
continue;
333+
};
334+
if let Err(arg_span) = elem.args().no_args() {
335+
cx.expected_no_args(arg_span);
336+
continue;
337+
}
338+
339+
let path = elem.path();
340+
let Some(ident) = path.word() else {
341+
cx.expected_identifier(path.span());
342+
continue;
343+
};
344+
345+
res.push(ident);
346+
}
347+
348+
res
349+
}
350+
}

compiler/rustc_attr_parsing/src/context.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -159,6 +159,7 @@ attribute_parsers!(
159159
Combine<DebuggerViualizerParser>,
160160
Combine<ForceTargetFeatureParser>,
161161
Combine<LinkParser>,
162+
Combine<RegisterToolParser>,
162163
Combine<ReprParser>,
163164
Combine<RustcCleanParser>,
164165
Combine<RustcLayoutParser>,

compiler/rustc_driver_impl/src/lib.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -707,8 +707,9 @@ fn print_crate_info(
707707
};
708708
let crate_name = passes::get_crate_name(sess, attrs);
709709
let lint_store = crate::unerased_lint_store(sess);
710-
let registered_tools = rustc_resolve::registered_tools_ast(sess.dcx(), attrs);
711710
let features = rustc_expand::config::features(sess, attrs, crate_name);
711+
let registered_tools =
712+
rustc_resolve::registered_tools_ast(sess.dcx(), attrs, sess, &features);
712713
let lint_levels = rustc_lint::LintLevelsBuilder::crate_root(
713714
sess,
714715
&features,

compiler/rustc_hir/src/attrs/data_structures.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1136,6 +1136,9 @@ pub enum AttributeKind {
11361136
/// Represents `#[reexport_test_harness_main]`
11371137
ReexportTestHarnessMain(Symbol),
11381138

1139+
/// Represents `#[register_tool]`
1140+
RegisterTool(ThinVec<Ident>, Span),
1141+
11391142
/// Represents [`#[repr]`](https://doc.rust-lang.org/stable/reference/type-layout.html#representations).
11401143
Repr {
11411144
reprs: ThinVec<(ReprAttr, Span)>,

compiler/rustc_hir/src/attrs/encode_cross_crate.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,7 @@ impl AttributeKind {
9191
ProfilerRuntime => No,
9292
RecursionLimit { .. } => No,
9393
ReexportTestHarnessMain(..) => No,
94+
RegisterTool(..) => No,
9495
Repr { .. } => No,
9596
RustcAbi { .. } => No,
9697
RustcAllocator => No,

compiler/rustc_passes/src/check_attr.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -288,6 +288,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
288288
| AttributeKind::ProfilerRuntime
289289
| AttributeKind::RecursionLimit { .. }
290290
| AttributeKind::ReexportTestHarnessMain(..)
291+
| AttributeKind::RegisterTool(..)
291292
// handled below this loop and elsewhere
292293
| AttributeKind::Repr { .. }
293294
| AttributeKind::RustcAbi { .. }
@@ -406,8 +407,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
406407
| sym::rustc_autodiff
407408
| sym::rustc_inherit_overflow_checks
408409
// crate-level attrs, are checked below
409-
| sym::feature
410-
| sym::register_tool,
410+
| sym::feature,
411411
..
412412
] => {}
413413
[name, rest@..] => {

compiler/rustc_resolve/src/errors.rs

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1201,15 +1201,6 @@ pub(crate) struct ToolWasAlreadyRegistered {
12011201
pub(crate) old_ident_span: Span,
12021202
}
12031203

1204-
#[derive(Diagnostic)]
1205-
#[diag("`{$tool}` only accepts identifiers")]
1206-
pub(crate) struct ToolOnlyAcceptsIdentifiers {
1207-
#[primary_span]
1208-
#[label("not an identifier")]
1209-
pub(crate) span: Span,
1210-
pub(crate) tool: Symbol,
1211-
}
1212-
12131204
#[derive(Subdiagnostic)]
12141205
pub(crate) enum DefinedHere {
12151206
#[label("similarly named {$candidate_descr} `{$candidate}` defined here")]

compiler/rustc_resolve/src/macros.rs

Lines changed: 28 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,9 @@
44
use std::mem;
55
use std::sync::Arc;
66

7-
use rustc_ast::{self as ast, Crate, NodeId, attr};
7+
use rustc_ast::{self as ast, Crate, DUMMY_NODE_ID, NodeId};
88
use rustc_ast_pretty::pprust;
9+
use rustc_attr_parsing::AttributeParser;
910
use rustc_errors::{Applicability, DiagCtxtHandle, StashKey};
1011
use rustc_expand::base::{
1112
Annotatable, DeriveResolution, Indeterminate, ResolverExpand, SyntaxExtension,
@@ -15,12 +16,14 @@ use rustc_expand::compile_declarative_macro;
1516
use rustc_expand::expand::{
1617
AstFragment, AstFragmentKind, Invocation, InvocationKind, SupportsMacroExpansion,
1718
};
18-
use rustc_hir::StabilityLevel;
19-
use rustc_hir::attrs::{CfgEntry, StrippedCfgItem};
19+
use rustc_feature::Features;
20+
use rustc_hir::attrs::{AttributeKind, CfgEntry, StrippedCfgItem};
2021
use rustc_hir::def::{self, DefKind, MacroKinds, Namespace, NonMacroAttrKind};
2122
use rustc_hir::def_id::{CrateNum, DefId, LocalDefId};
23+
use rustc_hir::{Attribute, StabilityLevel};
2224
use rustc_middle::middle::stability;
2325
use rustc_middle::ty::{RegisteredTools, TyCtxt};
26+
use rustc_session::Session;
2427
use rustc_session::lint::builtin::{
2528
LEGACY_DERIVE_HELPERS, OUT_OF_SCOPE_MACRO_CALLS, UNKNOWN_DIAGNOSTIC_ATTRIBUTES,
2629
UNUSED_MACRO_RULES, UNUSED_MACROS,
@@ -122,35 +125,38 @@ fn fast_print_path(path: &ast::Path) -> Symbol {
122125

123126
pub(crate) fn registered_tools(tcx: TyCtxt<'_>, (): ()) -> RegisteredTools {
124127
let (_, pre_configured_attrs) = &*tcx.crate_for_resolver(()).borrow();
125-
registered_tools_ast(tcx.dcx(), pre_configured_attrs)
128+
registered_tools_ast(tcx.dcx(), pre_configured_attrs, tcx.sess, tcx.features())
126129
}
127130

128131
pub fn registered_tools_ast(
129132
dcx: DiagCtxtHandle<'_>,
130133
pre_configured_attrs: &[ast::Attribute],
134+
sess: &Session,
135+
features: &Features,
131136
) -> RegisteredTools {
132137
let mut registered_tools = RegisteredTools::default();
133-
for attr in attr::filter_by_name(pre_configured_attrs, sym::register_tool) {
134-
for meta_item_inner in attr.meta_item_list().unwrap_or_default() {
135-
match meta_item_inner.ident() {
136-
Some(ident) => {
137-
if let Some(old_ident) = registered_tools.replace(ident) {
138-
dcx.emit_err(errors::ToolWasAlreadyRegistered {
139-
span: ident.span,
140-
tool: ident,
141-
old_ident_span: old_ident.span,
142-
});
143-
}
144-
}
145-
None => {
146-
dcx.emit_err(errors::ToolOnlyAcceptsIdentifiers {
147-
span: meta_item_inner.span(),
148-
tool: sym::register_tool,
149-
});
150-
}
138+
139+
if let Some(Attribute::Parsed(AttributeKind::RegisterTool(tools, _))) =
140+
AttributeParser::parse_limited(
141+
sess,
142+
pre_configured_attrs,
143+
sym::register_tool,
144+
DUMMY_SP,
145+
DUMMY_NODE_ID,
146+
Some(features),
147+
)
148+
{
149+
for tool in tools {
150+
if let Some(old_tool) = registered_tools.replace(tool) {
151+
dcx.emit_err(errors::ToolWasAlreadyRegistered {
152+
span: tool.span,
153+
tool,
154+
old_ident_span: old_tool.span,
155+
});
151156
}
152157
}
153158
}
159+
154160
// We implicitly add `rustfmt`, `clippy`, `diagnostic`, `miri` and `rust_analyzer` to known
155161
// tools, but it's not an error to register them explicitly.
156162
let predefined_tools =
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
#![feature(register_tool)]
22

33
#![register_tool(1)]
4-
//~^ ERROR `register_tool` only accepts identifiers
4+
//~^ ERROR malformed `register_tool` attribute input
55

66
fn main() {}
Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,12 @@
1-
error: `register_tool` only accepts identifiers
2-
--> $DIR/invalid-tool.rs:3:18
1+
error[E0539]: malformed `register_tool` attribute input
2+
--> $DIR/invalid-tool.rs:3:1
33
|
44
LL | #![register_tool(1)]
5-
| ^ not an identifier
5+
| ^^^^^^^^^^^^^^^^^-^^
6+
| | |
7+
| | expected a valid identifier here
8+
| help: must be of the form: `#![register_tool(tool1, tool2, ...)]`
69

710
error: aborting due to 1 previous error
811

12+
For more information about this error, try `rustc --explain E0539`.

0 commit comments

Comments
 (0)