Skip to content

Commit 3f8795a

Browse files
authored
Unrolled build for #142818
Rollup merge of #142818 - JonathanBrouwer:used_new_parser, r=jdonszelmann Port `#[used]` to new attribute parsing infrastructure Ports `used` to the new attribute parsing infrastructure for #131229 (comment) r? ``@jdonszelmann``
2 parents 13c46fd + 9e35684 commit 3f8795a

File tree

15 files changed

+185
-124
lines changed

15 files changed

+185
-124
lines changed

compiler/rustc_attr_data_structures/src/attributes.rs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -131,6 +131,17 @@ impl Deprecation {
131131
}
132132
}
133133

134+
/// There are three valid forms of the attribute:
135+
/// `#[used]`, which is semantically equivalent to `#[used(linker)]` except that the latter is currently unstable.
136+
/// `#[used(compiler)]`
137+
/// `#[used(linker)]`
138+
#[derive(Encodable, Decodable, Copy, Clone, Debug, PartialEq, Eq, Hash)]
139+
#[derive(HashStable_Generic, PrintAttribute)]
140+
pub enum UsedBy {
141+
Compiler,
142+
Linker,
143+
}
144+
134145
/// Represents parsed *built-in* inert attributes.
135146
///
136147
/// ## Overview
@@ -285,5 +296,8 @@ pub enum AttributeKind {
285296

286297
/// Represents `#[track_caller]`
287298
TrackCaller(Span),
299+
300+
/// Represents `#[used]`
301+
Used { used_by: UsedBy, span: Span },
288302
// tidy-alphabetical-end
289303
}

compiler/rustc_attr_data_structures/src/encode_cross_crate.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ impl AttributeKind {
3838
PubTransparent(..) => Yes,
3939
SkipDuringMethodDispatch { .. } => No,
4040
TrackCaller(..) => Yes,
41+
Used { .. } => No,
4142
}
4243
}
4344
}

compiler/rustc_attr_parsing/src/attributes/codegen_attrs.rs

Lines changed: 82 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use rustc_attr_data_structures::{AttributeKind, OptimizeAttr};
1+
use rustc_attr_data_structures::{AttributeKind, OptimizeAttr, UsedBy};
22
use rustc_feature::{AttributeTemplate, template};
33
use rustc_session::parse::feature_err;
44
use rustc_span::{Span, Symbol, sym};
@@ -228,3 +228,84 @@ impl<S: Stage> SingleAttributeParser<S> for NoMangleParser {
228228
Some(AttributeKind::NoMangle(cx.attr_span))
229229
}
230230
}
231+
232+
#[derive(Default)]
233+
pub(crate) struct UsedParser {
234+
first_compiler: Option<Span>,
235+
first_linker: Option<Span>,
236+
}
237+
238+
// A custom `AttributeParser` is used rather than a Simple attribute parser because
239+
// - Specifying two `#[used]` attributes is a warning (but will be an error in the future)
240+
// - But specifying two conflicting attributes: `#[used(compiler)]` and `#[used(linker)]` is already an error today
241+
// We can change this to a Simple parser once the warning becomes an error
242+
impl<S: Stage> AttributeParser<S> for UsedParser {
243+
const ATTRIBUTES: AcceptMapping<Self, S> = &[(
244+
&[sym::used],
245+
template!(Word, List: "compiler|linker"),
246+
|group: &mut Self, cx, args| {
247+
let used_by = match args {
248+
ArgParser::NoArgs => UsedBy::Linker,
249+
ArgParser::List(list) => {
250+
let Some(l) = list.single() else {
251+
cx.expected_single_argument(list.span);
252+
return;
253+
};
254+
255+
match l.meta_item().and_then(|i| i.path().word_sym()) {
256+
Some(sym::compiler) => {
257+
if !cx.features().used_with_arg() {
258+
feature_err(
259+
&cx.sess(),
260+
sym::used_with_arg,
261+
cx.attr_span,
262+
"`#[used(compiler)]` is currently unstable",
263+
)
264+
.emit();
265+
}
266+
UsedBy::Compiler
267+
}
268+
Some(sym::linker) => {
269+
if !cx.features().used_with_arg() {
270+
feature_err(
271+
&cx.sess(),
272+
sym::used_with_arg,
273+
cx.attr_span,
274+
"`#[used(linker)]` is currently unstable",
275+
)
276+
.emit();
277+
}
278+
UsedBy::Linker
279+
}
280+
_ => {
281+
cx.expected_specific_argument(l.span(), vec!["compiler", "linker"]);
282+
return;
283+
}
284+
}
285+
}
286+
ArgParser::NameValue(_) => return,
287+
};
288+
289+
let target = match used_by {
290+
UsedBy::Compiler => &mut group.first_compiler,
291+
UsedBy::Linker => &mut group.first_linker,
292+
};
293+
294+
let attr_span = cx.attr_span;
295+
if let Some(prev) = *target {
296+
cx.warn_unused_duplicate(prev, attr_span);
297+
} else {
298+
*target = Some(attr_span);
299+
}
300+
},
301+
)];
302+
303+
fn finalize(self, _cx: &FinalizeContext<'_, '_, S>) -> Option<AttributeKind> {
304+
// Ratcheting behaviour, if both `linker` and `compiler` are specified, use `linker`
305+
Some(match (self.first_compiler, self.first_linker) {
306+
(_, Some(span)) => AttributeKind::Used { used_by: UsedBy::Linker, span },
307+
(Some(span), _) => AttributeKind::Used { used_by: UsedBy::Compiler, span },
308+
(None, None) => return None,
309+
})
310+
}
311+
}

