about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--compiler/rustc_ast_passes/messages.ftl4
-rw-r--r--compiler/rustc_ast_passes/src/ast_validation.rs9
-rw-r--r--compiler/rustc_ast_passes/src/errors.rs12
-rw-r--r--tests/ui/c-variadic/not-async.rs7
-rw-r--r--tests/ui/c-variadic/not-async.stderr19
-rw-r--r--tests/ui/inference/note-and-explain-ReVar-124973.rs3
-rw-r--r--tests/ui/inference/note-and-explain-ReVar-124973.stderr8
7 files changed, 60 insertions, 2 deletions
diff --git a/compiler/rustc_ast_passes/messages.ftl b/compiler/rustc_ast_passes/messages.ftl
index e5f1fcdc4b4..68ac2a05a48 100644
--- a/compiler/rustc_ast_passes/messages.ftl
+++ b/compiler/rustc_ast_passes/messages.ftl
@@ -84,6 +84,10 @@ ast_passes_const_without_body =
 ast_passes_constraint_on_negative_bound =
     associated type constraints not allowed on negative bounds
 
+ast_passes_coroutine_and_c_variadic = functions cannot be both `{$coroutine_kind}` and C-variadic
+    .const = `{$coroutine_kind}` because of this
+    .variadic = C-variadic because of this
+
 ast_passes_equality_in_where = equality constraints are not yet supported in `where` clauses
     .label = not supported
     .suggestion = if `{$ident}` is an associated type you're trying to set, use the associated type binding syntax
diff --git a/compiler/rustc_ast_passes/src/ast_validation.rs b/compiler/rustc_ast_passes/src/ast_validation.rs
index 538918a890d..672c1e94418 100644
--- a/compiler/rustc_ast_passes/src/ast_validation.rs
+++ b/compiler/rustc_ast_passes/src/ast_validation.rs
@@ -685,6 +685,15 @@ impl<'a> AstValidator<'a> {
             });
         }
 
+        if let Some(coroutine_kind) = sig.header.coroutine_kind {
+            self.dcx().emit_err(errors::CoroutineAndCVariadic {
+                spans: vec![coroutine_kind.span(), variadic_param.span],
+                coroutine_kind: coroutine_kind.as_str(),
+                coroutine_span: coroutine_kind.span(),
+                variadic_span: variadic_param.span,
+            });
+        }
+
         match fn_ctxt {
             FnCtxt::Foreign => return,
             FnCtxt::Free => match sig.header.ext {
diff --git a/compiler/rustc_ast_passes/src/errors.rs b/compiler/rustc_ast_passes/src/errors.rs
index 476ed27a10e..f8806ef21c1 100644
--- a/compiler/rustc_ast_passes/src/errors.rs
+++ b/compiler/rustc_ast_passes/src/errors.rs
@@ -660,6 +660,18 @@ pub(crate) struct ConstAndCVariadic {
 }
 
 #[derive(Diagnostic)]
+#[diag(ast_passes_coroutine_and_c_variadic)]
+pub(crate) struct CoroutineAndCVariadic {
+    #[primary_span]
+    pub spans: Vec<Span>,
+    pub coroutine_kind: &'static str,
+    #[label(ast_passes_const)]
+    pub coroutine_span: Span,
+    #[label(ast_passes_variadic)]
+    pub variadic_span: Span,
+}
+
+#[derive(Diagnostic)]
 #[diag(ast_passes_pattern_in_foreign, code = E0130)]
 // FIXME: deduplicate with rustc_lint (`BuiltinLintDiag::PatternsInFnsWithoutBody`)
 pub(crate) struct PatternInForeign {
diff --git a/tests/ui/c-variadic/not-async.rs b/tests/ui/c-variadic/not-async.rs
new file mode 100644
index 00000000000..45a7e1f8972
--- /dev/null
+++ b/tests/ui/c-variadic/not-async.rs
@@ -0,0 +1,7 @@
+//@ edition: 2021
+#![feature(c_variadic)]
+#![crate_type = "lib"]
+
+async unsafe extern "C" fn cannot_be_async(x: isize, ...) {}
+//~^ ERROR functions cannot be both `async` and C-variadic
+//~| ERROR hidden type for `impl Future<Output = ()>` captures lifetime that does not appear in bounds
diff --git a/tests/ui/c-variadic/not-async.stderr b/tests/ui/c-variadic/not-async.stderr
new file mode 100644
index 00000000000..b8caf0d8bd8
--- /dev/null
+++ b/tests/ui/c-variadic/not-async.stderr
@@ -0,0 +1,19 @@
+error: functions cannot be both `async` and C-variadic
+  --> $DIR/not-async.rs:5:1
+   |
+LL | async unsafe extern "C" fn cannot_be_async(x: isize, ...) {}
+   | ^^^^^ `async` because of this                        ^^^ C-variadic because of this
+
+error[E0700]: hidden type for `impl Future<Output = ()>` captures lifetime that does not appear in bounds
+  --> $DIR/not-async.rs:5:59
+   |
+LL | async unsafe extern "C" fn cannot_be_async(x: isize, ...) {}
+   | --------------------------------------------------------- ^^
+   | |
+   | opaque type defined here
+   |
+   = note: hidden type `{async fn body of cannot_be_async()}` captures lifetime `'_`
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0700`.
diff --git a/tests/ui/inference/note-and-explain-ReVar-124973.rs b/tests/ui/inference/note-and-explain-ReVar-124973.rs
index f1e24645636..aa4b909fa76 100644
--- a/tests/ui/inference/note-and-explain-ReVar-124973.rs
+++ b/tests/ui/inference/note-and-explain-ReVar-124973.rs
@@ -3,6 +3,7 @@
 #![feature(c_variadic)]
 
 async unsafe extern "C" fn multiple_named_lifetimes<'a, 'b>(_: u8, ...) {}
-//~^ ERROR hidden type for `impl Future<Output = ()>` captures lifetime that does not appear in bounds
+//~^ ERROR functions cannot be both `async` and C-variadic
+//~| ERROR hidden type for `impl Future<Output = ()>` captures lifetime that does not appear in bounds
 
 fn main() {}
diff --git a/tests/ui/inference/note-and-explain-ReVar-124973.stderr b/tests/ui/inference/note-and-explain-ReVar-124973.stderr
index 574f6508e4c..964fbc4a4fb 100644
--- a/tests/ui/inference/note-and-explain-ReVar-124973.stderr
+++ b/tests/ui/inference/note-and-explain-ReVar-124973.stderr
@@ -1,3 +1,9 @@
+error: functions cannot be both `async` and C-variadic
+  --> $DIR/note-and-explain-ReVar-124973.rs:5:1
+   |
+LL | async unsafe extern "C" fn multiple_named_lifetimes<'a, 'b>(_: u8, ...) {}
+   | ^^^^^ `async` because of this                                      ^^^ C-variadic because of this
+
 error[E0700]: hidden type for `impl Future<Output = ()>` captures lifetime that does not appear in bounds
   --> $DIR/note-and-explain-ReVar-124973.rs:5:73
    |
@@ -8,6 +14,6 @@ LL | async unsafe extern "C" fn multiple_named_lifetimes<'a, 'b>(_: u8, ...) {}
    |
    = note: hidden type `{async fn body of multiple_named_lifetimes<'a, 'b>()}` captures lifetime `'_`
 
-error: aborting due to 1 previous error
+error: aborting due to 2 previous errors
 
 For more information about this error, try `rustc --explain E0700`.