Skip to content

Commit

Permalink
Rollup merge of rust-lang#54409 - estebank:remove-in, r=pnkfelix
Browse files Browse the repository at this point in the history
Detect `for _ in in bar {}` typo

Fix rust-lang#36611, rust-lang#52964, without modifying the parsing of emplacement `in` to avoid further problems like rust-lang#50832.
  • Loading branch information
pietroalbini authored Sep 22, 2018
2 parents 8455a7f + 06d577d commit 1eee532
Show file tree
Hide file tree
Showing 4 changed files with 51 additions and 13 deletions.
34 changes: 25 additions & 9 deletions src/libsyntax/parse/parser.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2703,8 +2703,8 @@ impl<'a> Parser<'a> {
token::Literal(token::Float(n), _suf) => {
self.bump();
let fstr = n.as_str();
let mut err = self.diagnostic().struct_span_err(self.prev_span,
&format!("unexpected token: `{}`", n));
let mut err = self.diagnostic()
.struct_span_err(self.prev_span, &format!("unexpected token: `{}`", n));
err.span_label(self.prev_span, "unexpected token");
if fstr.chars().all(|x| "0123456789.".contains(x)) {
let float = match fstr.parse::<f64>().ok() {
Expand Down Expand Up @@ -2864,8 +2864,8 @@ impl<'a> Parser<'a> {
let e = self.parse_prefix_expr(None);
let (span, e) = self.interpolated_or_expr_span(e)?;
let span_of_tilde = lo;
let mut err = self.diagnostic().struct_span_err(span_of_tilde,
"`~` cannot be used as a unary operator");
let mut err = self.diagnostic()
.struct_span_err(span_of_tilde, "`~` cannot be used as a unary operator");
err.span_suggestion_short_with_applicability(
span_of_tilde,
"use `!` to perform bitwise negation",
Expand Down Expand Up @@ -3423,6 +3423,24 @@ impl<'a> Parser<'a> {
);
err.emit();
}
let in_span = self.prev_span;
if self.eat_keyword(keywords::In) {
// a common typo: `for _ in in bar {}`
let mut err = self.sess.span_diagnostic.struct_span_err(
self.prev_span,
"expected iterable, found keyword `in`",
);
err.span_suggestion_short_with_applicability(
in_span.until(self.prev_span),
"remove the duplicated `in`",
String::new(),
Applicability::MachineApplicable,
);
err.note("if you meant to use emplacement syntax, it is obsolete (for now, anyway)");
err.note("for more information on the status of emplacement syntax, see <\
https://github.com/rust-lang/rust/issues/27779#issuecomment-378416911>");
err.emit();
}
let expr = self.parse_expr_res(Restrictions::NO_STRUCT_LITERAL, None)?;
let (iattrs, loop_block) = self.parse_inner_attrs_and_block()?;
attrs.extend(iattrs);
Expand Down Expand Up @@ -4766,12 +4784,9 @@ impl<'a> Parser<'a> {
if !self.eat(&token::OpenDelim(token::Brace)) {
let sp = self.span;
let tok = self.this_token_to_string();
let mut do_not_suggest_help = false;
let mut e = self.span_fatal(sp, &format!("expected `{{`, found `{}`", tok));
if self.token.is_keyword(keywords::In) || self.token == token::Colon {
do_not_suggest_help = true;
e.span_label(sp, "expected `{`");
}
let do_not_suggest_help =
self.token.is_keyword(keywords::In) || self.token == token::Colon;

if self.token.is_ident_named("and") {
e.span_suggestion_short_with_applicability(
Expand Down Expand Up @@ -4802,6 +4817,7 @@ impl<'a> Parser<'a> {
|| do_not_suggest_help {
// if the next token is an open brace (e.g., `if a b {`), the place-
// inside-a-block suggestion would be more likely wrong than right
e.span_label(sp, "expected `{`");
return Err(e);
}
let mut stmt_span = stmt.span;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,20 @@ error: expected `{`, found `and`
--> $DIR/issue-54109-and_instead_of_ampersands.rs:14:10
|
LL | if a and b {
| -- ^^^ help: use `&&` instead of `and` for the boolean operator
| |
| -- ^^^
| | |
| | expected `{`
| | help: use `&&` instead of `and` for the boolean operator
| this `if` statement has a condition, but no block

error: expected `{`, found `or`
--> $DIR/issue-54109-and_instead_of_ampersands.rs:23:10
|
LL | if a or b {
| -- ^^ help: use `||` instead of `or` for the boolean operator
| |
| -- ^^
| | |
| | expected `{`
| | help: use `||` instead of `or` for the boolean operator
| this `if` statement has a condition, but no block

error: expected one of `!`, `)`, `,`, `.`, `::`, `?`, `{`, or an operator, found `and`
Expand Down
5 changes: 5 additions & 0 deletions src/test/ui/parser/if-in-in.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
fn main() {
for i in in 1..2 {
println!("{}", i);
}
}
13 changes: 13 additions & 0 deletions src/test/ui/parser/if-in-in.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
error: expected iterable, found keyword `in`
--> $DIR/if-in-in.rs:2:14
|
LL | for i in in 1..2 {
| ---^^
| |
| help: remove the duplicated `in`
|
= note: if you meant to use emplacement syntax, it is obsolete (for now, anyway)
= note: for more information on the status of emplacement syntax, see <https://github.com/rust-lang/rust/issues/27779#issuecomment-378416911>

error: aborting due to previous error

0 comments on commit 1eee532

Please sign in to comment.