about summary refs log tree commit diff
diff options
context:
space:
mode:
authorMazdak Farrokhzad <twingoow@gmail.com>2019-12-08 06:32:58 +0100
committerMazdak Farrokhzad <twingoow@gmail.com>2019-12-12 18:05:05 +0100
commit74d4fbc5f5f68212d01a78738c207d5976fe13e4 (patch)
treef59091dcccb1661904d10849a1a896f98a2b8051
parente52f902a8ab3a1abbb200607db4766d95b27bc8e (diff)
downloadrust-74d4fbc5f5f68212d01a78738c207d5976fe13e4.tar.gz
rust-74d4fbc5f5f68212d01a78738c207d5976fe13e4.zip
De-fatalize `...` parsing.
Also fix error the code description.
-rw-r--r--src/librustc_error_codes/error_codes/E0743.md16
-rw-r--r--src/librustc_parse/parser/ty.rs16
-rw-r--r--src/test/ui/parser/variadic-ffi-nested-syntactic-fail.rs9
-rw-r--r--src/test/ui/parser/variadic-ffi-nested-syntactic-fail.stderr24
4 files changed, 53 insertions, 12 deletions
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`.