Change expr_trailing_brace to an exhaustive match to force new expression kinds to specify whether they contain a brace
Add inline const and other possible curly brace expressions to expr_trailing_brace Add tests for `}` before `else` in `let...else` error Change to explicit cases for expressions with optional values when being checked for trailing braces Add tests for more complex cases of `}` before `else` in `let..else` statement Move other possible `}` cases into separate arm and add FIXME for future reference
This commit is contained in:
parent
2fdd9eda0c
commit
1fc6dbc32b
3 changed files with 428 additions and 3 deletions
|
@ -40,15 +40,44 @@ pub fn expr_trailing_brace(mut expr: &ast::Expr) -> Option<&ast::Expr> {
|
||||||
| Range(_, Some(e), _)
|
| Range(_, Some(e), _)
|
||||||
| Ret(Some(e))
|
| Ret(Some(e))
|
||||||
| Unary(_, e)
|
| Unary(_, e)
|
||||||
| Yield(Some(e)) => {
|
| Yield(Some(e))
|
||||||
|
| Yeet(Some(e))
|
||||||
|
| Become(e) => {
|
||||||
expr = e;
|
expr = e;
|
||||||
}
|
}
|
||||||
Closure(closure) => {
|
Closure(closure) => {
|
||||||
expr = &closure.body;
|
expr = &closure.body;
|
||||||
}
|
}
|
||||||
Gen(..) | Block(..) | ForLoop(..) | If(..) | Loop(..) | Match(..) | Struct(..)
|
Gen(..) | Block(..) | ForLoop(..) | If(..) | Loop(..) | Match(..) | Struct(..)
|
||||||
| TryBlock(..) | While(..) => break Some(expr),
|
| TryBlock(..) | While(..) | ConstBlock(_) => break Some(expr),
|
||||||
_ => break None,
|
|
||||||
|
// FIXME: These can end in `}`, but changing these would break stable code.
|
||||||
|
InlineAsm(_) | OffsetOf(_, _) | MacCall(_) | IncludedBytes(_) | FormatArgs(_) => {
|
||||||
|
break None;
|
||||||
|
}
|
||||||
|
|
||||||
|
Break(_, None)
|
||||||
|
| Range(_, None, _)
|
||||||
|
| Ret(None)
|
||||||
|
| Yield(None)
|
||||||
|
| Array(_)
|
||||||
|
| Call(_, _)
|
||||||
|
| MethodCall(_)
|
||||||
|
| Tup(_)
|
||||||
|
| Lit(_)
|
||||||
|
| Cast(_, _)
|
||||||
|
| Type(_, _)
|
||||||
|
| Await(_, _)
|
||||||
|
| Field(_, _)
|
||||||
|
| Index(_, _, _)
|
||||||
|
| Underscore
|
||||||
|
| Path(_, _)
|
||||||
|
| Continue(_)
|
||||||
|
| Repeat(_, _)
|
||||||
|
| Paren(_)
|
||||||
|
| Try(_)
|
||||||
|
| Yeet(None)
|
||||||
|
| Err => break None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
164
tests/ui/parser/bad-let-else-statement.rs
Normal file
164
tests/ui/parser/bad-let-else-statement.rs
Normal file
|
@ -0,0 +1,164 @@
|
||||||
|
#![feature(inline_const)]
|
||||||
|
#![feature(yeet_expr)]
|
||||||
|
#![allow(incomplete_features)] // Necessary for now, while explicit_tail_calls is incomplete
|
||||||
|
#![feature(explicit_tail_calls)]
|
||||||
|
|
||||||
|
fn a() {
|
||||||
|
let foo = {
|
||||||
|
1
|
||||||
|
} else {
|
||||||
|
//~^ ERROR right curly brace `}` before `else` in a `let...else` statement not allowed
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
fn b() {
|
||||||
|
let foo = for i in 1..2 {
|
||||||
|
break;
|
||||||
|
} else {
|
||||||
|
//~^ ERROR `for...else` loops are not supported
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
fn c() {
|
||||||
|
let foo = if true {
|
||||||
|
1
|
||||||
|
} else {
|
||||||
|
0
|
||||||
|
} else {
|
||||||
|
//~^ ERROR right curly brace `}` before `else` in a `let...else` statement not allowed
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
fn d() {
|
||||||
|
let foo = loop {
|
||||||
|
break;
|
||||||
|
} else {
|
||||||
|
//~^ ERROR loop...else` loops are not supported
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
fn e() {
|
||||||
|
let foo = match true {
|
||||||
|
true => 1,
|
||||||
|
false => 0
|
||||||
|
} else {
|
||||||
|
//~^ ERROR right curly brace `}` before `else` in a `let...else` statement not allowed
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
struct X {a: i32}
|
||||||
|
fn f() {
|
||||||
|
let foo = X {
|
||||||
|
a: 1
|
||||||
|
} else {
|
||||||
|
//~^ ERROR right curly brace `}` before `else` in a `let...else` statement not allowed
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
fn g() {
|
||||||
|
let foo = while false {
|
||||||
|
break;
|
||||||
|
} else {
|
||||||
|
//~^ ERROR `while...else` loops are not supported
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
fn h() {
|
||||||
|
let foo = const {
|
||||||
|
1
|
||||||
|
} else {
|
||||||
|
//~^ ERROR right curly brace `}` before `else` in a `let...else` statement not allowed
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
fn i() {
|
||||||
|
let foo = &{
|
||||||
|
1
|
||||||
|
} else {
|
||||||
|
//~^ ERROR right curly brace `}` before `else` in a `let...else` statement not allowed
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
fn j() {
|
||||||
|
let bar = 0;
|
||||||
|
let foo = bar = {
|
||||||
|
1
|
||||||
|
} else {
|
||||||
|
//~^ ERROR right curly brace `}` before `else` in a `let...else` statement not allowed
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
fn k() {
|
||||||
|
let foo = 1 + {
|
||||||
|
1
|
||||||
|
} else {
|
||||||
|
//~^ ERROR right curly brace `}` before `else` in a `let...else` statement not allowed
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
fn l() {
|
||||||
|
let foo = 1..{
|
||||||
|
1
|
||||||
|
} else {
|
||||||
|
//~^ ERROR right curly brace `}` before `else` in a `let...else` statement not allowed
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
fn m() {
|
||||||
|
let foo = return {
|
||||||
|
()
|
||||||
|
} else {
|
||||||
|
//~^ ERROR right curly brace `}` before `else` in a `let...else` statement not allowed
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
fn n() {
|
||||||
|
let foo = -{
|
||||||
|
1
|
||||||
|
} else {
|
||||||
|
//~^ ERROR right curly brace `}` before `else` in a `let...else` statement not allowed
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
fn o() -> Result<(), ()> {
|
||||||
|
let foo = do yeet {
|
||||||
|
()
|
||||||
|
} else {
|
||||||
|
//~^ ERROR right curly brace `}` before `else` in a `let...else` statement not allowed
|
||||||
|
return Ok(());
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
fn p() {
|
||||||
|
let foo = become {
|
||||||
|
()
|
||||||
|
} else {
|
||||||
|
//~^ ERROR right curly brace `}` before `else` in a `let...else` statement not allowed
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
fn q() {
|
||||||
|
let foo = |x: i32| {
|
||||||
|
x
|
||||||
|
} else {
|
||||||
|
//~^ ERROR right curly brace `}` before `else` in a `let...else` statement not allowed
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {}
|
232
tests/ui/parser/bad-let-else-statement.stderr
Normal file
232
tests/ui/parser/bad-let-else-statement.stderr
Normal file
|
@ -0,0 +1,232 @@
|
||||||
|
error: right curly brace `}` before `else` in a `let...else` statement not allowed
|
||||||
|
--> $DIR/bad-let-else-statement.rs:9:5
|
||||||
|
|
|
||||||
|
LL | } else {
|
||||||
|
| ^
|
||||||
|
|
|
||||||
|
help: wrap the expression in parentheses
|
||||||
|
|
|
||||||
|
LL ~ let foo = ({
|
||||||
|
LL | 1
|
||||||
|
LL ~ }) else {
|
||||||
|
|
|
||||||
|
|
||||||
|
error: `for...else` loops are not supported
|
||||||
|
--> $DIR/bad-let-else-statement.rs:18:7
|
||||||
|
|
|
||||||
|
LL | let foo = for i in 1..2 {
|
||||||
|
| --- `else` is attached to this loop
|
||||||
|
LL | break;
|
||||||
|
LL | } else {
|
||||||
|
| _______^
|
||||||
|
LL | |
|
||||||
|
LL | | return;
|
||||||
|
LL | | };
|
||||||
|
| |_____^
|
||||||
|
|
|
||||||
|
= note: consider moving this `else` clause to a separate `if` statement and use a `bool` variable to control if it should run
|
||||||
|
|
||||||
|
error: right curly brace `}` before `else` in a `let...else` statement not allowed
|
||||||
|
--> $DIR/bad-let-else-statement.rs:29:5
|
||||||
|
|
|
||||||
|
LL | } else {
|
||||||
|
| ^
|
||||||
|
|
|
||||||
|
help: wrap the expression in parentheses
|
||||||
|
|
|
||||||
|
LL ~ let foo = (if true {
|
||||||
|
LL | 1
|
||||||
|
LL | } else {
|
||||||
|
LL | 0
|
||||||
|
LL ~ }) else {
|
||||||
|
|
|
||||||
|
|
||||||
|
error: `loop...else` loops are not supported
|
||||||
|
--> $DIR/bad-let-else-statement.rs:38:7
|
||||||
|
|
|
||||||
|
LL | let foo = loop {
|
||||||
|
| ---- `else` is attached to this loop
|
||||||
|
LL | break;
|
||||||
|
LL | } else {
|
||||||
|
| _______^
|
||||||
|
LL | |
|
||||||
|
LL | | return;
|
||||||
|
LL | | };
|
||||||
|
| |_____^
|
||||||
|
|
|
||||||
|
= note: consider moving this `else` clause to a separate `if` statement and use a `bool` variable to control if it should run
|
||||||
|
|
||||||
|
error: right curly brace `}` before `else` in a `let...else` statement not allowed
|
||||||
|
--> $DIR/bad-let-else-statement.rs:48:5
|
||||||
|
|
|
||||||
|
LL | } else {
|
||||||
|
| ^
|
||||||
|
|
|
||||||
|
help: wrap the expression in parentheses
|
||||||
|
|
|
||||||
|
LL ~ let foo = (match true {
|
||||||
|
LL | true => 1,
|
||||||
|
LL | false => 0
|
||||||
|
LL ~ }) else {
|
||||||
|
|
|
||||||
|
|
||||||
|
error: right curly brace `}` before `else` in a `let...else` statement not allowed
|
||||||
|
--> $DIR/bad-let-else-statement.rs:58:5
|
||||||
|
|
|
||||||
|
LL | } else {
|
||||||
|
| ^
|
||||||
|
|
|
||||||
|
help: wrap the expression in parentheses
|
||||||
|
|
|
||||||
|
LL ~ let foo = (X {
|
||||||
|
LL | a: 1
|
||||||
|
LL ~ }) else {
|
||||||
|
|
|
||||||
|
|
||||||
|
error: `while...else` loops are not supported
|
||||||
|
--> $DIR/bad-let-else-statement.rs:67:7
|
||||||
|
|
|
||||||
|
LL | let foo = while false {
|
||||||
|
| ----- `else` is attached to this loop
|
||||||
|
LL | break;
|
||||||
|
LL | } else {
|
||||||
|
| _______^
|
||||||
|
LL | |
|
||||||
|
LL | | return;
|
||||||
|
LL | | };
|
||||||
|
| |_____^
|
||||||
|
|
|
||||||
|
= note: consider moving this `else` clause to a separate `if` statement and use a `bool` variable to control if it should run
|
||||||
|
|
||||||
|
error: right curly brace `}` before `else` in a `let...else` statement not allowed
|
||||||
|
--> $DIR/bad-let-else-statement.rs:76:5
|
||||||
|
|
|
||||||
|
LL | } else {
|
||||||
|
| ^
|
||||||
|
|
|
||||||
|
help: wrap the expression in parentheses
|
||||||
|
|
|
||||||
|
LL ~ let foo = (const {
|
||||||
|
LL | 1
|
||||||
|
LL ~ }) else {
|
||||||
|
|
|
||||||
|
|
||||||
|
error: right curly brace `}` before `else` in a `let...else` statement not allowed
|
||||||
|
--> $DIR/bad-let-else-statement.rs:85:5
|
||||||
|
|
|
||||||
|
LL | } else {
|
||||||
|
| ^
|
||||||
|
|
|
||||||
|
help: wrap the expression in parentheses
|
||||||
|
|
|
||||||
|
LL ~ let foo = &({
|
||||||
|
LL | 1
|
||||||
|
LL ~ }) else {
|
||||||
|
|
|
||||||
|
|
||||||
|
error: right curly brace `}` before `else` in a `let...else` statement not allowed
|
||||||
|
--> $DIR/bad-let-else-statement.rs:95:5
|
||||||
|
|
|
||||||
|
LL | } else {
|
||||||
|
| ^
|
||||||
|
|
|
||||||
|
help: wrap the expression in parentheses
|
||||||
|
|
|
||||||
|
LL ~ let foo = bar = ({
|
||||||
|
LL | 1
|
||||||
|
LL ~ }) else {
|
||||||
|
|
|
||||||
|
|
||||||
|
error: right curly brace `}` before `else` in a `let...else` statement not allowed
|
||||||
|
--> $DIR/bad-let-else-statement.rs:104:5
|
||||||
|
|
|
||||||
|
LL | } else {
|
||||||
|
| ^
|
||||||
|
|
|
||||||
|
help: wrap the expression in parentheses
|
||||||
|
|
|
||||||
|
LL ~ let foo = 1 + ({
|
||||||
|
LL | 1
|
||||||
|
LL ~ }) else {
|
||||||
|
|
|
||||||
|
|
||||||
|
error: right curly brace `}` before `else` in a `let...else` statement not allowed
|
||||||
|
--> $DIR/bad-let-else-statement.rs:113:5
|
||||||
|
|
|
||||||
|
LL | } else {
|
||||||
|
| ^
|
||||||
|
|
|
||||||
|
help: wrap the expression in parentheses
|
||||||
|
|
|
||||||
|
LL ~ let foo = 1..({
|
||||||
|
LL | 1
|
||||||
|
LL ~ }) else {
|
||||||
|
|
|
||||||
|
|
||||||
|
error: right curly brace `}` before `else` in a `let...else` statement not allowed
|
||||||
|
--> $DIR/bad-let-else-statement.rs:122:5
|
||||||
|
|
|
||||||
|
LL | } else {
|
||||||
|
| ^
|
||||||
|
|
|
||||||
|
help: wrap the expression in parentheses
|
||||||
|
|
|
||||||
|
LL ~ let foo = return ({
|
||||||
|
LL | ()
|
||||||
|
LL ~ }) else {
|
||||||
|
|
|
||||||
|
|
||||||
|
error: right curly brace `}` before `else` in a `let...else` statement not allowed
|
||||||
|
--> $DIR/bad-let-else-statement.rs:131:5
|
||||||
|
|
|
||||||
|
LL | } else {
|
||||||
|
| ^
|
||||||
|
|
|
||||||
|
help: wrap the expression in parentheses
|
||||||
|
|
|
||||||
|
LL ~ let foo = -({
|
||||||
|
LL | 1
|
||||||
|
LL ~ }) else {
|
||||||
|
|
|
||||||
|
|
||||||
|
error: right curly brace `}` before `else` in a `let...else` statement not allowed
|
||||||
|
--> $DIR/bad-let-else-statement.rs:140:5
|
||||||
|
|
|
||||||
|
LL | } else {
|
||||||
|
| ^
|
||||||
|
|
|
||||||
|
help: wrap the expression in parentheses
|
||||||
|
|
|
||||||
|
LL ~ let foo = do yeet ({
|
||||||
|
LL | ()
|
||||||
|
LL ~ }) else {
|
||||||
|
|
|
||||||
|
|
||||||
|
error: right curly brace `}` before `else` in a `let...else` statement not allowed
|
||||||
|
--> $DIR/bad-let-else-statement.rs:149:5
|
||||||
|
|
|
||||||
|
LL | } else {
|
||||||
|
| ^
|
||||||
|
|
|
||||||
|
help: wrap the expression in parentheses
|
||||||
|
|
|
||||||
|
LL ~ let foo = become ({
|
||||||
|
LL | ()
|
||||||
|
LL ~ }) else {
|
||||||
|
|
|
||||||
|
|
||||||
|
error: right curly brace `}` before `else` in a `let...else` statement not allowed
|
||||||
|
--> $DIR/bad-let-else-statement.rs:158:5
|
||||||
|
|
|
||||||
|
LL | } else {
|
||||||
|
| ^
|
||||||
|
|
|
||||||
|
help: wrap the expression in parentheses
|
||||||
|
|
|
||||||
|
LL ~ let foo = |x: i32| ({
|
||||||
|
LL | x
|
||||||
|
LL ~ }) else {
|
||||||
|
|
|
||||||
|
|
||||||
|
error: aborting due to 17 previous errors
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue