From 3e4d9df02bf8a801fb6f4903697ec523590210a9 Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Mon, 9 Oct 2017 20:02:17 +0300 Subject: [PATCH] Fix a bug in diagnostics for `x as usize < y` Improve diagnostics for `x as usize << y` --- src/libsyntax/parse/parser.rs | 19 ++++++++++++++++--- src/test/ui/issue-22644.rs | 2 ++ src/test/ui/issue-22644.stderr | 13 +++++++++++-- src/test/ui/issue-44406.rs | 19 +++++++++++++++++++ src/test/ui/issue-44406.stderr | 26 ++++++++++++++++++++++++++ 5 files changed, 74 insertions(+), 5 deletions(-) create mode 100644 src/test/ui/issue-44406.rs create mode 100644 src/test/ui/issue-44406.stderr diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index 978e06c75dd46..ff020445715d4 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -2890,17 +2890,30 @@ impl<'a> Parser<'a> { match self.parse_path(PathStyle::Expr) { Ok(path) => { + let (op_noun, op_verb) = match self.token { + token::Lt => ("comparison", "comparing"), + token::BinOp(token::Shl) => ("shift", "shifting"), + _ => { + // We can end up here even without `<` being the next token, for + // example because `parse_ty_no_plus` returns `Err` on keywords, + // but `parse_path` returns `Ok` on them due to error recovery. + // Return original error and parser state. + mem::replace(self, parser_snapshot_after_type); + return Err(type_err); + } + }; + // Successfully parsed the type path leaving a `<` yet to parse. type_err.cancel(); // Report non-fatal diagnostics, keep `x as usize` as an expression // in AST and continue parsing. let msg = format!("`<` is interpreted as a start of generic \ - arguments for `{}`, not a comparison", path); + arguments for `{}`, not a {}", path, op_noun); let mut err = self.sess.span_diagnostic.struct_span_err(self.span, &msg); err.span_label(self.look_ahead_span(1).to(parser_snapshot_after_type.span), "interpreted as generic arguments"); - err.span_label(self.span, "not interpreted as comparison"); + err.span_label(self.span, format!("not interpreted as {}", op_noun)); let expr = mk_expr(self, P(Ty { span: path.span, @@ -2911,7 +2924,7 @@ impl<'a> Parser<'a> { let expr_str = self.sess.codemap().span_to_snippet(expr.span) .unwrap_or(pprust::expr_to_string(&expr)); err.span_suggestion(expr.span, - "try comparing the casted value", + &format!("try {} the casted value", op_verb), format!("({})", expr_str)); err.emit(); diff --git a/src/test/ui/issue-22644.rs b/src/test/ui/issue-22644.rs index b482d0595f7b6..c8e0cd1763ffa 100644 --- a/src/test/ui/issue-22644.rs +++ b/src/test/ui/issue-22644.rs @@ -35,5 +35,7 @@ fn main() { < 5); + println!("{}", a as usize << long_name); + println!("{}", a: &mut 4); } diff --git a/src/test/ui/issue-22644.stderr b/src/test/ui/issue-22644.stderr index 54c325b24a3b7..f4967c4803bee 100644 --- a/src/test/ui/issue-22644.stderr +++ b/src/test/ui/issue-22644.stderr @@ -76,9 +76,18 @@ help: try comparing the casted value 33 | ... +error: `<` is interpreted as a start of generic arguments for `usize`, not a shift + --> $DIR/issue-22644.rs:38:31 + | +38 | println!("{}", a as usize << long_name); + | ---------- ^^ --------- interpreted as generic arguments + | | | + | | not interpreted as shift + | help: try shifting the casted value: `(a as usize)` + error: expected type, found `4` - --> $DIR/issue-22644.rs:38:28 + --> $DIR/issue-22644.rs:40:28 | -38 | println!("{}", a: &mut 4); +40 | println!("{}", a: &mut 4); | ^ expecting a type here because of type ascription diff --git a/src/test/ui/issue-44406.rs b/src/test/ui/issue-44406.rs new file mode 100644 index 0000000000000..abf572118fc68 --- /dev/null +++ b/src/test/ui/issue-44406.rs @@ -0,0 +1,19 @@ +// 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. + +macro_rules! foo { + ($rest: tt) => { + bar(baz: $rest) + } +} + +fn main() { + foo!(true); +} diff --git a/src/test/ui/issue-44406.stderr b/src/test/ui/issue-44406.stderr new file mode 100644 index 0000000000000..e07face24bab7 --- /dev/null +++ b/src/test/ui/issue-44406.stderr @@ -0,0 +1,26 @@ +error: expected identifier, found keyword `true` + --> $DIR/issue-44406.rs:18:10 + | +18 | foo!(true); + | ^^^^ + +error: expected type, found keyword `true` + --> $DIR/issue-44406.rs:18:10 + | +13 | bar(baz: $rest) + | - help: did you mean to use `;` here? +... +18 | foo!(true); + | ^^^^ expecting a type here because of type ascription + +error: expected one of `!`, `&&`, `&`, `(`, `*`, `.`, `;`, `<`, `?`, `[`, `_`, `extern`, `fn`, `for`, `impl`, `unsafe`, `}`, an operator, or lifetime, found `true` + --> $DIR/issue-44406.rs:18:10 + | +13 | bar(baz: $rest) + | - expected one of 19 possible tokens here +... +18 | foo!(true); + | ^^^^ unexpected token + +error: aborting due to 3 previous errors +