From 594de02cbacccd3a220c69971e085bfd76a84eac Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Wed, 11 Sep 2024 18:22:37 -0400 Subject: [PATCH] Properly deny const gen/async gen fns --- compiler/rustc_ast/src/ast.rs | 8 ++++++++ compiler/rustc_ast_passes/messages.ftl | 10 +++++----- .../rustc_ast_passes/src/ast_validation.rs | 17 ++++++---------- compiler/rustc_ast_passes/src/errors.rs | 11 +++++----- tests/ui/coroutine/const_gen_fn.rs | 12 +++++++++++ tests/ui/coroutine/const_gen_fn.stderr | 20 +++++++++++++++++++ 6 files changed, 57 insertions(+), 21 deletions(-) create mode 100644 tests/ui/coroutine/const_gen_fn.rs create mode 100644 tests/ui/coroutine/const_gen_fn.stderr diff --git a/compiler/rustc_ast/src/ast.rs b/compiler/rustc_ast/src/ast.rs index 42741bdca22..1fb85abcbfa 100644 --- a/compiler/rustc_ast/src/ast.rs +++ b/compiler/rustc_ast/src/ast.rs @@ -2602,6 +2602,14 @@ impl CoroutineKind { } } + pub fn as_str(self) -> &'static str { + match self { + CoroutineKind::Async { .. } => "async", + CoroutineKind::Gen { .. } => "gen", + CoroutineKind::AsyncGen { .. } => "async gen", + } + } + pub fn is_async(self) -> bool { matches!(self, CoroutineKind::Async { .. }) } diff --git a/compiler/rustc_ast_passes/messages.ftl b/compiler/rustc_ast_passes/messages.ftl index df5c639382f..c361c35b723 100644 --- a/compiler/rustc_ast_passes/messages.ftl +++ b/compiler/rustc_ast_passes/messages.ftl @@ -40,15 +40,15 @@ ast_passes_body_in_extern = incorrect `{$kind}` inside `extern` block ast_passes_bound_in_context = bounds on `type`s in {$ctx} have no effect -ast_passes_const_and_async = functions cannot be both `const` and `async` - .const = `const` because of this - .async = `async` because of this - .label = {""} - ast_passes_const_and_c_variadic = functions cannot be both `const` and C-variadic .const = `const` because of this .variadic = C-variadic because of this +ast_passes_const_and_coroutine = functions cannot be both `const` and `{$coroutine_kind}` + .const = `const` because of this + .coroutine = `{$coroutine_kind}` because of this + .label = {""} + ast_passes_const_bound_trait_object = const trait bounds are not allowed in trait object types ast_passes_const_without_body = diff --git a/compiler/rustc_ast_passes/src/ast_validation.rs b/compiler/rustc_ast_passes/src/ast_validation.rs index ed9672a9e79..f6731c6bd54 100644 --- a/compiler/rustc_ast_passes/src/ast_validation.rs +++ b/compiler/rustc_ast_passes/src/ast_validation.rs @@ -1418,21 +1418,16 @@ impl<'a> Visitor<'a> for AstValidator<'a> { // Functions cannot both be `const async` or `const gen` if let Some(&FnHeader { - constness: Const::Yes(cspan), + constness: Const::Yes(const_span), coroutine_kind: Some(coroutine_kind), .. }) = fk.header() { - let aspan = match coroutine_kind { - CoroutineKind::Async { span: aspan, .. } - | CoroutineKind::Gen { span: aspan, .. } - | CoroutineKind::AsyncGen { span: aspan, .. } => aspan, - }; - // FIXME(gen_blocks): Report a different error for `const gen` - self.dcx().emit_err(errors::ConstAndAsync { - spans: vec![cspan, aspan], - cspan, - aspan, + self.dcx().emit_err(errors::ConstAndCoroutine { + spans: vec![coroutine_kind.span(), const_span], + const_span, + coroutine_span: coroutine_kind.span(), + coroutine_kind: coroutine_kind.as_str(), span, }); } diff --git a/compiler/rustc_ast_passes/src/errors.rs b/compiler/rustc_ast_passes/src/errors.rs index 67c0396333c..5cce47ce7bd 100644 --- a/compiler/rustc_ast_passes/src/errors.rs +++ b/compiler/rustc_ast_passes/src/errors.rs @@ -657,16 +657,17 @@ pub(crate) enum TildeConstReason { } #[derive(Diagnostic)] -#[diag(ast_passes_const_and_async)] -pub(crate) struct ConstAndAsync { +#[diag(ast_passes_const_and_coroutine)] +pub(crate) struct ConstAndCoroutine { #[primary_span] pub spans: Vec, #[label(ast_passes_const)] - pub cspan: Span, - #[label(ast_passes_async)] - pub aspan: Span, + pub const_span: Span, + #[label(ast_passes_coroutine)] + pub coroutine_span: Span, #[label] pub span: Span, + pub coroutine_kind: &'static str, } #[derive(Diagnostic)] diff --git a/tests/ui/coroutine/const_gen_fn.rs b/tests/ui/coroutine/const_gen_fn.rs new file mode 100644 index 00000000000..986693f33ab --- /dev/null +++ b/tests/ui/coroutine/const_gen_fn.rs @@ -0,0 +1,12 @@ +//@ edition:2024 +//@ compile-flags: -Zunstable-options + +#![feature(gen_blocks)] + +const gen fn a() {} +//~^ ERROR functions cannot be both `const` and `gen` + +const async gen fn b() {} +//~^ ERROR functions cannot be both `const` and `async gen` + +fn main() {} diff --git a/tests/ui/coroutine/const_gen_fn.stderr b/tests/ui/coroutine/const_gen_fn.stderr new file mode 100644 index 00000000000..b58446ac88f --- /dev/null +++ b/tests/ui/coroutine/const_gen_fn.stderr @@ -0,0 +1,20 @@ +error: functions cannot be both `const` and `gen` + --> $DIR/const_gen_fn.rs:6:1 + | +LL | const gen fn a() {} + | ^^^^^-^^^---------- + | | | + | | `gen` because of this + | `const` because of this + +error: functions cannot be both `const` and `async gen` + --> $DIR/const_gen_fn.rs:9:1 + | +LL | const async gen fn b() {} + | ^^^^^-^^^^^^^^^---------- + | | | + | | `async gen` because of this + | `const` because of this + +error: aborting due to 2 previous errors +