Fix a bug in diagnostics for x as usize < y
Improve diagnostics for `x as usize << y`
This commit is contained in:
parent
72d65019c7
commit
3e4d9df02b
5 changed files with 75 additions and 6 deletions
|
@ -2890,17 +2890,30 @@ impl<'a> Parser<'a> {
|
||||||
|
|
||||||
match self.parse_path(PathStyle::Expr) {
|
match self.parse_path(PathStyle::Expr) {
|
||||||
Ok(path) => {
|
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.
|
// Successfully parsed the type path leaving a `<` yet to parse.
|
||||||
type_err.cancel();
|
type_err.cancel();
|
||||||
|
|
||||||
// Report non-fatal diagnostics, keep `x as usize` as an expression
|
// Report non-fatal diagnostics, keep `x as usize` as an expression
|
||||||
// in AST and continue parsing.
|
// in AST and continue parsing.
|
||||||
let msg = format!("`<` is interpreted as a start of generic \
|
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);
|
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),
|
err.span_label(self.look_ahead_span(1).to(parser_snapshot_after_type.span),
|
||||||
"interpreted as generic arguments");
|
"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 {
|
let expr = mk_expr(self, P(Ty {
|
||||||
span: path.span,
|
span: path.span,
|
||||||
|
@ -2911,7 +2924,7 @@ impl<'a> Parser<'a> {
|
||||||
let expr_str = self.sess.codemap().span_to_snippet(expr.span)
|
let expr_str = self.sess.codemap().span_to_snippet(expr.span)
|
||||||
.unwrap_or(pprust::expr_to_string(&expr));
|
.unwrap_or(pprust::expr_to_string(&expr));
|
||||||
err.span_suggestion(expr.span,
|
err.span_suggestion(expr.span,
|
||||||
"try comparing the casted value",
|
&format!("try {} the casted value", op_verb),
|
||||||
format!("({})", expr_str));
|
format!("({})", expr_str));
|
||||||
err.emit();
|
err.emit();
|
||||||
|
|
||||||
|
|
|
@ -35,5 +35,7 @@ fn main() {
|
||||||
<
|
<
|
||||||
5);
|
5);
|
||||||
|
|
||||||
|
println!("{}", a as usize << long_name);
|
||||||
|
|
||||||
println!("{}", a: &mut 4);
|
println!("{}", a: &mut 4);
|
||||||
}
|
}
|
||||||
|
|
|
@ -76,9 +76,18 @@ help: try comparing the casted value
|
||||||
33 |
|
33 |
|
||||||
...
|
...
|
||||||
|
|
||||||
error: expected type, found `4`
|
error: `<` is interpreted as a start of generic arguments for `usize`, not a shift
|
||||||
--> $DIR/issue-22644.rs:38:28
|
--> $DIR/issue-22644.rs:38:31
|
||||||
|
|
|
|
||||||
38 | println!("{}", a: &mut 4);
|
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:40:28
|
||||||
|
|
|
||||||
|
40 | println!("{}", a: &mut 4);
|
||||||
| ^ expecting a type here because of type ascription
|
| ^ expecting a type here because of type ascription
|
||||||
|
|
||||||
|
|
19
src/test/ui/issue-44406.rs
Normal file
19
src/test/ui/issue-44406.rs
Normal file
|
@ -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 <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.
|
||||||
|
|
||||||
|
macro_rules! foo {
|
||||||
|
($rest: tt) => {
|
||||||
|
bar(baz: $rest)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
foo!(true);
|
||||||
|
}
|
26
src/test/ui/issue-44406.stderr
Normal file
26
src/test/ui/issue-44406.stderr
Normal file
|
@ -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
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue