about summary refs log tree commit diff
diff options
context:
space:
mode:
authorEsteban Küber <esteban@osdyne.com>2025-09-16 11:38:08 -0700
committerEsteban Küber <esteban@osdyne.com>2025-09-16 11:38:08 -0700
commite9270e3cba3da56d4d83ed74f648e53b041cb263 (patch)
tree32a7be7d68e4f3a06b45634fa36007b9931f7388
parent8306a2f02e6c56447ff05b19b4b73c5c861e34fd (diff)
downloadrust-e9270e3cba3da56d4d83ed74f648e53b041cb263.tar.gz
rust-e9270e3cba3da56d4d83ed74f648e53b041cb263.zip
Detect top-level `...` in argument type
When writing something like the expression `|_: ...| {}`, we now detect the `...` during parsing explicitly instead of relying on the detection in `parse_ty_common` so that we don't talk about "nested `...` are not supported".

```
error: unexpected `...`
  --> $DIR/no-closure.rs:6:35
   |
LL | const F: extern "C" fn(...) = |_: ...| {};
   |                                   ^^^
   |
   = note: only `extern "C"` and `extern "C-unwind"` functions may have a C variable argument list
```
-rw-r--r--compiler/rustc_parse/messages.ftl3
-rw-r--r--compiler/rustc_parse/src/errors.rs8
-rw-r--r--compiler/rustc_parse/src/parser/ty.rs13
-rw-r--r--tests/ui/c-variadic/no-closure.rs8
-rw-r--r--tests/ui/c-variadic/no-closure.stderr13
5 files changed, 36 insertions, 9 deletions
diff --git a/compiler/rustc_parse/messages.ftl b/compiler/rustc_parse/messages.ftl
index 3a4c9348b32..f83cf645f82 100644
--- a/compiler/rustc_parse/messages.ftl
+++ b/compiler/rustc_parse/messages.ftl
@@ -191,6 +191,9 @@ parse_dotdotdot_rest_pattern = unexpected `...`
     .suggestion = for a rest pattern, use `..` instead of `...`
     .note = only `extern "C"` and `extern "C-unwind"` functions may have a C variable argument list
 
+parse_dotdotdot_rest_type = unexpected `...`
+    .note = only `extern "C"` and `extern "C-unwind"` functions may have a C variable argument list
+
 parse_double_colon_in_bound = expected `:` followed by trait or lifetime
     .suggestion = use single colon
 
diff --git a/compiler/rustc_parse/src/errors.rs b/compiler/rustc_parse/src/errors.rs
index 2b107fe35d5..1abeee6fe43 100644
--- a/compiler/rustc_parse/src/errors.rs
+++ b/compiler/rustc_parse/src/errors.rs
@@ -3033,6 +3033,14 @@ pub(crate) struct NestedCVariadicType {
 }
 
 #[derive(Diagnostic)]
