Skip to content

Commit

Permalink
Change expr_trailing_brace to an exhaustive match to force new expres…
Browse files Browse the repository at this point in the history
…sion 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
  • Loading branch information
GearsDatapacks committed Dec 14, 2023
1 parent 2fdd9ed commit 1fc6dbc
Show file tree
Hide file tree
Showing 3 changed files with 428 additions and 3 deletions.
35 changes: 32 additions & 3 deletions compiler/rustc_ast/src/util/classify.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,15 +40,44 @@ pub fn expr_trailing_brace(mut expr: &ast::Expr) -> Option<&ast::Expr> {
| Range(_, Some(e), _)
| Ret(Some(e))
| Unary(_, e)
| Yield(Some(e)) => {
| Yield(Some(e))
| Yeet(Some(e))
| Become(e) => {
expr = e;
}
Closure(closure) => {
expr = &closure.body;
}
Gen(..) | Block(..) | ForLoop(..) | If(..) | Loop(..) | Match(..) | Struct(..)
| TryBlock(..) | While(..) => break Some(expr),
_ => break None,
| TryBlock(..) | While(..) | ConstBlock(_) => break Some(expr),

// 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 changes: 164 additions & 0 deletions tests/ui/parser/bad-let-else-statement.rs
Original file line number Diff line number Diff line change
@@ -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() {}
Loading

0 comments on commit 1fc6dbc

Please sign in to comment.