]> git.lizzy.rs Git - rust.git/commitdiff
Introduce `TyErr` independent from `TyInfer`
authorEsteban Küber <esteban@kuber.com.ar>
Wed, 29 Mar 2017 01:56:29 +0000 (18:56 -0700)
committerEsteban Küber <esteban@kuber.com.ar>
Sun, 2 Apr 2017 16:45:57 +0000 (09:45 -0700)
Add a `TyErr` type to represent unknown types in places where
parse errors have happened, while still able to build the AST.

Initially only used to represent incorrectly written fn arguments and
avoid "expected X parameters, found Y" errors when called with the
appropriate amount of parameters. We cannot use `TyInfer` for this as
`_` is not allowed as a valid argument type.

Example output:

```rust
error: expected one of `:` or `@`, found `,`
  --> file.rs:12:9
   |
12 | fn bar(x, y: usize) {}
   |         ^

error[E0061]: this function takes 2 parameters but 3 parameters were supplied
  --> file.rs:19:9
   |
12 | fn bar(x, y) {}
   | --------------- defined here
...
19 |     bar(1, 2, 3);
   |         ^^^^^^^ expected 2 parameters
```

14 files changed:
src/librustc/hir/intravisit.rs
src/librustc/hir/lowering.rs
src/librustc/hir/mod.rs
src/librustc/hir/print.rs
src/librustc_incremental/calculate_svh/svh_visitor.rs
src/librustc_typeck/astconv.rs
src/librustdoc/clean/mod.rs
src/libsyntax/ast.rs
src/libsyntax/fold.rs
src/libsyntax/parse/parser.rs
src/libsyntax/print/pprust.rs
src/libsyntax/visit.rs
src/test/ui/span/issue-34264.rs [new file with mode: 0644]
src/test/ui/span/issue-34264.stderr [new file with mode: 0644]

index c7ad143c94979762f7ac060dc2be4ba9e91a865a..2c8b145f126cd17ffb05ddd7c805dc4dc9c21132 100644 (file)
@@ -578,7 +578,7 @@ pub fn walk_ty<'v, V: Visitor<'v>>(visitor: &mut V, typ: &'v Ty) {
         TyTypeof(expression) => {
             visitor.visit_nested_body(expression)
         }
-        TyInfer => {}
+        TyInfer | TyErr => {}
     }
 }
 
index 17185a6ab69f493399e327afc94c8504c5f84a11..acc6d21ddc696044a064c051ac227e1982e25c67 100644 (file)
@@ -555,6 +555,7 @@ fn lower_ty_binding(&mut self, b: &TypeBinding) -> hir::TypeBinding {
     fn lower_ty(&mut self, t: &Ty) -> P<hir::Ty> {
         let kind = match t.node {
             TyKind::Infer => hir::TyInfer,
+            TyKind::Err => hir::TyErr,
             TyKind::Slice(ref ty) => hir::TySlice(self.lower_ty(ty)),
             TyKind::Ptr(ref mt) => hir::TyPtr(self.lower_mt(mt)),
             TyKind::Rptr(ref region, ref mt) => {
index d5000ac9c18669a3940bbea0a4629eaa6645d614..0da405d1821d360d8d804ae6463a7f42af706e86 100644 (file)
@@ -1351,6 +1351,8 @@ pub enum Ty_ {
     /// TyInfer means the type should be inferred instead of it having been
     /// specified. This can appear anywhere in a type.
     TyInfer,
+    /// Placeholder for a type that has failed to be defined.
+    TyErr,
 }
 
 #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
index 04a65fd5e3aa47c0a748993578135da24124bf5b..4a5a35aa82ca0ef5799733d4021f2c4d86e49c50 100644 (file)
@@ -450,6 +450,9 @@ pub fn print_type(&mut self, ty: &hir::Ty) -> io::Result<()> {
             hir::TyInfer => {
                 word(&mut self.s, "_")?;
             }
+            hir::TyErr => {
+                word(&mut self.s, "?")?;
+            }
         }
         self.end()
     }
index 5401b371888e939c58b6b3145b5f3faf67aa5315..4700b77be07629738dfa00477c6ccb256fb086c5 100644 (file)
@@ -432,7 +432,8 @@ enum SawTyComponent {
     SawTyObjectSum,
     SawTyImplTrait,
     SawTyTypeof,
-    SawTyInfer
+    SawTyInfer,
+    SawTyErr,
 }
 
 fn saw_ty(node: &Ty_) -> SawTyComponent {
@@ -448,7 +449,8 @@ fn saw_ty(node: &Ty_) -> SawTyComponent {
       TyTraitObject(..) => SawTyObjectSum,
       TyImplTrait(..) => SawTyImplTrait,
       TyTypeof(..) => SawTyTypeof,
-      TyInfer => SawTyInfer
+      TyInfer => SawTyInfer,
+      TyErr => SawTyErr,
     }
 }
 
index 923ec05c22b77d0410952f3349460e15f4f53331..66c4a81a5c0f2f582975ddc130721dfadf7cb614 100644 (file)
@@ -1229,6 +1229,9 @@ pub fn ast_ty_to_ty(&self, ast_ty: &hir::Ty) -> Ty<'tcx> {
                 // handled specially and will not descend into this routine.
                 self.ty_infer(ast_ty.span)
             }
+            hir::TyErr => {
+                tcx.types.err
+            }
         };
 
         cache.borrow_mut().insert(ast_ty.id, result_ty);
index f3ea6c4467c401c396bccf1733a2494ea1040efa..ac72d7d29a24c4813839cd5b7185544ee269b698 100644 (file)
@@ -1805,7 +1805,7 @@ fn clean(&self, cx: &DocContext) -> Type {
             }
             TyBareFn(ref barefn) => BareFunction(box barefn.clean(cx)),
             TyImplTrait(ref bounds) => ImplTrait(bounds.clean(cx)),
-            TyInfer => Infer,
+            TyInfer | TyErr => Infer,
             TyTypeof(..) => panic!("Unimplemented type {:?}", self.node),
         }
     }