+#[diag(parse_dotdotdot_rest_type)]
+#[note]
+pub(crate) struct InvalidCVariadicType {
+    #[primary_span]
+    pub span: Span,
+}
+
+#[derive(Diagnostic)]
 #[diag(parse_invalid_dyn_keyword)]
 #[help]
 pub(crate) struct InvalidDynKeyword {
diff --git a/compiler/rustc_parse/src/parser/ty.rs b/compiler/rustc_parse/src/parser/ty.rs
index 23aaafac934..65347496599 100644
--- a/compiler/rustc_parse/src/parser/ty.rs
+++ b/compiler/rustc_parse/src/parser/ty.rs
@@ -15,8 +15,8 @@ use super::{Parser, PathStyle, SeqSep, TokenType, Trailing};
 use crate::errors::{
     self, AttributeOnEmptyType, AttributeOnType, DynAfterMut, ExpectedFnPathFoundFnKeyword,
     ExpectedMutOrConstInRawPointerType, FnPtrWithGenerics, FnPtrWithGenericsSugg,
-    HelpUseLatestEdition, InvalidDynKeyword, LifetimeAfterMut, NeedPlusAfterTraitObjectLifetime,
-    NestedCVariadicType, ReturnTypesUseThinArrow,
+    HelpUseLatestEdition, InvalidCVariadicType, InvalidDynKeyword, LifetimeAfterMut,
+    NeedPlusAfterTraitObjectLifetime, NestedCVariadicType, ReturnTypesUseThinArrow,
 };
 use crate::parser::item::FrontMatterParsingMode;
 use crate::parser::{FnContext, FnParseMode};
@@ -106,6 +106,15 @@ fn can_begin_dyn_bound_in_edition_2015(t: &Token) -> bool {
 impl<'a> Parser<'a> {
     /// Parses a type.
     pub fn parse_ty(&mut self) -> PResult<'a, Box<Ty>> {
+        if self.token == token::DotDotDot {
+            // We special case this so that we don't talk about "nested C-variadics" in types.
+            // We still pass in `AllowCVariadic::No` so that `parse_ty_common` can complain about
+            // things like `Vec<...>`.
+            let span = self.token.span;
+            self.bump();
+            let kind = TyKind::Err(self.dcx().emit_err(InvalidCVariadicType { span }));
+            return Ok(self.mk_ty(span, kind));
+        }
         // Make sure deeply nested types don't overflow the stack.
         ensure_sufficient_stack(|| {
             self.parse_ty_common(
diff --git a/tests/ui/c-variadic/no-closure.rs b/tests/ui/c-variadic/no-closure.rs
index a5b791fbca8..830ed962a8c 100644
--- a/tests/ui/c-variadic/no-closure.rs
+++ b/tests/ui/c-variadic/no-closure.rs
@@ -4,13 +4,17 @@
 // Check that `...` in closures is rejected.
 
 const F: extern "C" fn(...) = |_: ...| {};
-//~^ ERROR C-variadic type `...` may not be nested inside another type
+//~^ ERROR: unexpected `...`
+//~| NOTE: only `extern "C"` and `extern "C-unwind"` functions may have a C variable argument list
 
 fn foo() {
     let f = |...| {};
     //~^ ERROR: unexpected `...`
+    //~| NOTE: not a valid pattern
+    //~| NOTE: only `extern "C"` and `extern "C-unwind"` functions may have a C variable argument list
 
     let f = |_: ...| {};
-    //~^ ERROR C-variadic type `...` may not be nested inside another type
+    //~^ ERROR: unexpected `...`
+    //~| NOTE: only `extern "C"` and `extern "C-unwind"` functions may have a C variable argument list
     f(1i64)
 }
diff --git a/tests/ui/c-variadic/no-closure.stderr b/tests/ui/c-variadic/no-closure.stderr
index 4b553c21597..0946c4632e6 100644
--- a/tests/ui/c-variadic/no-closure.stderr
+++ b/tests/ui/c-variadic/no-closure.stderr
@@ -1,23 +1,26 @@
-error[E0743]: C-variadic type `...` may not be nested inside another type
+error: unexpected `...`
   --> $DIR/no-closure.rs:6:35
    |
 LL | const F: extern "C" fn(...) = |_: ...| {};
    |                                   ^^^
+   |
+   = note: only `extern "C"` and `extern "C-unwind"` functions may have a C variable argument list
 
 error: unexpected `...`
-  --> $DIR/no-closure.rs:10:14
+  --> $DIR/no-closure.rs:11:14
    |
 LL |     let f = |...| {};
    |              ^^^ not a valid pattern
    |
    = note: only `extern "C"` and `extern "C-unwind"` functions may have a C variable argument list
 
-error[E0743]: C-variadic type `...` may not be nested inside another type
-  --> $DIR/no-closure.rs:13:17
+error: unexpected `...`
+  --> $DIR/no-closure.rs:16:17
    |
 LL |     let f = |_: ...| {};
    |                 ^^^
+   |
+   = note: only `extern "C"` and `extern "C-unwind"` functions may have a C variable argument list
 
 error: aborting due to 3 previous errors
 
-For more information about this error, try `rustc --explain E0743`.