diff options
| author | Esteban Küber <esteban@osdyne.com> | 2025-09-16 11:38:08 -0700 |
|---|---|---|
| committer | Esteban Küber <esteban@osdyne.com> | 2025-09-16 11:38:08 -0700 |
| commit | e9270e3cba3da56d4d83ed74f648e53b041cb263 (patch) | |
| tree | 32a7be7d68e4f3a06b45634fa36007b9931f7388 | |
| parent | 8306a2f02e6c56447ff05b19b4b73c5c861e34fd (diff) | |
| download | rust-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.ftl | 3 | ||||
| -rw-r--r-- | compiler/rustc_parse/src/errors.rs | 8 | ||||
| -rw-r--r-- | compiler/rustc_parse/src/parser/ty.rs | 13 | ||||
| -rw-r--r-- | tests/ui/c-variadic/no-closure.rs | 8 | ||||
| -rw-r--r-- | tests/ui/c-variadic/no-closure.stderr | 13 |
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`. |
