Skip to content

Commit e9270e3

Browse files
committed
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 ```
1 parent 8306a2f commit e9270e3

File tree

5 files changed

+36
-9
lines changed

5 files changed

+36
-9
lines changed

compiler/rustc_parse/messages.ftl

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -191,6 +191,9 @@ parse_dotdotdot_rest_pattern = unexpected `...`
191191
.suggestion = for a rest pattern, use `..` instead of `...`
192192
.note = only `extern "C"` and `extern "C-unwind"` functions may have a C variable argument list
193193
194+
parse_dotdotdot_rest_type = unexpected `...`
195+
.note = only `extern "C"` and `extern "C-unwind"` functions may have a C variable argument list
196+
194197
parse_double_colon_in_bound = expected `:` followed by trait or lifetime
195198
.suggestion = use single colon
196199

compiler/rustc_parse/src/errors.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3032,6 +3032,14 @@ pub(crate) struct NestedCVariadicType {
30323032
pub span: Span,
30333033
}
30343034

3035+
#[derive(Diagnostic)]
3036+
#[diag(parse_dotdotdot_rest_type)]
3037+
#[note]
3038+
pub(crate) struct InvalidCVariadicType {
3039+
#[primary_span]
3040+
pub span: Span,
3041+
}
3042+
30353043
#[derive(Diagnostic)]
30363044
#[diag(parse_invalid_dyn_keyword)]
30373045
#[help]

compiler/rustc_parse/src/parser/ty.rs

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,8 @@ use super::{Parser, PathStyle, SeqSep, TokenType, Trailing};
1515
use crate::errors::{
1616
self, AttributeOnEmptyType, AttributeOnType, DynAfterMut, ExpectedFnPathFoundFnKeyword,
1717
ExpectedMutOrConstInRawPointerType, FnPtrWithGenerics, FnPtrWithGenericsSugg,
18-
HelpUseLatestEdition, InvalidDynKeyword, LifetimeAfterMut, NeedPlusAfterTraitObjectLifetime,
19-
NestedCVariadicType, ReturnTypesUseThinArrow,
18+
HelpUseLatestEdition, InvalidCVariadicType, InvalidDynKeyword, LifetimeAfterMut,
19+
NeedPlusAfterTraitObjectLifetime, NestedCVariadicType, ReturnTypesUseThinArrow,
2020
};
2121
use crate::parser::item::FrontMatterParsingMode;
2222
use crate::parser::{FnContext, FnParseMode};
@@ -106,6 +106,15 @@ fn can_begin_dyn_bound_in_edition_2015(t: &Token) -> bool {
106106
impl<'a> Parser<'a> {
107107
/// Parses a type.
108108
pub fn parse_ty(&mut self) -> PResult<'a, Box<Ty>> {
109+
if self.token == token::DotDotDot {
110+
// We special case this so that we don't talk about "nested C-variadics" in types.
111+
// We still pass in `AllowCVariadic::No` so that `parse_ty_common` can complain about
112+
// things like `Vec<...>`.
113+
let span = self.token.span;
114+
self.bump();
115+
let kind = TyKind::Err(self.dcx().emit_err(InvalidCVariadicType { span }));
116+
return Ok(self.mk_ty(span, kind));
117+
}
109118
// Make sure deeply nested types don't overflow the stack.
110119
ensure_sufficient_stack(|| {
111120
self.parse_ty_common(

tests/ui/c-variadic/no-closure.rs

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,17 @@
44
// Check that `...` in closures is rejected.
55

66
const F: extern "C" fn(...) = |_: ...| {};
7-
//~^ ERROR C-variadic type `...` may not be nested inside another type
7+
//~^ ERROR: unexpected `...`
8+
//~| NOTE: only `extern "C"` and `extern "C-unwind"` functions may have a C variable argument list
89

910
fn foo() {
1011
let f = |...| {};
1112
//~^ ERROR: unexpected `...`
13+
//~| NOTE: not a valid pattern
14+
//~| NOTE: only `extern "C"` and `extern "C-unwind"` functions may have a C variable argument list
1215

1316
let f = |_: ...| {};
14-
//~^ ERROR C-variadic type `...` may not be nested inside another type
17+
//~^ ERROR: unexpected `...`
18+
//~| NOTE: only `extern "C"` and `extern "C-unwind"` functions may have a C variable argument list
1519
f(1i64)
1620
}

tests/ui/c-variadic/no-closure.stderr

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,26 @@
1-
error[E0743]: C-variadic type `...` may not be nested inside another type
1+
error: unexpected `...`
22
--> $DIR/no-closure.rs:6:35
33
|
44
LL | const F: extern "C" fn(...) = |_: ...| {};
55
| ^^^
6+
|
7+
= note: only `extern "C"` and `extern "C-unwind"` functions may have a C variable argument list
68

79
error: unexpected `...`
8-
--> $DIR/no-closure.rs:10:14
10+
--> $DIR/no-closure.rs:11:14
911
|
1012
LL | let f = |...| {};
1113
| ^^^ not a valid pattern
1214
|
1315
= note: only `extern "C"` and `extern "C-unwind"` functions may have a C variable argument list
1416

15-
error[E0743]: C-variadic type `...` may not be nested inside another type
16-
--> $DIR/no-closure.rs:13:17
17+
error: unexpected `...`
18+
--> $DIR/no-closure.rs:16:17
1719
|
1820
LL | let f = |_: ...| {};
1921
| ^^^
22+
|
23+
= note: only `extern "C"` and `extern "C-unwind"` functions may have a C variable argument list
2024

2125
error: aborting due to 3 previous errors
2226

23-
For more information about this error, try `rustc --explain E0743`.

0 commit comments

Comments
 (0)