index 9eb86aa006d171f4ca0af868bdb13bd66921a237..c6a3e8a2dedc4653985b20276673a99c3fa658b9 100644 (file)
@@ -1361,6 +1361,8 @@ pub enum TyKind {
     ImplicitSelf,
     // A macro in the type position.
     Mac(Mac),
+    /// Placeholder for a kind that has failed to be defined.
+    Err,
 }
 
 /// Inline assembly dialect.
index 1a4e196ac557778e3b39ec6760495ebbadbd79c6..92e25b00e0ac108cfd41d90b06e1773f45b21d38 100644 (file)
@@ -358,7 +358,7 @@ pub fn noop_fold_ty<T: Folder>(t: P<Ty>, fld: &mut T) -> P<Ty> {
     t.map(|Ty {id, node, span}| Ty {
         id: fld.new_id(id),
         node: match node {
-            TyKind::Infer | TyKind::ImplicitSelf => node,
+            TyKind::Infer | TyKind::ImplicitSelf | TyKind::Err => node,
             TyKind::Slice(ty) => TyKind::Slice(fld.fold_ty(ty)),
             TyKind::Ptr(mt) => TyKind::Ptr(fld.fold_mt(mt)),
             TyKind::Rptr(region, mt) => {
index c2c3e5a6855af4ca8e415b7bbc5f3a48e97c6920..23fc1351426c2ead6a7ee9f41897fb28f1f5b570 100644 (file)
@@ -407,6 +407,25 @@ fn from(expr: P<Expr>) -> Self {
     }
 }
 
+/// Create a placeholder argument.
+fn dummy_arg(span: Span) -> Arg {
+    let spanned = Spanned {
+        span: span,
+        node: keywords::Invalid.ident()
+    };
+    let pat = P(Pat {
+        id: ast::DUMMY_NODE_ID,
+        node: PatKind::Ident(BindingMode::ByValue(Mutability::Immutable), spanned, None),
+        span: span
+    });
+    let ty = Ty {
+        node: TyKind::Err,
+        span: span,
+        id: ast::DUMMY_NODE_ID
+    };
+    Arg { ty: P(ty), pat: pat, id: ast::DUMMY_NODE_ID }
+}
+
 impl<'a> Parser<'a> {
     pub fn new(sess: &'a ParseSess,
                tokens: TokenStream,
@@ -4343,8 +4362,12 @@ fn parse_fn_args(&mut self, named_args: bool, allow_variadic: bool)
                             Ok(arg) => Ok(Some(arg)),
                             Err(mut e) => {
                                 e.emit();
+                                let lo = p.prev_span;
+                                // Skip every token until next possible arg or end.
                                 p.eat_to_tokens(&[&token::Comma, &token::CloseDelim(token::Paren)]);
-                                Ok(None)
+                                // Create a placeholder argument for proper arg count (#34264).
+                                let span = lo.to(p.prev_span);
+                                Ok(Some(dummy_arg(span)))
                             }
                         }
                     }
index f042a18d610360b1184c306d95117706de49056d..e7feff2b79fceb9936a665f90923ee0f9fa490b1 100644 (file)
@@ -1095,6 +1095,9 @@ pub fn print_type(&mut self, ty: &ast::Ty) -> io::Result<()> {
             ast::TyKind::Infer => {
                 word(&mut self.s, "_")?;
             }
+            ast::TyKind::Err => {
+                word(&mut self.s, "?")?;
+            }
             ast::TyKind::ImplicitSelf => {
                 word(&mut self.s, "Self")?;
             }
index a5333f3bb6a6e46c1f3af1c8e1d30194c194d897..b5e9a1892acc9927446c1cfffcd394cbbcd93094 100644 (file)
@@ -350,7 +350,7 @@ pub fn walk_ty<'a, V: Visitor<'a>>(visitor: &mut V, typ: &'a Ty) {
         TyKind::Typeof(ref expression) => {
             visitor.visit_expr(expression)
         }
-        TyKind::Infer | TyKind::ImplicitSelf => {}
+        TyKind::Infer | TyKind::ImplicitSelf | TyKind::Err => {}
         TyKind::Mac(ref mac) => {
             visitor.visit_mac(mac)
         }
diff --git a/src/test/ui/span/issue-34264.rs b/src/test/ui/span/issue-34264.rs
new file mode 100644 (file)
index 0000000..00482f5
--- /dev/null
@@ -0,0 +1,20 @@
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+fn foo(Option<i32>, String) {}
+fn bar(x, y: usize) {}
+
+fn main() {
+    foo(Some(42), 2);
+    foo(Some(42), 2, "");
+    bar("", "");
+    bar(1, 2);
+    bar(1, 2, 3);
+}
diff --git a/src/test/ui/span/issue-34264.stderr b/src/test/ui/span/issue-34264.stderr
new file mode 100644 (file)
index 0000000..c79db54
--- /dev/null
@@ -0,0 +1,49 @@
+error: expected one of `:` or `@`, found `<`
+  --> $DIR/issue-34264.rs:11:14
+   |
+11 | fn foo(Option<i32>, String) {}
+   |              ^
+
+error: expected one of `:` or `@`, found `)`
+  --> $DIR/issue-34264.rs:11:27
+   |
+11 | fn foo(Option<i32>, String) {}
+   |                           ^
+
+error: expected one of `:` or `@`, found `,`
+  --> $DIR/issue-34264.rs:12:9
+   |
+12 | fn bar(x, y: usize) {}
+   |         ^
+
+error[E0061]: this function takes 2 parameters but 3 parameters were supplied
+  --> $DIR/issue-34264.rs:16:9
+   |
+11 | fn foo(Option<i32>, String) {}
+   | ------------------------------ defined here
+...
+16 |     foo(Some(42), 2, "");
+   |         ^^^^^^^^^^^^^^^ expected 2 parameters
+
+error[E0308]: mismatched types
+  --> $DIR/issue-34264.rs:17:13
+   |
+17 |     bar("", "");
+   |             ^^ expected usize, found reference
+   |
+   = note: expected type `usize`
+              found type `&'static str`
+   = help: here are some functions which might fulfill your needs:
+           - .len()
+
+error[E0061]: this function takes 2 parameters but 3 parameters were supplied
+  --> $DIR/issue-34264.rs:19:9
+   |
+12 | fn bar(x, y: usize) {}
+   | ---------------------- defined here
+...
+19 |     bar(1, 2, 3);
+   |         ^^^^^^^ expected 2 parameters
+
+error: aborting due to 3 previous errors
+