Skip to content

Commit 8c92cbe

Browse files
committed
Moved let-chain warning/error to ast_validation and changed to unconditional error.
1 parent 2ce56c5 commit 8c92cbe

File tree

5 files changed

+92
-96
lines changed

5 files changed

+92
-96
lines changed

src/librustc_passes/ast_validation.rs

+48
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ use syntax::ast::*;
2222
use syntax::attr;
2323
use syntax::source_map::Spanned;
2424
use syntax::symbol::keywords;
25+
use syntax::ptr::P;
2526
use syntax::visit::{self, Visitor};
2627
use syntax_pos::Span;
2728
use errors;
@@ -167,11 +168,58 @@ impl<'a> AstValidator<'a> {
167168
"only lifetime parameters can be used in this context");
168169
}
169170
}
171+
172+
/// With eRFC 2497, we need to check whether an expression is ambigious and warn or error
173+
/// depending on the edition, this function handles that.
174+
fn while_if_let_ambiguity(&self, expr: &P<Expr>) {
175+
if let Some((span, op_kind)) = self.while_if_let_expr_ambiguity(&expr) {
176+
let mut err = self.err_handler().struct_span_err(
177+
span, &format!("ambigious use of `{}`", op_kind.to_string())
178+
);
179+
180+
err.note(
181+
"this will be a error until the `let_chains` feature is stabilized"
182+
);
183+
184+
if let Ok(snippet) = self.session.source_map().span_to_snippet(span) {
185+
err.span_suggestion(
186+
span, "consider adding parentheses", format!("({})", snippet),
187+
);
188+
}
189+
190+
err.emit();
191+
}
192+
}
193+
194+
/// With eRFC 2497 adding if-let chains, there is a requirement that the parsing of
195+
/// `&&` and `||` in a if-let statement be unambigious. This function returns a span and
196+
/// a `BinOpKind` (either `&&` or `||` depending on what was ambigious) if it is determined
197+
/// that the current expression parsed is ambigious and will break in future.
198+
fn while_if_let_expr_ambiguity(&self, expr: &P<Expr>) -> Option<(Span, BinOpKind)> {
199+
debug!("while_if_let_expr_ambiguity: expr.node: {:?}", expr.node);
200+
match &expr.node {
201+
ExprKind::Binary(op, _, _) if op.node == BinOpKind::And || op.node == BinOpKind::Or => {
202+
Some((expr.span, op.node))
203+
},
204+
ExprKind::Range(ref lhs, ref rhs, _) => {
205+
let lhs_ambigious = lhs.as_ref()
206+
.and_then(|lhs| self.while_if_let_expr_ambiguity(lhs));
207+
let rhs_ambigious = rhs.as_ref()
208+
.and_then(|rhs| self.while_if_let_expr_ambiguity(rhs));
209+
210+
lhs_ambigious.or(rhs_ambigious)
211+
}
212+
_ => None,
213+
}
214+
}
215+
170216
}
171217

