Skip to content

Commit e65caaa

Browse files
committed
convert the optimize attribute to a new parser
1 parent 251ad20 commit e65caaa

File tree

11 files changed

+71
-39
lines changed

11 files changed

+71
-39
lines changed

compiler/rustc_attr_data_structures/src/attributes.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,8 @@ pub enum InstructionSetAttr {
3838
ArmT32,
3939
}
4040

41-
#[derive(Clone, Encodable, Decodable, Debug, PartialEq, Eq, HashStable_Generic, Default)]
41+
#[derive(Copy, Clone, Debug, PartialEq, Eq, Default, PrintAttribute)]
42+
#[derive(Encodable, Decodable, HashStable_Generic)]
4243
pub enum OptimizeAttr {
4344
/// No `#[optimize(..)]` attribute
4445
#[default]
@@ -191,6 +192,7 @@ pub enum AttributeKind {
191192
},
192193
Inline(InlineAttr, Span),
193194
MacroTransparency(Transparency),
195+
Optimize(OptimizeAttr, Span),
194196
Repr(ThinVec<(ReprAttr, Span)>),
195197
RustcForceInline(Span, Option<Symbol>),
196198
Stability {
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
use rustc_attr_data_structures::{AttributeKind, OptimizeAttr};
2+
use rustc_feature::{AttributeTemplate, template};
3+
use rustc_span::sym;
4+
5+
use super::{AttributeOrder, OnDuplicate, SingleAttributeParser};
6+
use crate::context::{AcceptContext, Stage};
7+
use crate::parser::ArgParser;
8+
9+
pub(crate) struct OptimizeParser;
10+
11+
impl<S: Stage> SingleAttributeParser<S> for OptimizeParser {
12+
const PATH: &[rustc_span::Symbol] = &[sym::optimize];
13+
const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepLast;
14+
const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::WarnButFutureError;
15+
const TEMPLATE: AttributeTemplate = template!(List: "size|speed|none");
16+
17+
fn convert(cx: &AcceptContext<'_, '_, S>, args: &ArgParser<'_>) -> Option<AttributeKind> {
18+
let Some(list) = args.list() else {
19+
cx.expected_list(cx.attr_span);
20+
return None;
21+
};
22+
23+
let Some(single) = list.single() else {
24+
cx.expected_single_argument(list.span);
25+
return None;
26+
};
27+
28+
let res = match single.meta_item().and_then(|i| i.word_without_args().map(|i| i.name)) {
29+
Some(sym::size) => OptimizeAttr::Size,
30+
Some(sym::speed) => OptimizeAttr::Speed,
31+
Some(sym::none) => OptimizeAttr::DoNotOptimize,
32+
_ => {
33+
cx.expected_specific_argument(single.span(), vec!["size", "speed", "none"]);
34+
OptimizeAttr::Default
35+
}
36+
};
37+
38+
Some(AttributeKind::Optimize(res, cx.attr_span))
39+
}
40+
}

compiler/rustc_attr_parsing/src/attributes/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ use crate::session_diagnostics::{self, UnusedMultiple};
2828

2929
pub(crate) mod allow_unstable;
3030
pub(crate) mod cfg;
31+
pub(crate) mod codegen_attrs;
3132
pub(crate) mod confusables;
3233
pub(crate) mod deprecation;
3334
pub(crate) mod inline;

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::symbol::kw;
1717
use rustc_span::{DUMMY_SP, ErrorGuaranteed, Span, Symbol, sym};
1818

1919
use crate::attributes::allow_unstable::{AllowConstFnUnstableParser, AllowInternalUnstableParser};
20+
use crate::attributes::codegen_attrs::OptimizeParser;
2021
use crate::attributes::confusables::ConfusablesParser;
2122
use crate::attributes::deprecation::DeprecationParser;
2223
use crate::attributes::inline::{InlineParser, RustcForceInlineParser};
@@ -107,6 +108,7 @@ attribute_groups!(
107108
Single<ConstStabilityIndirectParser>,
108109
Single<DeprecationParser>,
109110
Single<InlineParser>,
111+
Single<OptimizeParser>,
110112
Single<RustcForceInlineParser>,
111113
Single<TransparencyParser>,
112114
// tidy-alphabetical-end

compiler/rustc_codegen_ssa/src/codegen_attrs.rs

Lines changed: 2 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -533,34 +533,8 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs {
533533
codegen_fn_attrs.inline = InlineAttr::Never;
534534
}
535535

536-
codegen_fn_attrs.optimize = attrs.iter().fold(OptimizeAttr::Default, |ia, attr| {
537-
if !attr.has_name(sym::optimize) {
538-
return ia;
539-
}
540-
let err = |sp, s| struct_span_code_err!(tcx.dcx(), sp, E0722, "{}", s).emit();
541-
if attr.is_word() {
542-
err(attr.span(), "expected one argument");
543-
return ia;
544-
}
545-
let Some(ref items) = attr.meta_item_list() else {
546-
return OptimizeAttr::Default;
547-
};
548-
549-
let [item] = &items[..] else {
550-
err(attr.span(), "expected one argument");
551-
return OptimizeAttr::Default;
552-
};
553-
if item.has_name(sym::size) {
554-
OptimizeAttr::Size
555-
} else if item.has_name(sym::speed) {
556-
OptimizeAttr::Speed
557-
} else if item.has_name(sym::none) {
558-
OptimizeAttr::DoNotOptimize
559-
} else {
560-
err(item.span(), "invalid argument");
561-
OptimizeAttr::Default
562-
}
563-
});
536+
codegen_fn_attrs.optimize =
537+
find_attr!(attrs, AttributeKind::Optimize(i, _) => *i).unwrap_or(OptimizeAttr::Default);
564538

565539
// #73631: closures inherit `#[target_feature]` annotations
566540
//

compiler/rustc_error_codes/src/error_codes/E0722.md

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,14 @@
1+
#### Note: this error code is no longer emitted by the compiler
2+
3+
This is because it was too specific to the `optimize` attribute.
4+
Similar diagnostics occur for other attributes too.
5+
The example here will now emit `E0539`
6+
17
The `optimize` attribute was malformed.
28

39
Erroneous code example:
410

5-
```compile_fail,E0722
11+
```compile_fail,E0539
612
#![feature(optimize_attribute)]
713
814
#[optimize(something)] // error: invalid argument

compiler/rustc_error_codes/src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -685,6 +685,7 @@ E0804: 0804,
685685
// E0707, // multiple elided lifetimes used in arguments of `async fn`
686686
// E0709, // multiple different lifetimes used in arguments of `async fn`
687687
// E0721, // `await` keyword
688+
// E0722, // replaced with a generic attribute input check
688689
// E0723, // unstable feature in `const` context
689690
// E0738, // Removed; errored on `#[track_caller] fn`s in `extern "Rust" { ... }`.
690691
// E0744, // merged into E0728

compiler/rustc_parse/src/validate_attr.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -243,6 +243,7 @@ fn emit_malformed_attribute(
243243
| sym::rustc_confusables
244244
| sym::repr
245245
| sym::deprecated
246+
| sym::optimize
246247
) {
247248
return;
248249
}

compiler/rustc_passes/src/check_attr.rs

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,9 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
128128
Attribute::Parsed(AttributeKind::Inline(_, attr_span)) => {
129129
self.check_inline(hir_id, *attr_span, span, target)
130130
}
131+
Attribute::Parsed(AttributeKind::Optimize(_, attr_span)) => {
132+
self.check_optimize(hir_id, *attr_span, span, target)
133+
}
131134
Attribute::Parsed(AttributeKind::AllowInternalUnstable(syms)) => self
132135
.check_allow_internal_unstable(
133136
hir_id,
@@ -145,7 +148,6 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
145148
self.check_diagnostic_on_unimplemented(attr.span(), hir_id, target)
146149
}
147150
[sym::coverage, ..] => self.check_coverage(attr, span, target),
148-
[sym::optimize, ..] => self.check_optimize(hir_id, attr, span, target),
149151
[sym::no_sanitize, ..] => {
150152
self.check_no_sanitize(attr, span, target)
151153
}
@@ -485,7 +487,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
485487

486488
/// Checks that `#[optimize(..)]` is applied to a function/closure/method,
487489
/// or to an impl block or module.
488-
fn check_optimize(&self, hir_id: HirId, attr: &Attribute, span: Span, target: Target) {
490+
fn check_optimize(&self, hir_id: HirId, attr_span: Span, span: Span, target: Target) {
489491
let is_valid = matches!(
490492
target,
491493
Target::Fn
@@ -494,7 +496,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
494496
);
495497
if !is_valid {
496498
self.dcx().emit_err(errors::OptimizeInvalidTarget {
497-
attr_span: attr.span(),
499+
attr_span,
498500
defn_span: span,
499501
on_crate: hir_id == CRATE_HIR_ID,
500502
});

tests/ui/feature-gates/feature-gate-optimize_attribute.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,5 +11,5 @@ fn none() {}
1111

1212
#[optimize(banana)]
1313
//~^ ERROR the `#[optimize]` attribute is an experimental feature
14-
//~| ERROR E0722
14+
//~| ERROR malformed `optimize` attribute input [E0539]
1515
fn not_known() {}

0 commit comments

Comments
 (0)