diff --git a/compiler/rustc_passes/messages.ftl b/compiler/rustc_passes/messages.ftl index e5a14f6a156..3613b7b862d 100644 --- a/compiler/rustc_passes/messages.ftl +++ b/compiler/rustc_passes/messages.ftl @@ -553,9 +553,9 @@ passes_only_has_effect_on = *[unspecified] (unspecified--this is a compiler bug) } -passes_optimize_not_fn_or_closure = - attribute should be applied to function or closure - .label = not a function or closure +passes_optimize_invalid_target = + attribute applied to an invalid target + .label = invalid target passes_outer_crate_level_attr = crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]` diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs index 4516ea94cad..8b30546d5cc 100644 --- a/compiler/rustc_passes/src/check_attr.rs +++ b/compiler/rustc_passes/src/check_attr.rs @@ -124,7 +124,7 @@ fn check_attributes( } [sym::inline, ..] => self.check_inline(hir_id, attr, span, target), [sym::coverage, ..] => self.check_coverage(attr, span, target), - [sym::optimize, ..] => self.check_optimize(hir_id, attr, target), + [sym::optimize, ..] => self.check_optimize(hir_id, attr, span, target), [sym::no_sanitize, ..] => { self.check_applied_to_fn_or_method(hir_id, attr, span, target) } @@ -433,23 +433,19 @@ fn check_coverage(&self, attr: &Attribute, span: Span, target: Target) { /// Checks that `#[optimize(..)]` is applied to a function/closure/method, /// or to an impl block or module. - // FIXME(#128488): this should probably be elevated to an error? - fn check_optimize(&self, hir_id: HirId, attr: &Attribute, target: Target) { - match target { + fn check_optimize(&self, hir_id: HirId, attr: &Attribute, span: Span, target: Target) { + let is_valid = matches!( + target, Target::Fn - | Target::Closure - | Target::Method(MethodKind::Trait { body: true } | MethodKind::Inherent) - | Target::Impl - | Target::Mod => {} - - _ => { - self.tcx.emit_node_span_lint( - UNUSED_ATTRIBUTES, - hir_id, - attr.span, - errors::OptimizeNotFnOrClosure, - ); - } + | Target::Closure + | Target::Method(MethodKind::Trait { body: true } | MethodKind::Inherent) + ); + if !is_valid { + self.dcx().emit_err(errors::OptimizeInvalidTarget { + attr_span: attr.span, + defn_span: span, + on_crate: hir_id == CRATE_HIR_ID, + }); } } diff --git a/compiler/rustc_passes/src/errors.rs b/compiler/rustc_passes/src/errors.rs index 6dc3dfba58f..f01ddbd47ef 100644 --- a/compiler/rustc_passes/src/errors.rs +++ b/compiler/rustc_passes/src/errors.rs @@ -76,9 +76,15 @@ pub(crate) struct CoverageNotFnOrClosure { pub defn_span: Span, } -#[derive(LintDiagnostic)] -#[diag(passes_optimize_not_fn_or_closure)] -pub(crate) struct OptimizeNotFnOrClosure; +#[derive(Diagnostic)] +#[diag(passes_optimize_invalid_target)] +pub(crate) struct OptimizeInvalidTarget { + #[primary_span] + pub attr_span: Span, + #[label] + pub defn_span: Span, + pub on_crate: bool, +} #[derive(Diagnostic)] #[diag(passes_should_be_applied_to_fn)] diff --git a/tests/ui/attributes/optimize.rs b/tests/ui/attributes/optimize.rs index b01806165c1..7a1cc1be9ee 100644 --- a/tests/ui/attributes/optimize.rs +++ b/tests/ui/attributes/optimize.rs @@ -3,11 +3,13 @@ #![deny(unused_attributes)] #![allow(dead_code)] -#[optimize(speed)] //~ ERROR attribute should be applied to function or closure +//@ edition: 2018 + +#[optimize(speed)] //~ ERROR attribute applied to an invalid target struct F; fn invalid() { - #[optimize(speed)] //~ ERROR attribute should be applied to function or closure + #[optimize(speed)] //~ ERROR attribute applied to an invalid target { 1 }; @@ -16,13 +18,25 @@ fn invalid() { #[optimize(speed)] fn valid() {} -#[optimize(speed)] +#[optimize(speed)] //~ ERROR attribute applied to an invalid target mod valid_module {} -#[optimize(speed)] +#[optimize(speed)] //~ ERROR attribute applied to an invalid target impl F {} fn main() { let _ = #[optimize(speed)] (|| 1); } + +use std::future::Future; + +fn async_block() -> impl Future { + #[optimize(speed)] + async { } +} + +#[optimize(speed)] +async fn async_fn() { + () +} diff --git a/tests/ui/attributes/optimize.stderr b/tests/ui/attributes/optimize.stderr index 3c445d73c2e..ad9309d27a5 100644 --- a/tests/ui/attributes/optimize.stderr +++ b/tests/ui/attributes/optimize.stderr @@ -1,20 +1,36 @@ -error: attribute should be applied to function or closure - --> $DIR/optimize.rs:6:1 +error: attribute applied to an invalid target + --> $DIR/optimize.rs:8:1 | LL | #[optimize(speed)] | ^^^^^^^^^^^^^^^^^^ - | -note: the lint level is defined here - --> $DIR/optimize.rs:3:9 - | -LL | #![deny(unused_attributes)] - | ^^^^^^^^^^^^^^^^^ +LL | struct F; + | --------- invalid target -error: attribute should be applied to function or closure - --> $DIR/optimize.rs:10:5 +error: attribute applied to an invalid target + --> $DIR/optimize.rs:12:5 | -LL | #[optimize(speed)] - | ^^^^^^^^^^^^^^^^^^ +LL | #[optimize(speed)] + | ^^^^^^^^^^^^^^^^^^ +LL | / { +LL | | 1 +LL | | }; + | |_____- invalid target -error: aborting due to 2 previous errors +error: attribute applied to an invalid target + --> $DIR/optimize.rs:21:1 + | +LL | #[optimize(speed)] + | ^^^^^^^^^^^^^^^^^^ +LL | mod valid_module {} + | ------------------- invalid target + +error: attribute applied to an invalid target + --> $DIR/optimize.rs:24:1 + | +LL | #[optimize(speed)] + | ^^^^^^^^^^^^^^^^^^ +LL | impl F {} + | --------- invalid target + +error: aborting due to 4 previous errors diff --git a/tests/ui/coroutine/other-attribute-on-gen.rs b/tests/ui/coroutine/other-attribute-on-gen.rs new file mode 100644 index 00000000000..0f26dc6860d --- /dev/null +++ b/tests/ui/coroutine/other-attribute-on-gen.rs @@ -0,0 +1,40 @@ +//@ edition: 2024 +//@ compile-flags: -Zunstable-options +//@ run-pass +#![feature(gen_blocks)] +#![feature(optimize_attribute)] +#![feature(stmt_expr_attributes)] +#![feature(async_iterator)] +#![allow(dead_code)] + +// make sure that other attributes e.g. `optimize` can be applied to gen blocks and functions + +fn main() { } + +fn optimize_gen_block() -> impl Iterator { + #[optimize(speed)] + gen { yield (); } +} + +#[optimize(speed)] +gen fn optimize_gen_fn() -> i32 { + yield 1; + yield 2; + yield 3; +} + +#[optimize(speed)] +async gen fn optimize_async_gen_fn() -> i32 { + yield 1; + yield 2; + yield 3; +} + +use std::async_iter::AsyncIterator; + +pub fn deduce() -> impl AsyncIterator { + #[optimize(size)] + async gen { + yield (); + } +} diff --git a/tests/ui/feature-gates/feature-gate-optimize_attribute.rs b/tests/ui/feature-gates/feature-gate-optimize_attribute.rs index 15aa3a6af4c..7f9cada6a47 100644 --- a/tests/ui/feature-gates/feature-gate-optimize_attribute.rs +++ b/tests/ui/feature-gates/feature-gate-optimize_attribute.rs @@ -1,8 +1,4 @@ #![crate_type="rlib"] -#![optimize(speed)] //~ ERROR the `#[optimize]` attribute is an experimental feature - -#[optimize(size)] //~ ERROR the `#[optimize]` attribute is an experimental feature -mod module { #[optimize(size)] //~ ERROR the `#[optimize]` attribute is an experimental feature fn size() {} @@ -14,5 +10,3 @@ fn speed() {} //~^ ERROR the `#[optimize]` attribute is an experimental feature //~| ERROR E0722 fn not_known() {} - -} diff --git a/tests/ui/feature-gates/feature-gate-optimize_attribute.stderr b/tests/ui/feature-gates/feature-gate-optimize_attribute.stderr index 609526150ba..ca8f4a078f0 100644 --- a/tests/ui/feature-gates/feature-gate-optimize_attribute.stderr +++ b/tests/ui/feature-gates/feature-gate-optimize_attribute.stderr @@ -1,15 +1,5 @@ error[E0658]: the `#[optimize]` attribute is an experimental feature - --> $DIR/feature-gate-optimize_attribute.rs:2:1 - | -LL | #![optimize(speed)] - | ^^^^^^^^^^^^^^^^^^^ - | - = note: see issue #54882 for more information - = help: add `#![feature(optimize_attribute)]` to the crate attributes to enable - = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date - -error[E0658]: the `#[optimize]` attribute is an experimental feature - --> $DIR/feature-gate-optimize_attribute.rs:4:1 + --> $DIR/feature-gate-optimize_attribute.rs:3:1 | LL | #[optimize(size)] | ^^^^^^^^^^^^^^^^^ @@ -19,17 +9,7 @@ LL | #[optimize(size)] = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0658]: the `#[optimize]` attribute is an experimental feature - --> $DIR/feature-gate-optimize_attribute.rs:7:1 - | -LL | #[optimize(size)] - | ^^^^^^^^^^^^^^^^^ - | - = note: see issue #54882 for more information - = help: add `#![feature(optimize_attribute)]` to the crate attributes to enable - = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date - -error[E0658]: the `#[optimize]` attribute is an experimental feature - --> $DIR/feature-gate-optimize_attribute.rs:10:1 + --> $DIR/feature-gate-optimize_attribute.rs:6:1 | LL | #[optimize(speed)] | ^^^^^^^^^^^^^^^^^^ @@ -39,7 +19,7 @@ LL | #[optimize(speed)] = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0658]: the `#[optimize]` attribute is an experimental feature - --> $DIR/feature-gate-optimize_attribute.rs:13:1 + --> $DIR/feature-gate-optimize_attribute.rs:9:1 | LL | #[optimize(banana)] | ^^^^^^^^^^^^^^^^^^^ @@ -49,12 +29,12 @@ LL | #[optimize(banana)] = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0722]: invalid argument - --> $DIR/feature-gate-optimize_attribute.rs:13:12 + --> $DIR/feature-gate-optimize_attribute.rs:9:12 | LL | #[optimize(banana)] | ^^^^^^ -error: aborting due to 6 previous errors +error: aborting due to 4 previous errors Some errors have detailed explanations: E0658, E0722. For more information about an error, try `rustc --explain E0658`.