From 74d4fbc5f5f68212d01a78738c207d5976fe13e4 Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Sun, 8 Dec 2019 06:32:58 +0100 Subject: [PATCH] De-fatalize `...` parsing. Also fix error the code description. --- src/librustc_error_codes/error_codes/E0743.md | 16 +++++++++---- src/librustc_parse/parser/ty.rs | 16 +++++++------ .../variadic-ffi-nested-syntactic-fail.rs | 9 +++++++ .../variadic-ffi-nested-syntactic-fail.stderr | 24 +++++++++++++++++++ 4 files changed, 53 insertions(+), 12 deletions(-) create mode 100644 src/test/ui/parser/variadic-ffi-nested-syntactic-fail.rs create mode 100644 src/test/ui/parser/variadic-ffi-nested-syntactic-fail.stderr diff --git a/src/librustc_error_codes/error_codes/E0743.md b/src/librustc_error_codes/error_codes/E0743.md index aaf19d8478c..1780fe59cbd 100644 --- a/src/librustc_error_codes/error_codes/E0743.md +++ b/src/librustc_error_codes/error_codes/E0743.md @@ -1,11 +1,17 @@ -C-variadic has been used on a non-foreign function. +The C-variadic type `...` has been nested inside another type. Erroneous code example: ```compile_fail,E0743 -fn foo2(x: u8, ...) {} // error! +#![feature(c_variadic)] + +fn foo2(x: u8, y: &...) {} // error! ``` -Only foreign functions can use C-variadic (`...`). It is used to give an -undefined number of parameters to a given function (like `printf` in C). The -equivalent in Rust would be to use macros directly. +Only foreign functions can use the C-variadic type (`...`). +In such functions, `...` may only occur non-nested. +That is, `y: &'a ...` is not allowed. + +A C-variadic type is used to give an undefined number +of parameters to a given function (like `printf` in C). +The equivalent in Rust would be to use macros directly. diff --git a/src/librustc_parse/parser/ty.rs b/src/librustc_parse/parser/ty.rs index 3ab290d1cbb..6f7ab0542d5 100644 --- a/src/librustc_parse/parser/ty.rs +++ b/src/librustc_parse/parser/ty.rs @@ -10,7 +10,7 @@ use syntax::ast::{self, Ty, TyKind, MutTy, BareFnTy, FunctionRetTy, GenericParam use syntax::ast::{TraitBoundModifier, TraitObjectSyntax, GenericBound, GenericBounds, PolyTraitRef}; use syntax::ast::{Mutability, AnonConst, Mac}; use syntax::token::{self, Token}; -use syntax::struct_span_fatal; +use syntax::struct_span_err; use syntax_pos::source_map::Span; use syntax_pos::symbol::kw; @@ -209,19 +209,21 @@ impl<'a> Parser<'a> { TyKind::Path(None, path) } } - } else if self.check(&token::DotDotDot) { + } else if self.eat(&token::DotDotDot) { if allow_c_variadic { - self.eat(&token::DotDotDot); TyKind::CVarArgs } else { // FIXME(Centril): Should we just allow `...` syntactically // anywhere in a type and use semantic restrictions instead? - return Err(struct_span_fatal!( + struct_span_err!( self.sess.span_diagnostic, - self.token.span, + lo.to(self.prev_span), E0743, - "only foreign functions are allowed to be C-variadic", - )); + "C-variadic type `...` may not be nested inside another type", + ) + .emit(); + + TyKind::Err } } else { let msg = format!("expected type, found {}", self.this_token_descr()); diff --git a/src/test/ui/parser/variadic-ffi-nested-syntactic-fail.rs b/src/test/ui/parser/variadic-ffi-nested-syntactic-fail.rs new file mode 100644 index 00000000000..9eeee195e56 --- /dev/null +++ b/src/test/ui/parser/variadic-ffi-nested-syntactic-fail.rs @@ -0,0 +1,9 @@ +fn f1<'a>(x: u8, y: &'a ...) {} +//~^ ERROR C-variadic type `...` may not be nested inside another type + +fn f2<'a>(x: u8, y: Vec<&'a ...>) {} +//~^ ERROR C-variadic type `...` may not be nested inside another type + +fn main() { + let _recovery_witness: () = 0; //~ ERROR mismatched types +} diff --git a/src/test/ui/parser/variadic-ffi-nested-syntactic-fail.stderr b/src/test/ui/parser/variadic-ffi-nested-syntactic-fail.stderr new file mode 100644 index 00000000000..8b9d676a45d --- /dev/null +++ b/src/test/ui/parser/variadic-ffi-nested-syntactic-fail.stderr @@ -0,0 +1,24 @@ +error[E0743]: C-variadic type `...` may not be nested inside another type + --> $DIR/variadic-ffi-nested-syntactic-fail.rs:1:25 + | +LL | fn f1<'a>(x: u8, y: &'a ...) {} + | ^^^ + +error[E0743]: C-variadic type `...` may not be nested inside another type + --> $DIR/variadic-ffi-nested-syntactic-fail.rs:4:29 + | +LL | fn f2<'a>(x: u8, y: Vec<&'a ...>) {} + | ^^^ + +error[E0308]: mismatched types + --> $DIR/variadic-ffi-nested-syntactic-fail.rs:8:33 + | +LL | let _recovery_witness: () = 0; + | -- ^ expected `()`, found integer + | | + | expected due to this + +error: aborting due to 3 previous errors + +Some errors have detailed explanations: E0308, E0743. +For more information about an error, try `rustc --explain E0308`.