about summary refs log tree commit diff
diff options
context:
space:
mode:
authorMichael Goulet <michael@errs.io>2024-09-11 18:22:37 -0400
committerMichael Goulet <michael@errs.io>2024-09-11 18:39:06 -0400
commit594de02cbacccd3a220c69971e085bfd76a84eac (patch)
tree2cb1e063a08428e7a3a563b68d703814c989e602
parent8d6b88b168e45ee1624699c19443c49665322a91 (diff)
downloadrust-594de02cbacccd3a220c69971e085bfd76a84eac.tar.gz
rust-594de02cbacccd3a220c69971e085bfd76a84eac.zip
Properly deny const gen/async gen fns
-rw-r--r--compiler/rustc_ast/src/ast.rs8
-rw-r--r--compiler/rustc_ast_passes/messages.ftl10
-rw-r--r--compiler/rustc_ast_passes/src/ast_validation.rs17
-rw-r--r--compiler/rustc_ast_passes/src/errors.rs11
-rw-r--r--tests/ui/coroutine/const_gen_fn.rs12
-rw-r--r--tests/ui/coroutine/const_gen_fn.stderr20
6 files changed, 57 insertions, 21 deletions
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<Span>,
     #[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
+