diff --git a/src/librustc/hir/intravisit.rs b/src/librustc/hir/intravisit.rs index c7ad143c949..2c8b145f126 100644 --- a/src/librustc/hir/intravisit.rs +++ b/src/librustc/hir/intravisit.rs @@ -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 => {} } } diff --git a/src/librustc/hir/lowering.rs b/src/librustc/hir/lowering.rs index 17185a6ab69..acc6d21ddc6 100644 --- a/src/librustc/hir/lowering.rs +++ b/src/librustc/hir/lowering.rs @@ -555,6 +555,7 @@ fn lower_ty_binding(&mut self, b: &TypeBinding) -> hir::TypeBinding { fn lower_ty(&mut self, t: &Ty) -> P { 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) => { diff --git a/src/librustc/hir/mod.rs b/src/librustc/hir/mod.rs index d5000ac9c18..0da405d1821 100644 --- a/src/librustc/hir/mod.rs +++ b/src/librustc/hir/mod.rs @@ -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)] diff --git a/src/librustc/hir/print.rs b/src/librustc/hir/print.rs index 04a65fd5e3a..4a5a35aa82c 100644 --- a/src/librustc/hir/print.rs +++ b/src/librustc/hir/print.rs @@ -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() } diff --git a/src/librustc_incremental/calculate_svh/svh_visitor.rs b/src/librustc_incremental/calculate_svh/svh_visitor.rs index 5401b371888..4700b77be07 100644 --- a/src/librustc_incremental/calculate_svh/svh_visitor.rs +++ b/src/librustc_incremental/calculate_svh/svh_visitor.rs @@ -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, } } diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs index 923ec05c22b..66c4a81a5c0 100644 --- a/src/librustc_typeck/astconv.rs +++ b/src/librustc_typeck/astconv.rs @@ -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); diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index f3ea6c4467c..ac72d7d29a2 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -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), } } diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs index 9eb86aa006d..c6a3e8a2ded 100644 --- a/src/libsyntax/ast.rs +++ b/src/libsyntax/ast.rs @@ -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. diff --git a/src/libsyntax/fold.rs b/src/libsyntax/fold.rs index 1a4e196ac55..92e25b00e0a 100644 --- a/src/libsyntax/fold.rs +++ b/src/libsyntax/fold.rs @@ -358,7 +358,7 @@ pub fn noop_fold_ty(t: P, fld: &mut T) -> P { 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) => { diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index c2c3e5a6855..23fc1351426 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -407,6 +407,25 @@ fn from(expr: P) -> 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))) } } } diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs index f042a18d610..e7feff2b79f 100644 --- a/src/libsyntax/print/pprust.rs +++ b/src/libsyntax/print/pprust.rs @@ -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")?; } diff --git a/src/libsyntax/visit.rs b/src/libsyntax/visit.rs index a5333f3bb6a..b5e9a1892ac 100644 --- a/src/libsyntax/visit.rs +++ b/src/libsyntax/visit.rs @@ -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 index 00000000000..00482f50618 --- /dev/null +++ b/src/test/ui/span/issue-34264.rs @@ -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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +fn foo(Option, 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 index 00000000000..c79db54eaef --- /dev/null +++ b/src/test/ui/span/issue-34264.stderr @@ -0,0 +1,49 @@ +error: expected one of `:` or `@`, found `<` + --> $DIR/issue-34264.rs:11:14 + | +11 | fn foo(Option, String) {} + | ^ + +error: expected one of `:` or `@`, found `)` + --> $DIR/issue-34264.rs:11:27 + | +11 | fn foo(Option, 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, 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 +