compiler/rustc_attr_parsing/src/context.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ use rustc_span::{DUMMY_SP, ErrorGuaranteed, Span, Symbol, sym};
1717
use crate::attributes::allow_unstable::{AllowConstFnUnstableParser, AllowInternalUnstableParser};
1818
use crate::attributes::codegen_attrs::{
1919
ColdParser, ExportNameParser, NakedParser, NoMangleParser, OptimizeParser, TrackCallerParser,
20+
UsedParser,
2021
};
2122
use crate::attributes::confusables::ConfusablesParser;
2223
use crate::attributes::deprecation::DeprecationParser;
@@ -103,6 +104,7 @@ attribute_parsers!(
103104
ConstStabilityParser,
104105
NakedParser,
105106
StabilityParser,
107+
UsedParser,
106108
// tidy-alphabetical-end
107109

108110
// tidy-alphabetical-start

compiler/rustc_codegen_ssa/messages.ftl

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -48,8 +48,6 @@ codegen_ssa_error_writing_def_file =
4848
4949
codegen_ssa_expected_name_value_pair = expected name value pair
5050
51-
codegen_ssa_expected_used_symbol = expected `used`, `used(compiler)` or `used(linker)`
52-
5351
codegen_ssa_extern_funcs_not_found = some `extern` functions couldn't be found; some native libraries may need to be installed or have their path specified
5452
5553
codegen_ssa_extract_bundled_libs_archive_member = failed to get data from archive member '{$rlib}': {$error}

compiler/rustc_codegen_ssa/src/codegen_attrs.rs

Lines changed: 5 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ use rustc_abi::ExternAbi;
44
use rustc_ast::expand::autodiff_attrs::{AutoDiffAttrs, DiffActivity, DiffMode};
55
use rustc_ast::{LitKind, MetaItem, MetaItemInner, attr};
66
use rustc_attr_data_structures::{
7-
AttributeKind, InlineAttr, InstructionSetAttr, OptimizeAttr, ReprAttr, find_attr,
7+
AttributeKind, InlineAttr, InstructionSetAttr, OptimizeAttr, ReprAttr, UsedBy, find_attr,
88
};
99
use rustc_hir::def::DefKind;
1010
use rustc_hir::def_id::{DefId, LOCAL_CRATE, LocalDefId};
@@ -160,6 +160,10 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs {
160160
}
161161
codegen_fn_attrs.flags |= CodegenFnAttrFlags::TRACK_CALLER
162162
}
163+
AttributeKind::Used { used_by, .. } => match used_by {
164+
UsedBy::Compiler => codegen_fn_attrs.flags |= CodegenFnAttrFlags::USED_COMPILER,
165+
UsedBy::Linker => codegen_fn_attrs.flags |= CodegenFnAttrFlags::USED_LINKER,
166+
},
163167
_ => {}
164168
}
165169
}
@@ -181,44 +185,6 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs {
181185
sym::rustc_std_internal_symbol => {
182186
codegen_fn_attrs.flags |= CodegenFnAttrFlags::RUSTC_STD_INTERNAL_SYMBOL
183187
}
184-
sym::used => {
185-
let inner = attr.meta_item_list();
186-
match inner.as_deref() {
187-
Some([item]) if item.has_name(sym::linker) => {
188-
if !tcx.features().used_with_arg() {
189-
feature_err(
190-
&tcx.sess,
191-
sym::used_with_arg,
192-
attr.span(),
193-
"`#[used(linker)]` is currently unstable",
194-
)
195-
.emit();
196-
}
197-
codegen_fn_attrs.flags |= CodegenFnAttrFlags::USED_LINKER;
198-
}
199-
Some([item]) if item.has_name(sym::compiler) => {
200-
if !tcx.features().used_with_arg() {
201-
feature_err(
202-
&tcx.sess,
203-
sym::used_with_arg,
204-
attr.span(),
205-
"`#[used(compiler)]` is currently unstable",
206-
)
207-
.emit();
208-
}
209-
codegen_fn_attrs.flags |= CodegenFnAttrFlags::USED_COMPILER;
210-
}
211-
Some(_) => {
212-
tcx.dcx().emit_err(errors::ExpectedUsedSymbol { span: attr.span() });
213-
}
214-
None => {
215-
// Unconditionally using `llvm.used` causes issues in handling
216-
// `.init_array` with the gold linker. Luckily gold has been
217-
// deprecated with GCC 15 and rustc now warns about using gold.
218-
codegen_fn_attrs.flags |= CodegenFnAttrFlags::USED_LINKER
219-
}
220-
}
221-
}
222188
sym::thread_local => codegen_fn_attrs.flags |= CodegenFnAttrFlags::THREAD_LOCAL,
223189
sym::target_feature => {
224190
let Some(sig) = tcx.hir_node_by_def_id(did).fn_sig() else {

compiler/rustc_codegen_ssa/src/errors.rs

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -726,13 +726,6 @@ pub struct UnknownArchiveKind<'a> {
726726
pub kind: &'a str,
727727
}
728728

729-
#[derive(Diagnostic)]
730-
#[diag(codegen_ssa_expected_used_symbol)]
731-
pub(crate) struct ExpectedUsedSymbol {
732-
#[primary_span]
733-
pub span: Span,
734-
}
735-
736729
#[derive(Diagnostic)]
737730
#[diag(codegen_ssa_multiple_main_functions)]
738731
#[help]

compiler/rustc_passes/messages.ftl

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -816,9 +816,6 @@ passes_unused_variable_try_prefix = unused variable: `{$name}`
816816
.suggestion = if this is intentional, prefix it with an underscore
817817
818818
819-
passes_used_compiler_linker =
820-
`used(compiler)` and `used(linker)` can't be used together
821-
822819
passes_used_static =
823820
attribute must be applied to a `static` variable
824821
.label = but this is a {$target}

compiler/rustc_passes/src/check_attr.rs

Lines changed: 10 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -200,6 +200,9 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
200200
Attribute::Parsed(AttributeKind::NoMangle(attr_span)) => {
201201
self.check_no_mangle(hir_id, *attr_span, span, target)
202202
}
203+
Attribute::Parsed(AttributeKind::Used { span: attr_span, .. }) => {
204+
self.check_used(*attr_span, target, span);
205+
}
203206
Attribute::Unparsed(attr_item) => {
204207
style = Some(attr_item.style);
205208
match attr.path().as_slice() {
@@ -333,7 +336,6 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
333336
| sym::cfi_encoding // FIXME(cfi_encoding)
334337
| sym::pointee // FIXME(derive_coerce_pointee)
335338
| sym::omit_gdb_pretty_printer_section // FIXME(omit_gdb_pretty_printer_section)
336-
| sym::used // handled elsewhere to restrict to static items
337339
| sym::instruction_set // broken on stable!!!
338340
| sym::windows_subsystem // broken on stable!!!
339341
| sym::patchable_function_entry // FIXME(patchable_function_entry)
@@ -403,7 +405,6 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
403405
}
404406

405407
self.check_repr(attrs, span, target, item, hir_id);
406-
self.check_used(attrs, target, span);
407408
self.check_rustc_force_inline(hir_id, attrs, span, target);
408409
self.check_mix_no_mangle_export(hir_id, attrs);
409410
}
@@ -2107,44 +2108,13 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
21072108
}
21082109
}
21092110

