Skip to content

Commit 9405e76

Browse files
committed
Detect attempt to use var-args in closure
``` error: unexpected `...` --> $DIR/varargs-in-closure-isnt-supported.rs:5:20 | LL | let mut lol = |...| (); | ^^^ not a valid pattern | = note: C-variadic type `...` is not allowed here ```
1 parent 52618eb commit 9405e76

File tree

5 files changed

+56
-9
lines changed

5 files changed

+56
-9
lines changed

compiler/rustc_parse/messages.ftl

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -189,6 +189,7 @@ parse_dotdotdot = unexpected token: `...`
189189
parse_dotdotdot_rest_pattern = unexpected `...`
190190
.label = not a valid pattern
191191
.suggestion = for a rest pattern, use `..` instead of `...`
192+
.note = C-variadic type `...` is not allowed here
192193
193194
parse_double_colon_in_bound = expected `:` followed by trait or lifetime
194195
.suggestion = use single colon

compiler/rustc_parse/src/errors.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2723,7 +2723,9 @@ pub(crate) struct DotDotDotRestPattern {
27232723
#[label]
27242724
pub span: Span,
27252725
#[suggestion(style = "verbose", code = "", applicability = "machine-applicable")]
2726-
pub suggestion: Span,
2726+
pub suggestion: Option<Span>,
2727+
#[note]
2728+
pub var_args: Option<()>,
27272729
}
27282730

27292731
#[derive(Diagnostic)]

compiler/rustc_parse/src/parser/pat.rs

Lines changed: 19 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -756,7 +756,7 @@ impl<'a> Parser<'a> {
756756
self.bump(); // `..`
757757
PatKind::Rest
758758
} else if self.check(exp!(DotDotDot)) && !self.is_pat_range_end_start(1) {
759-
self.recover_dotdotdot_rest_pat(lo)
759+
self.recover_dotdotdot_rest_pat(lo, expected)
760760
} else if let Some(form) = self.parse_range_end() {
761761
self.parse_pat_range_to(form)? // `..=X`, `...X`, or `..X`.
762762
} else if self.eat(exp!(Bang)) {
@@ -886,16 +886,27 @@ impl<'a> Parser<'a> {
886886

887887
/// Recover from a typoed `...` pattern that was encountered
888888
/// Ref: Issue #70388
889-
fn recover_dotdotdot_rest_pat(&mut self, lo: Span) -> PatKind {
889+
fn recover_dotdotdot_rest_pat(&mut self, lo: Span, expected: Option<Expected>) -> PatKind {
890890
// A typoed rest pattern `...`.
891891
self.bump(); // `...`
892892

893-
// The user probably mistook `...` for a rest pattern `..`.
894-
self.dcx().emit_err(DotDotDotRestPattern {
895-
span: lo,
896-
suggestion: lo.with_lo(lo.hi() - BytePos(1)),
897-
});
898-
PatKind::Rest
893+
if let Some(Expected::ParameterName) = expected {
894+
// We have `...` in a closure argument, likely meant to be var-arg, which aren't
895+
// supported in closures (#146489).
896+
PatKind::Err(self.dcx().emit_err(DotDotDotRestPattern {
897+
span: lo,
898+
suggestion: None,
899+
var_args: Some(()),
900+
}))
901+
} else {
902+
// The user probably mistook `...` for a rest pattern `..`.
903+
self.dcx().emit_err(DotDotDotRestPattern {
904+
span: lo,
905+
suggestion: Some(lo.with_lo(lo.hi() - BytePos(1))),
906+
var_args: None,
907+
});
908+
PatKind::Rest
909+
}
899910
}
900911

901912
/// Try to recover the more general form `intersect ::= $pat_lhs @ $pat_rhs`.
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
// var-args are not supported in closures, ensure we don't misdirect people (#146489)
2+
#![feature(c_variadic)]
3+
4+
unsafe extern "C" fn thats_not_a_pattern(mut ap: ...) -> u32 {
5+
let mut lol = |...| (); //~ ERROR: unexpected `...`
6+
unsafe { ap.arg::<u32>() } //~^ NOTE: C-variadic type `...` is not allowed here
7+
//~| ERROR: type annotations needed
8+
//~| NOTE: not a valid pattern
9+
}
10+
11+
fn main() {}
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
error: unexpected `...`
2+
--> $DIR/varargs-in-closure-isnt-supported.rs:5:20
3+
|
4+
LL | let mut lol = |...| ();
5+
| ^^^ not a valid pattern
6+
|
7+
= note: C-variadic type `...` is not allowed here
8+
9+
error[E0282]: type annotations needed
10+
--> $DIR/varargs-in-closure-isnt-supported.rs:5:20
11+
|
12+
LL | let mut lol = |...| ();
13+
| ^^^
14+
|
15+
help: consider giving this closure parameter an explicit type
16+
|
17+
LL | let mut lol = |...: /* Type */| ();
18+
| ++++++++++++
19+
20+
error: aborting due to 2 previous errors
21+
22+
For more information about this error, try `rustc --explain E0282`.

0 commit comments

Comments
 (0)