172218
impl<'a> Visitor<'a> for AstValidator<'a> {
173219
fn visit_expr(&mut self, expr: &'a Expr) {
174220
match expr.node {
221+
ExprKind::IfLet(_, ref expr, _, _) | ExprKind::WhileLet(_, ref expr, _, _) =>
222+
self.while_if_let_ambiguity(&expr),
175223
ExprKind::InlineAsm(..) if !self.session.target.target.options.allow_asm => {
176224
span_err!(self.session, expr.span, E0472, "asm! is unsupported on this target");
177225
}

src/libsyntax/parse/parser.rs

-53
Original file line numberDiff line numberDiff line change
@@ -3327,8 +3327,6 @@ impl<'a> Parser<'a> {
33273327
let pats = self.parse_pats()?;
33283328
self.expect(&token::Eq)?;
33293329
let expr = self.parse_expr_res(Restrictions::NO_STRUCT_LITERAL, None)?;
3330-
self.while_if_let_ambiguity(&expr);
3331-
33323330
let thn = self.parse_block()?;
33333331
let (hi, els) = if self.eat_keyword(keywords::Else) {
33343332
let expr = self.parse_else_expr()?;
@@ -3339,56 +3337,6 @@ impl<'a> Parser<'a> {
33393337
Ok(self.mk_expr(lo.to(hi), ExprKind::IfLet(pats, expr, thn, els), attrs))
33403338
}
33413339

3342-
/// With eRFC 2497, we need to check whether an expression is ambigious and warn or error
3343-
/// depending on the edition, this function handles that.
3344-
fn while_if_let_ambiguity(&self, expr: &P<Expr>) {
3345-
if let Some((span, op_kind)) = self.while_if_let_expr_ambiguity(&expr) {
3346-
let message = format!("ambigious use of `{}`", op_kind.to_string());
3347-
let mut err = if self.span.edition() >= Edition::Edition2018 {
3348-
self.diagnostic().struct_span_err(span, &message)
3349-
} else {
3350-
self.diagnostic().struct_span_warn(span, &message)
3351-
};
3352-
3353-
let note = if self.span.edition() >= Edition::Edition2018 {
3354-
"This will be a error until the `let_chains` feature is stabilized."
3355-
} else {
3356-
"This will be a error in Rust 2018 until the `let_chains` feature is stabilized."
3357-
};
3358-
err.note(note);
3359-
3360-
if let Ok(snippet) = self.sess.source_map().span_to_snippet(span) {
3361-
err.span_suggestion(
3362-
span, "consider adding parenthesis", format!("({})", snippet),
3363-
);
3364-
}
3365-
3366-
err.emit();
3367-
}
3368-
}
3369-
3370-
/// With eRFC 2497 adding if-let chains, there is a requirement that the parsing of
3371-
/// `&&` and `||` in a if-let statement be unambigious. This function returns a span and
3372-
/// a `BinOpKind` (either `&&` or `||` depending on what was ambigious) if it is determined
3373-
/// that the current expression parsed is ambigious and will break in future.
3374-
fn while_if_let_expr_ambiguity(&self, expr: &P<Expr>) -> Option<(Span, BinOpKind)> {
3375-
debug!("while_if_let_expr_ambiguity: expr.node: {:?}", expr.node);
3376-
match &expr.node {
3377-
ExprKind::Binary(op, _, _) if op.node == BinOpKind::And || op.node == BinOpKind::Or => {
3378-
Some((expr.span, op.node))
3379-
},
3380-
ExprKind::Range(ref lhs, ref rhs, _) => {
3381-
let lhs_ambigious = lhs.as_ref()
3382-
.and_then(|lhs| self.while_if_let_expr_ambiguity(lhs));
3383-
let rhs_ambigious = rhs.as_ref()
3384-
.and_then(|rhs| self.while_if_let_expr_ambiguity(rhs));
3385-
3386-
lhs_ambigious.or(rhs_ambigious)
3387-
}
3388-
_ => None,
3389-
}
3390-
}
3391-
33923340
// `move |args| expr`
33933341
fn parse_lambda_expr(&mut self,
33943342
attrs: ThinVec<Attribute>)
@@ -3489,7 +3437,6 @@ impl<'a> Parser<'a> {
34893437
let pats = self.parse_pats()?;
34903438
self.expect(&token::Eq)?;
34913439
let expr = self.parse_expr_res(Restrictions::NO_STRUCT_LITERAL, None)?;
3492-
self.while_if_let_ambiguity(&expr);
34933440
let (iattrs, body) = self.parse_inner_attrs_and_block()?;
34943441
attrs.extend(iattrs);
34953442
let span = span_lo.to(body.span);

src/test/ui/rfc-2497-if-let-chains/syntax-ambiguity-2015.rs

+6-7
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@
99
// except according to those terms.
1010

1111
// edition:2015
12-
// compile-pass
1312

1413
// Enabling `ireffutable_let_patterns` isn't necessary for what this tests, but it makes coming up
1514
// with examples easier.
@@ -20,22 +19,22 @@ fn main() {
2019
use std::ops::Range;
2120

2221
if let Range { start: _, end: _ } = true..true && false { }
23-
//~^ WARN error in 2018
22+
//~^ ERROR ambigious use of `&&`
2423

2524
if let Range { start: _, end: _ } = true..true || false { }
26-
//~^ WARN error in 2018
25+
//~^ ERROR ambigious use of `||`
2726

2827
while let Range { start: _, end: _ } = true..true && false { }
29-
//~^ WARN error in 2018
28+
//~^ ERROR ambigious use of `&&`
3029

3130
while let Range { start: _, end: _ } = true..true || false { }
32-
//~^ WARN error in 2018
31+
//~^ ERROR ambigious use of `||`
3332

3433
if let true = false && false { }
35-
//~^ WARN error in 2018
34+
//~^ ERROR ambigious use of `&&`
3635

3736
while let true = (1 == 2) && false { }
38-
//~^ WARN error in 2018
37+
//~^ ERROR ambigious use of `&&`
3938

4039
// The following cases are not an error as parenthesis are used to
4140
// clarify intent:
Original file line numberDiff line numberDiff line change
@@ -1,48 +1,50 @@
1-
warning: ambigious use of `&&`
2-
--> $DIR/syntax-ambiguity-2015.rs:22:47
1+
error: ambigious use of `&&`
2+
--> $DIR/syntax-ambiguity-2015.rs:21:47
33
|
44
LL | if let Range { start: _, end: _ } = true..true && false { }
5-
| ^^^^^^^^^^^^^ help: consider adding parenthesis: `(true && false)`
5+
| ^^^^^^^^^^^^^ help: consider adding parentheses: `(true && false)`
66
|
7-
= note: This will be a error in Rust 2018 until the `let_chains` feature is stabilized.
7+
= note: this will be a error until the `let_chains` feature is stabilized
88

9-
warning: ambigious use of `||`
10-
--> $DIR/syntax-ambiguity-2015.rs:25:47
9+
error: ambigious use of `||`
10+
--> $DIR/syntax-ambiguity-2015.rs:24:47
1111
|
1212
LL | if let Range { start: _, end: _ } = true..true || false { }
13-
| ^^^^^^^^^^^^^ help: consider adding parenthesis: `(true || false)`
13+
| ^^^^^^^^^^^^^ help: consider adding parentheses: `(true || false)`
1414
|
15-
= note: This will be a error in Rust 2018 until the `let_chains` feature is stabilized.
15+
= note: this will be a error until the `let_chains` feature is stabilized
1616

17-
warning: ambigious use of `&&`
18-
--> $DIR/syntax-ambiguity-2015.rs:28:50
17+
error: ambigious use of `&&`
18+
--> $DIR/syntax-ambiguity-2015.rs:27:50
1919
|
2020
LL | while let Range { start: _, end: _ } = true..true && false { }
21-
| ^^^^^^^^^^^^^ help: consider adding parenthesis: `(true && false)`
21+
| ^^^^^^^^^^^^^ help: consider adding parentheses: `(true && false)`
2222
|
23-
= note: This will be a error in Rust 2018 until the `let_chains` feature is stabilized.
23+
= note: this will be a error until the `let_chains` feature is stabilized
2424

25-
warning: ambigious use of `||`
26-
--> $DIR/syntax-ambiguity-2015.rs:31:50
25+
error: ambigious use of `||`
26+
--> $DIR/syntax-ambiguity-2015.rs:30:50
2727
|
2828
LL | while let Range { start: _, end: _ } = true..true || false { }
29-
| ^^^^^^^^^^^^^ help: consider adding parenthesis: `(true || false)`
29+
| ^^^^^^^^^^^^^ help: consider adding parentheses: `(true || false)`
3030
|
31-
= note: This will be a error in Rust 2018 until the `let_chains` feature is stabilized.
31+
= note: this will be a error until the `let_chains` feature is stabilized
3232

33-
warning: ambigious use of `&&`
34-
--> $DIR/syntax-ambiguity-2015.rs:34:19
33+
error: ambigious use of `&&`
34+
--> $DIR/syntax-ambiguity-2015.rs:33:19
3535
|
3636
LL | if let true = false && false { }
37-
| ^^^^^^^^^^^^^^ help: consider adding parenthesis: `(false && false)`
37+
| ^^^^^^^^^^^^^^ help: consider adding parentheses: `(false && false)`
3838
|
39-
= note: This will be a error in Rust 2018 until the `let_chains` feature is stabilized.
39+
= note: this will be a error until the `let_chains` feature is stabilized
4040

41-
warning: ambigious use of `&&`
42-
--> $DIR/syntax-ambiguity-2015.rs:37:22
41+
error: ambigious use of `&&`
42+
--> $DIR/syntax-ambiguity-2015.rs:36:22
4343
|
4444
LL | while let true = (1 == 2) && false { }
45-
| ^^^^^^^^^^^^^^^^^ help: consider adding parenthesis: `((1 == 2) && false)`
45+
| ^^^^^^^^^^^^^^^^^ help: consider adding parentheses: `((1 == 2) && false)`
4646
|
47-
= note: This will be a error in Rust 2018 until the `let_chains` feature is stabilized.
47+
= note: this will be a error until the `let_chains` feature is stabilized
48+
49+
error: aborting due to 6 previous errors
4850

src/test/ui/rfc-2497-if-let-chains/syntax-ambiguity-2018.stderr

+12-12
Original file line numberDiff line numberDiff line change
@@ -2,49 +2,49 @@ error: ambigious use of `&&`
22
--> $DIR/syntax-ambiguity-2018.rs:21:47
33
|
44
LL | if let Range { start: _, end: _ } = true..true && false { }
5-
| ^^^^^^^^^^^^^ help: consider adding parenthesis: `(true && false)`
5+
| ^^^^^^^^^^^^^ help: consider adding parentheses: `(true && false)`
66
|
7-
= note: This will be a error until the `let_chains` feature is stabilized.
7+
= note: this will be a error until the `let_chains` feature is stabilized
88

99
error: ambigious use of `||`
1010
--> $DIR/syntax-ambiguity-2018.rs:24:47
1111
|
1212
LL | if let Range { start: _, end: _ } = true..true || false { }
13-
| ^^^^^^^^^^^^^ help: consider adding parenthesis: `(true || false)`
13+
| ^^^^^^^^^^^^^ help: consider adding parentheses: `(true || false)`
1414
|
15-
= note: This will be a error until the `let_chains` feature is stabilized.
15+
= note: this will be a error until the `let_chains` feature is stabilized
1616

1717
error: ambigious use of `&&`
1818
--> $DIR/syntax-ambiguity-2018.rs:27:50
1919
|
2020
LL | while let Range { start: _, end: _ } = true..true && false { }
21-
| ^^^^^^^^^^^^^ help: consider adding parenthesis: `(true && false)`
21+
| ^^^^^^^^^^^^^ help: consider adding parentheses: `(true && false)`
2222
|
23-
= note: This will be a error until the `let_chains` feature is stabilized.
23+
= note: this will be a error until the `let_chains` feature is stabilized
2424

2525
error: ambigious use of `||`
2626
--> $DIR/syntax-ambiguity-2018.rs:30:50
2727
|
2828
LL | while let Range { start: _, end: _ } = true..true || false { }
29-
| ^^^^^^^^^^^^^ help: consider adding parenthesis: `(true || false)`
29+
| ^^^^^^^^^^^^^ help: consider adding parentheses: `(true || false)`
3030
|
31-
= note: This will be a error until the `let_chains` feature is stabilized.
31+
= note: this will be a error until the `let_chains` feature is stabilized
3232

3333
error: ambigious use of `&&`
3434
--> $DIR/syntax-ambiguity-2018.rs:33:19
3535
|
3636
LL | if let true = false && false { }
37-
| ^^^^^^^^^^^^^^ help: consider adding parenthesis: `(false && false)`
37+
| ^^^^^^^^^^^^^^ help: consider adding parentheses: `(false && false)`
3838
|
39-
= note: This will be a error until the `let_chains` feature is stabilized.
39+
= note: this will be a error until the `let_chains` feature is stabilized
4040

4141
error: ambigious use of `&&`
4242
--> $DIR/syntax-ambiguity-2018.rs:36:22
4343
|
4444
LL | while let true = (1 == 2) && false { }
45-
| ^^^^^^^^^^^^^^^^^ help: consider adding parenthesis: `((1 == 2) && false)`
45+
| ^^^^^^^^^^^^^^^^^ help: consider adding parentheses: `((1 == 2) && false)`
4646
|
47-
= note: This will be a error until the `let_chains` feature is stabilized.
47+
= note: this will be a error until the `let_chains` feature is stabilized
4848

4949
error: aborting due to 6 previous errors
5050

0 commit comments

Comments
 (0)