2110-
fn check_used(&self, attrs: &[Attribute], target: Target, target_span: Span) {
2111-
let mut used_linker_span = None;
2112-
let mut used_compiler_span = None;
2113-
for attr in attrs.iter().filter(|attr| attr.has_name(sym::used)) {
2114-
if target != Target::Static {
2115-
self.dcx().emit_err(errors::UsedStatic {
2116-
attr_span: attr.span(),
2117-
span: target_span,
2118-
target: target.name(),
2119-
});
2120-
}
2121-
let inner = attr.meta_item_list();
2122-
match inner.as_deref() {
2123-
Some([item]) if item.has_name(sym::linker) => {
2124-
if used_linker_span.is_none() {
2125-
used_linker_span = Some(attr.span());
2126-
}
2127-
}
2128-
Some([item]) if item.has_name(sym::compiler) => {
2129-
if used_compiler_span.is_none() {
2130-
used_compiler_span = Some(attr.span());
2131-
}
2132-
}
2133-
Some(_) => {
2134-
// This error case is handled in rustc_hir_analysis::collect.
2135-
}
2136-
None => {
2137-
// Default case (compiler) when arg isn't defined.
2138-
if used_compiler_span.is_none() {
2139-
used_compiler_span = Some(attr.span());
2140-
}
2141-
}
2142-
}
2143-
}
2144-
if let (Some(linker_span), Some(compiler_span)) = (used_linker_span, used_compiler_span) {
2145-
self.tcx
2146-
.dcx()
2147-
.emit_err(errors::UsedCompilerLinker { spans: vec![linker_span, compiler_span] });
2111+
fn check_used(&self, attr_span: Span, target: Target, target_span: Span) {
2112+
if target != Target::Static {
2113+
self.dcx().emit_err(errors::UsedStatic {
2114+
attr_span,
2115+
span: target_span,
2116+
target: target.name(),
2117+
});
21482118
}
21492119
}
21502120

compiler/rustc_passes/src/errors.rs

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -641,13 +641,6 @@ pub(crate) struct UsedStatic {
641641
pub target: &'static str,
642642
}
643643

644-
#[derive(Diagnostic)]
645-
#[diag(passes_used_compiler_linker)]
646-
pub(crate) struct UsedCompilerLinker {
647-
#[primary_span]
648-
pub spans: Vec<Span>,
649-
}
650-
651644
#[derive(Diagnostic)]
652645
#[diag(passes_allow_internal_unstable)]
653646
pub(crate) struct AllowInternalUnstable {

tests/ui/attributes/used_with_arg.rs

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
#![deny(unused_attributes)]
12
#![feature(used_with_arg)]
23

34
#[used(linker)]
@@ -6,14 +7,22 @@ static mut USED_LINKER: [usize; 1] = [0];
67
#[used(compiler)]
78
static mut USED_COMPILER: [usize; 1] = [0];
89

9-
#[used(compiler)] //~ ERROR `used(compiler)` and `used(linker)` can't be used together
10+
#[used(compiler)]
1011
#[used(linker)]
1112
static mut USED_COMPILER_LINKER2: [usize; 1] = [0];
1213

13-
#[used(compiler)] //~ ERROR `used(compiler)` and `used(linker)` can't be used together
14-
#[used(linker)]
1514
#[used(compiler)]
1615
#[used(linker)]
16+
#[used(compiler)] //~ ERROR unused attribute
17+
#[used(linker)] //~ ERROR unused attribute
1718
static mut USED_COMPILER_LINKER3: [usize; 1] = [0];
1819

20+
#[used(compiler)]
21+
#[used]
22+
static mut USED_WITHOUT_ATTR1: [usize; 1] = [0];
23+
24+
#[used(linker)]
25+
#[used] //~ ERROR unused attribute
26+
static mut USED_WITHOUT_ATTR2: [usize; 1] = [0];
27+
1928
fn main() {}

0 commit comments

Comments
 (0)