Rollup merge of #125049 - dtolnay:castbrace, r=compiler-errors

Disallow cast with trailing braced macro in let-else

This fixes an edge case I noticed while porting #118880 and #119062 to syn.

Previously, rustc incorrectly accepted code such as:

```rust
let foo = &std::ptr::null as &'static dyn std::ops::Fn() -> *const primitive! {
    8
} else {
    return;
};
```

even though a right curl brace `}` directly before `else` in a `let...else` statement is not supposed to be valid syntax.
This commit is contained in:
León Orell Valerian Liehr 2024-05-22 19:04:44 +02:00 committed by GitHub
commit 5b485f04de
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 210 additions and 298 deletions

View File

@ -81,8 +81,17 @@ pub fn expr_requires_semi_to_be_stmt(e: &ast::Expr) -> bool {
} }
} }
pub enum TrailingBrace<'a> {
/// Trailing brace in a macro call, like the one in `x as *const brace! {}`.
/// We will suggest changing the macro call to a different delimiter.
MacCall(&'a ast::MacCall),
/// Trailing brace in any other expression, such as `a + B {}`. We will
/// suggest wrapping the innermost expression in parentheses: `a + (B {})`.
Expr(&'a ast::Expr),
}
/// If an expression ends with `}`, returns the innermost expression ending in the `}` /// If an expression ends with `}`, returns the innermost expression ending in the `}`
pub fn expr_trailing_brace(mut expr: &ast::Expr) -> Option<&ast::Expr> { pub fn expr_trailing_brace(mut expr: &ast::Expr) -> Option<TrailingBrace<'_>> {
loop { loop {
match &expr.kind { match &expr.kind {
AddrOf(_, _, e) AddrOf(_, _, e)
@ -111,10 +120,14 @@ pub fn expr_trailing_brace(mut expr: &ast::Expr) -> Option<&ast::Expr> {
| Struct(..) | Struct(..)
| TryBlock(..) | TryBlock(..)
| While(..) | While(..)
| ConstBlock(_) => break Some(expr), | ConstBlock(_) => break Some(TrailingBrace::Expr(expr)),
Cast(_, ty) => {
break type_trailing_braced_mac_call(ty).map(TrailingBrace::MacCall);
}
MacCall(mac) => { MacCall(mac) => {
break (mac.args.delim == Delimiter::Brace).then_some(expr); break (mac.args.delim == Delimiter::Brace).then_some(TrailingBrace::MacCall(mac));
} }
InlineAsm(_) | OffsetOf(_, _) | IncludedBytes(_) | FormatArgs(_) => { InlineAsm(_) | OffsetOf(_, _) | IncludedBytes(_) | FormatArgs(_) => {
@ -131,7 +144,6 @@ pub fn expr_trailing_brace(mut expr: &ast::Expr) -> Option<&ast::Expr> {
| MethodCall(_) | MethodCall(_)
| Tup(_) | Tup(_)
| Lit(_) | Lit(_)
| Cast(_, _)
| Type(_, _) | Type(_, _)
| Await(_, _) | Await(_, _)
| Field(_, _) | Field(_, _)
@ -148,3 +160,78 @@ pub fn expr_trailing_brace(mut expr: &ast::Expr) -> Option<&ast::Expr> {
} }
} }
} }
/// If the type's last token is `}`, it must be due to a braced macro call, such
/// as in `*const brace! { ... }`. Returns that trailing macro call.
fn type_trailing_braced_mac_call(mut ty: &ast::Ty) -> Option<&ast::MacCall> {
loop {
match &ty.kind {
ast::TyKind::MacCall(mac) => {
break (mac.args.delim == Delimiter::Brace).then_some(mac);
}
ast::TyKind::Ptr(mut_ty) | ast::TyKind::Ref(_, mut_ty) => {
ty = &mut_ty.ty;
}
ast::TyKind::BareFn(fn_ty) => match &fn_ty.decl.output {
ast::FnRetTy::Default(_) => break None,
ast::FnRetTy::Ty(ret) => ty = ret,
},
ast::TyKind::Path(_, path) => match path_return_type(path) {
Some(trailing_ty) => ty = trailing_ty,
None => break None,
},
ast::TyKind::TraitObject(bounds, _) | ast::TyKind::ImplTrait(_, bounds, _) => {
match bounds.last() {
Some(ast::GenericBound::Trait(bound, _)) => {
match path_return_type(&bound.trait_ref.path) {
Some(trailing_ty) => ty = trailing_ty,
None => break None,
}
}
Some(ast::GenericBound::Outlives(_)) | None => break None,
}
}
ast::TyKind::Slice(..)
| ast::TyKind::Array(..)
| ast::TyKind::Never
| ast::TyKind::Tup(..)
| ast::TyKind::Paren(..)
| ast::TyKind::Typeof(..)
| ast::TyKind::Infer
| ast::TyKind::ImplicitSelf
| ast::TyKind::CVarArgs
| ast::TyKind::Pat(..)
| ast::TyKind::Dummy
| ast::TyKind::Err(..) => break None,
// These end in brace, but cannot occur in a let-else statement.
// They are only parsed as fields of a data structure. For the
// purpose of denying trailing braces in the expression of a
// let-else, we can disregard these.
ast::TyKind::AnonStruct(..) | ast::TyKind::AnonUnion(..) => break None,
}
}
}
/// Returns the trailing return type in the given path, if it has one.
///
/// ```ignore (illustrative)
/// ::std::ops::FnOnce(&str) -> fn() -> *const c_void
/// ^^^^^^^^^^^^^^^^^^^^^
/// ```
fn path_return_type(path: &ast::Path) -> Option<&ast::Ty> {
let last_segment = path.segments.last()?;
let args = last_segment.args.as_ref()?;
match &**args {
ast::GenericArgs::Parenthesized(args) => match &args.output {
ast::FnRetTy::Default(_) => None,
ast::FnRetTy::Ty(ret) => Some(ret),
},
ast::GenericArgs::AngleBracketed(_) => None,
}
}

View File

@ -15,7 +15,7 @@ use ast::Label;
use rustc_ast as ast; use rustc_ast as ast;
use rustc_ast::ptr::P; use rustc_ast::ptr::P;
use rustc_ast::token::{self, Delimiter, TokenKind}; use rustc_ast::token::{self, Delimiter, TokenKind};
use rustc_ast::util::classify; use rustc_ast::util::classify::{self, TrailingBrace};
use rustc_ast::{AttrStyle, AttrVec, LocalKind, MacCall, MacCallStmt, MacStmtStyle}; use rustc_ast::{AttrStyle, AttrVec, LocalKind, MacCall, MacCallStmt, MacStmtStyle};
use rustc_ast::{Block, BlockCheckMode, Expr, ExprKind, HasAttrs, Local, Recovered, Stmt}; use rustc_ast::{Block, BlockCheckMode, Expr, ExprKind, HasAttrs, Local, Recovered, Stmt};
use rustc_ast::{StmtKind, DUMMY_NODE_ID}; use rustc_ast::{StmtKind, DUMMY_NODE_ID};
@ -407,18 +407,24 @@ impl<'a> Parser<'a> {
fn check_let_else_init_trailing_brace(&self, init: &ast::Expr) { fn check_let_else_init_trailing_brace(&self, init: &ast::Expr) {
if let Some(trailing) = classify::expr_trailing_brace(init) { if let Some(trailing) = classify::expr_trailing_brace(init) {
let sugg = match &trailing.kind { let (span, sugg) = match trailing {
ExprKind::MacCall(mac) => errors::WrapInParentheses::MacroArgs { TrailingBrace::MacCall(mac) => (
left: mac.args.dspan.open, mac.span(),
right: mac.args.dspan.close, errors::WrapInParentheses::MacroArgs {
}, left: mac.args.dspan.open,
_ => errors::WrapInParentheses::Expression { right: mac.args.dspan.close,
left: trailing.span.shrink_to_lo(), },
right: trailing.span.shrink_to_hi(), ),
}, TrailingBrace::Expr(expr) => (
expr.span,
errors::WrapInParentheses::Expression {
left: expr.span.shrink_to_lo(),
right: expr.span.shrink_to_hi(),
},
),
}; };
self.dcx().emit_err(errors::InvalidCurlyInLetElse { self.dcx().emit_err(errors::InvalidCurlyInLetElse {
span: trailing.span.with_lo(trailing.span.hi() - BytePos(1)), span: span.with_lo(span.hi() - BytePos(1)),
sugg, sugg,
}); });
} }

View File

@ -3,8 +3,7 @@
#![feature(explicit_tail_calls)] #![feature(explicit_tail_calls)]
fn a() { fn a() {
let foo = { let 0 = {
//~^ WARN irrefutable `let...else` pattern
1 1
} else { } else {
//~^ ERROR right curly brace `}` before `else` in a `let...else` statement not allowed //~^ ERROR right curly brace `}` before `else` in a `let...else` statement not allowed
@ -22,8 +21,7 @@ fn b() {
} }
fn c() { fn c() {
let foo = if true { let 0 = if true {
//~^ WARN irrefutable `let...else` pattern
1 1
} else { } else {
0 0
@ -43,8 +41,7 @@ fn d() {
} }
fn e() { fn e() {
let foo = match true { let 0 = match true {
//~^ WARN irrefutable `let...else` pattern
true => 1, true => 1,
false => 0 false => 0
} else { } else {
@ -53,10 +50,12 @@ fn e() {
}; };
} }
struct X {a: i32}
fn f() { fn f() {
let foo = X { struct X {
//~^ WARN irrefutable `let...else` pattern a: i32,
}
let X { a: 0 } = X {
a: 1 a: 1
} else { } else {
//~^ ERROR right curly brace `}` before `else` in a `let...else` statement not allowed //~^ ERROR right curly brace `}` before `else` in a `let...else` statement not allowed
@ -74,8 +73,7 @@ fn g() {
} }
fn h() { fn h() {
let foo = const { let 0 = const {
//~^ WARN irrefutable `let...else` pattern
1 1
} else { } else {
//~^ ERROR right curly brace `}` before `else` in a `let...else` statement not allowed //~^ ERROR right curly brace `}` before `else` in a `let...else` statement not allowed
@ -84,8 +82,7 @@ fn h() {
} }
fn i() { fn i() {
let foo = &{ let 0 = &{
//~^ WARN irrefutable `let...else` pattern
1 1
} else { } else {
//~^ ERROR right curly brace `}` before `else` in a `let...else` statement not allowed //~^ ERROR right curly brace `}` before `else` in a `let...else` statement not allowed
@ -94,8 +91,8 @@ fn i() {
} }
fn j() { fn j() {
let bar = 0; let mut bar = 0;
let foo = bar = { //~ ERROR: cannot assign twice let foo = bar = {
//~^ WARN irrefutable `let...else` pattern //~^ WARN irrefutable `let...else` pattern
1 1
} else { } else {
@ -105,8 +102,7 @@ fn j() {
} }
fn k() { fn k() {
let foo = 1 + { let 0 = 1 + {
//~^ WARN irrefutable `let...else` pattern
1 1
} else { } else {
//~^ ERROR right curly brace `}` before `else` in a `let...else` statement not allowed //~^ ERROR right curly brace `}` before `else` in a `let...else` statement not allowed
@ -115,8 +111,8 @@ fn k() {
} }
fn l() { fn l() {
let foo = 1..{ const RANGE: std::ops::Range<u8> = 0..0;
//~^ WARN irrefutable `let...else` pattern let RANGE = 1..{
1 1
} else { } else {
//~^ ERROR right curly brace `}` before `else` in a `let...else` statement not allowed //~^ ERROR right curly brace `}` before `else` in a `let...else` statement not allowed
@ -125,8 +121,7 @@ fn l() {
} }
fn m() { fn m() {
let foo = return { let 0 = return {
//~^ WARN irrefutable `let...else` pattern
() ()
} else { } else {
//~^ ERROR right curly brace `}` before `else` in a `let...else` statement not allowed //~^ ERROR right curly brace `}` before `else` in a `let...else` statement not allowed
@ -135,8 +130,7 @@ fn m() {
} }
fn n() { fn n() {
let foo = -{ let 0 = -{
//~^ WARN irrefutable `let...else` pattern
1 1
} else { } else {
//~^ ERROR right curly brace `}` before `else` in a `let...else` statement not allowed //~^ ERROR right curly brace `}` before `else` in a `let...else` statement not allowed
@ -145,8 +139,7 @@ fn n() {
} }
fn o() -> Result<(), ()> { fn o() -> Result<(), ()> {
let foo = do yeet { let 0 = do yeet {
//~^ WARN irrefutable `let...else` pattern
() ()
} else { } else {
//~^ ERROR right curly brace `}` before `else` in a `let...else` statement not allowed //~^ ERROR right curly brace `}` before `else` in a `let...else` statement not allowed
@ -155,8 +148,7 @@ fn o() -> Result<(), ()> {
} }
fn p() { fn p() {
let foo = become { let 0 = become {
//~^ WARN irrefutable `let...else` pattern
() ()
} else { } else {
//~^ ERROR right curly brace `}` before `else` in a `let...else` statement not allowed //~^ ERROR right curly brace `}` before `else` in a `let...else` statement not allowed
@ -185,22 +177,37 @@ fn r() {
fn s() { fn s() {
macro_rules! a { macro_rules! a {
() => { {} } () => {
//~^ WARN irrefutable `let...else` pattern { 1 }
//~| WARN irrefutable `let...else` pattern };
} }
macro_rules! b { macro_rules! b {
(1) => { (1) => {
let x = a!() else { return; }; let 0 = a!() else { return; };
}; };
(2) => { (2) => {
let x = a! {} else { return; }; let 0 = a! {} else { return; };
//~^ ERROR right curly brace `}` before `else` in a `let...else` statement not allowed //~^ ERROR right curly brace `}` before `else` in a `let...else` statement not allowed
}; };
} }
b!(1); b!(2); b!(1);
b!(2);
}
fn t() {
macro_rules! primitive {
(8) => { u8 };
}
let foo = &std::ptr::null as &'static dyn std::ops::Fn() -> *const primitive! {
//~^ WARN irrefutable `let...else` pattern
8
} else {
//~^ ERROR right curly brace `}` before `else` in a `let...else` statement not allowed
return;
};
} }
fn main() {} fn main() {}

View File

@ -1,19 +1,18 @@
error: right curly brace `}` before `else` in a `let...else` statement not allowed error: right curly brace `}` before `else` in a `let...else` statement not allowed
--> $DIR/bad-let-else-statement.rs:9:5 --> $DIR/bad-let-else-statement.rs:8:5
| |
LL | } else { LL | } else {
| ^ | ^
| |
help: wrap the expression in parentheses help: wrap the expression in parentheses
| |
LL ~ let foo = ({ LL ~ let 0 = ({
LL |
LL | 1 LL | 1
LL ~ }) else { LL ~ }) else {
| |
error: `for...else` loops are not supported error: `for...else` loops are not supported
--> $DIR/bad-let-else-statement.rs:18:7 --> $DIR/bad-let-else-statement.rs:17:7
| |
LL | let foo = for i in 1..2 { LL | let foo = for i in 1..2 {
| --- `else` is attached to this loop | --- `else` is attached to this loop
@ -28,22 +27,22 @@ LL | | };
= note: consider moving this `else` clause to a separate `if` statement and use a `bool` variable to control if it should run = 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 error: right curly brace `}` before `else` in a `let...else` statement not allowed
--> $DIR/bad-let-else-statement.rs:30:5 --> $DIR/bad-let-else-statement.rs:28:5
| |
LL | } else { LL | } else {
| ^ | ^
| |
help: wrap the expression in parentheses help: wrap the expression in parentheses
| |
LL ~ let foo = (if true { LL ~ let 0 = (if true {
LL | LL | 1
... LL | } else {
LL | 0 LL | 0
LL ~ }) else { LL ~ }) else {
| |
error: `loop...else` loops are not supported error: `loop...else` loops are not supported
--> $DIR/bad-let-else-statement.rs:39:7 --> $DIR/bad-let-else-statement.rs:37:7
| |
LL | let foo = loop { LL | let foo = loop {
| ---- `else` is attached to this loop | ---- `else` is attached to this loop
@ -58,36 +57,34 @@ LL | | };
= note: consider moving this `else` clause to a separate `if` statement and use a `bool` variable to control if it should run = 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 error: right curly brace `}` before `else` in a `let...else` statement not allowed
--> $DIR/bad-let-else-statement.rs:50:5 --> $DIR/bad-let-else-statement.rs:47:5
| |
LL | } else { LL | } else {
| ^ | ^
| |
help: wrap the expression in parentheses help: wrap the expression in parentheses
| |
LL ~ let foo = (match true { LL ~ let 0 = (match true {
LL |
LL | true => 1, LL | true => 1,
LL | false => 0 LL | false => 0
LL ~ }) else { LL ~ }) else {
| |
error: right curly brace `}` before `else` in a `let...else` statement not allowed error: right curly brace `}` before `else` in a `let...else` statement not allowed
--> $DIR/bad-let-else-statement.rs:61:5 --> $DIR/bad-let-else-statement.rs:60:5
| |
LL | } else { LL | } else {
| ^ | ^
| |
help: wrap the expression in parentheses help: wrap the expression in parentheses
| |
LL ~ let foo = (X { LL ~ let X { a: 0 } = (X {
LL |
LL | a: 1 LL | a: 1
LL ~ }) else { LL ~ }) else {
| |
error: `while...else` loops are not supported error: `while...else` loops are not supported
--> $DIR/bad-let-else-statement.rs:70:7 --> $DIR/bad-let-else-statement.rs:69:7
| |
LL | let foo = while false { LL | let foo = while false {
| ----- `else` is attached to this loop | ----- `else` is attached to this loop
@ -102,35 +99,33 @@ LL | | };
= note: consider moving this `else` clause to a separate `if` statement and use a `bool` variable to control if it should run = 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 error: right curly brace `}` before `else` in a `let...else` statement not allowed
--> $DIR/bad-let-else-statement.rs:80:5 --> $DIR/bad-let-else-statement.rs:78:5
| |
LL | } else { LL | } else {
| ^ | ^
| |
help: wrap the expression in parentheses help: wrap the expression in parentheses
| |
LL ~ let foo = (const { LL ~ let 0 = (const {
LL |
LL | 1 LL | 1
LL ~ }) else { LL ~ }) else {
| |
error: right curly brace `}` before `else` in a `let...else` statement not allowed error: right curly brace `}` before `else` in a `let...else` statement not allowed
--> $DIR/bad-let-else-statement.rs:90:5 --> $DIR/bad-let-else-statement.rs:87:5
| |
LL | } else { LL | } else {
| ^ | ^
| |
help: wrap the expression in parentheses help: wrap the expression in parentheses
| |
LL ~ let foo = &({ LL ~ let 0 = &({
LL |
LL | 1 LL | 1
LL ~ }) else { LL ~ }) else {
| |
error: right curly brace `}` before `else` in a `let...else` statement not allowed error: right curly brace `}` before `else` in a `let...else` statement not allowed
--> $DIR/bad-let-else-statement.rs:101:5 --> $DIR/bad-let-else-statement.rs:98:5
| |
LL | } else { LL | } else {
| ^ | ^
@ -144,91 +139,85 @@ LL ~ }) else {
| |
error: right curly brace `}` before `else` in a `let...else` statement not allowed error: right curly brace `}` before `else` in a `let...else` statement not allowed
--> $DIR/bad-let-else-statement.rs:111:5 --> $DIR/bad-let-else-statement.rs:107:5
| |
LL | } else { LL | } else {
| ^ | ^
| |
help: wrap the expression in parentheses help: wrap the expression in parentheses
| |
LL ~ let foo = 1 + ({ LL ~ let 0 = 1 + ({
LL |
LL | 1 LL | 1
LL ~ }) else { LL ~ }) else {
| |
error: right curly brace `}` before `else` in a `let...else` statement not allowed error: right curly brace `}` before `else` in a `let...else` statement not allowed
--> $DIR/bad-let-else-statement.rs:121:5 --> $DIR/bad-let-else-statement.rs:117:5
| |
LL | } else { LL | } else {
| ^ | ^
| |
help: wrap the expression in parentheses help: wrap the expression in parentheses
| |
LL ~ let foo = 1..({ LL ~ let RANGE = 1..({
LL |
LL | 1 LL | 1
LL ~ }) else { LL ~ }) else {
| |
error: right curly brace `}` before `else` in a `let...else` statement not allowed error: right curly brace `}` before `else` in a `let...else` statement not allowed
--> $DIR/bad-let-else-statement.rs:131:5 --> $DIR/bad-let-else-statement.rs:126:5
| |
LL | } else { LL | } else {
| ^ | ^
| |
help: wrap the expression in parentheses help: wrap the expression in parentheses
| |
LL ~ let foo = return ({ LL ~ let 0 = return ({
LL |
LL | () LL | ()
LL ~ }) else { LL ~ }) else {
| |
error: right curly brace `}` before `else` in a `let...else` statement not allowed error: right curly brace `}` before `else` in a `let...else` statement not allowed
--> $DIR/bad-let-else-statement.rs:141:5 --> $DIR/bad-let-else-statement.rs:135:5
| |
LL | } else { LL | } else {
| ^ | ^
| |
help: wrap the expression in parentheses help: wrap the expression in parentheses
| |
LL ~ let foo = -({ LL ~ let 0 = -({
LL |
LL | 1 LL | 1
LL ~ }) else { LL ~ }) else {
| |
error: right curly brace `}` before `else` in a `let...else` statement not allowed error: right curly brace `}` before `else` in a `let...else` statement not allowed
--> $DIR/bad-let-else-statement.rs:151:5 --> $DIR/bad-let-else-statement.rs:144:5
| |
LL | } else { LL | } else {
| ^ | ^
| |
help: wrap the expression in parentheses help: wrap the expression in parentheses
| |
LL ~ let foo = do yeet ({ LL ~ let 0 = do yeet ({
LL |
LL | () LL | ()
LL ~ }) else { LL ~ }) else {
| |
error: right curly brace `}` before `else` in a `let...else` statement not allowed error: right curly brace `}` before `else` in a `let...else` statement not allowed
--> $DIR/bad-let-else-statement.rs:161:5 --> $DIR/bad-let-else-statement.rs:153:5
| |
LL | } else { LL | } else {
| ^ | ^
| |
help: wrap the expression in parentheses help: wrap the expression in parentheses
| |
LL ~ let foo = become ({ LL ~ let 0 = become ({
LL |
LL | () LL | ()
LL ~ }) else { LL ~ }) else {
| |
error: right curly brace `}` before `else` in a `let...else` statement not allowed error: right curly brace `}` before `else` in a `let...else` statement not allowed
--> $DIR/bad-let-else-statement.rs:171:5 --> $DIR/bad-let-else-statement.rs:163:5
| |
LL | } else { LL | } else {
| ^ | ^
@ -242,7 +231,7 @@ LL ~ }) else {
| |
error: right curly brace `}` before `else` in a `let...else` statement not allowed error: right curly brace `}` before `else` in a `let...else` statement not allowed
--> $DIR/bad-let-else-statement.rs:181:31 --> $DIR/bad-let-else-statement.rs:173:31
| |
LL | let bad = format_args! {""} else { return; }; LL | let bad = format_args! {""} else { return; };
| ^ | ^
@ -253,24 +242,38 @@ LL | let bad = format_args! ("") else { return; };
| ~ ~ | ~ ~
error: right curly brace `}` before `else` in a `let...else` statement not allowed error: right curly brace `}` before `else` in a `let...else` statement not allowed
--> $DIR/bad-let-else-statement.rs:198:25 --> $DIR/bad-let-else-statement.rs:207:5
| |
LL | let x = a! {} else { return; }; LL | } else {
| ^
|
help: use parentheses instead of braces for this macro
|
LL ~ let foo = &std::ptr::null as &'static dyn std::ops::Fn() -> *const primitive! (
LL |
LL | 8
LL ~ ) else {
|
error: right curly brace `}` before `else` in a `let...else` statement not allowed
--> $DIR/bad-let-else-statement.rs:190:25
|
LL | let 0 = a! {} else { return; };
| ^ | ^
... ...
LL | b!(1); b!(2); LL | b!(2);
| ----- in this macro invocation | ----- in this macro invocation
| |
= note: this error originates in the macro `b` (in Nightly builds, run with -Z macro-backtrace for more info) = note: this error originates in the macro `b` (in Nightly builds, run with -Z macro-backtrace for more info)
help: use parentheses instead of braces for this macro help: use parentheses instead of braces for this macro
| |
LL | let x = a! () else { return; }; LL | let 0 = a! () else { return; };
| ~~ | ~~
warning: irrefutable `let...else` pattern warning: irrefutable `let...else` pattern
--> $DIR/bad-let-else-statement.rs:6:5 --> $DIR/bad-let-else-statement.rs:95:5
| |
LL | / let foo = { LL | / let foo = bar = {
LL | | LL | |
LL | | 1 LL | | 1
LL | | } else { LL | | } else {
@ -281,169 +284,7 @@ LL | | } else {
= note: `#[warn(irrefutable_let_patterns)]` on by default = note: `#[warn(irrefutable_let_patterns)]` on by default
warning: irrefutable `let...else` pattern warning: irrefutable `let...else` pattern
--> $DIR/bad-let-else-statement.rs:25:5 --> $DIR/bad-let-else-statement.rs:160:5
|
LL | / let foo = if true {
LL | |
LL | | 1
LL | | } else {
LL | | 0
LL | | } else {
| |_____^
|
= note: this pattern will always match, so the `else` clause is useless
= help: consider removing the `else` clause
warning: irrefutable `let...else` pattern
--> $DIR/bad-let-else-statement.rs:46:5
|
LL | / let foo = match true {
LL | |
LL | | true => 1,
LL | | false => 0
LL | | } else {
| |_____^
|
= note: this pattern will always match, so the `else` clause is useless
= help: consider removing the `else` clause
warning: irrefutable `let...else` pattern
--> $DIR/bad-let-else-statement.rs:58:5
|
LL | / let foo = X {
LL | |
LL | | a: 1
LL | | } else {
| |_____^
|
= note: this pattern will always match, so the `else` clause is useless
= help: consider removing the `else` clause
warning: irrefutable `let...else` pattern
--> $DIR/bad-let-else-statement.rs:77:5
|
LL | / let foo = const {
LL | |
LL | | 1
LL | | } else {
| |_____^
|
= note: this pattern will always match, so the `else` clause is useless
= help: consider removing the `else` clause
warning: irrefutable `let...else` pattern
--> $DIR/bad-let-else-statement.rs:87:5
|
LL | / let foo = &{
LL | |
LL | | 1
LL | | } else {
| |_____^
|
= note: this pattern will always match, so the `else` clause is useless
= help: consider removing the `else` clause
warning: irrefutable `let...else` pattern
--> $DIR/bad-let-else-statement.rs:98:5
|
LL | / let foo = bar = {
LL | |
LL | | 1
LL | | } else {
| |_____^
|
= note: this pattern will always match, so the `else` clause is useless
= help: consider removing the `else` clause
error[E0384]: cannot assign twice to immutable variable `bar`
--> $DIR/bad-let-else-statement.rs:98:15
|
LL | let bar = 0;
| ---
| |
| first assignment to `bar`
| help: consider making this binding mutable: `mut bar`
LL | let foo = bar = {
| _______________^
LL | |
LL | | 1
LL | | } else {
| |_____^ cannot assign twice to immutable variable
warning: irrefutable `let...else` pattern
--> $DIR/bad-let-else-statement.rs:108:5
|
LL | / let foo = 1 + {
LL | |
LL | | 1
LL | | } else {
| |_____^
|
= note: this pattern will always match, so the `else` clause is useless
= help: consider removing the `else` clause
warning: irrefutable `let...else` pattern
--> $DIR/bad-let-else-statement.rs:118:5
|
LL | / let foo = 1..{
LL | |
LL | | 1
LL | | } else {
| |_____^
|
= note: this pattern will always match, so the `else` clause is useless
= help: consider removing the `else` clause
warning: irrefutable `let...else` pattern
--> $DIR/bad-let-else-statement.rs:128:5
|
LL | / let foo = return {
LL | |
LL | | ()
LL | | } else {
| |_____^
|
= note: this pattern will always match, so the `else` clause is useless
= help: consider removing the `else` clause
warning: irrefutable `let...else` pattern
--> $DIR/bad-let-else-statement.rs:138:5
|
LL | / let foo = -{
LL | |
LL | | 1
LL | | } else {
| |_____^
|
= note: this pattern will always match, so the `else` clause is useless
= help: consider removing the `else` clause
warning: irrefutable `let...else` pattern
--> $DIR/bad-let-else-statement.rs:148:5
|
LL | / let foo = do yeet {
LL | |
LL | | ()
LL | | } else {
| |_____^
|
= note: this pattern will always match, so the `else` clause is useless
= help: consider removing the `else` clause
warning: irrefutable `let...else` pattern
--> $DIR/bad-let-else-statement.rs:158:5
|
LL | / let foo = become {
LL | |
LL | | ()
LL | | } else {
| |_____^
|
= note: this pattern will always match, so the `else` clause is useless
= help: consider removing the `else` clause
warning: irrefutable `let...else` pattern
--> $DIR/bad-let-else-statement.rs:168:5
| |
LL | / let foo = |x: i32| { LL | / let foo = |x: i32| {
LL | | LL | |
@ -455,7 +296,7 @@ LL | | } else {
= help: consider removing the `else` clause = help: consider removing the `else` clause
warning: irrefutable `let...else` pattern warning: irrefutable `let...else` pattern
--> $DIR/bad-let-else-statement.rs:178:5 --> $DIR/bad-let-else-statement.rs:170:5
| |
LL | let ok = format_args!("") else { return; }; LL | let ok = format_args!("") else { return; };
| ^^^^^^^^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^^^^^^^^
@ -464,7 +305,7 @@ LL | let ok = format_args!("") else { return; };
= help: consider removing the `else` clause = help: consider removing the `else` clause
warning: irrefutable `let...else` pattern warning: irrefutable `let...else` pattern
--> $DIR/bad-let-else-statement.rs:181:5 --> $DIR/bad-let-else-statement.rs:173:5
| |
LL | let bad = format_args! {""} else { return; }; LL | let bad = format_args! {""} else { return; };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^
@ -473,45 +314,16 @@ LL | let bad = format_args! {""} else { return; };
= help: consider removing the `else` clause = help: consider removing the `else` clause
warning: irrefutable `let...else` pattern warning: irrefutable `let...else` pattern
--> $DIR/bad-let-else-statement.rs:188:19 --> $DIR/bad-let-else-statement.rs:204:5
| |
LL | () => { {} } LL | / let foo = &std::ptr::null as &'static dyn std::ops::Fn() -> *const primitive! {
| ___________________^
LL | | LL | |
LL | | LL | | 8
LL | | } LL | | } else {
... | | |_____^
LL | | (1) => {
LL | | let x = a!() else { return; };
| |____________^
...
LL | b!(1); b!(2);
| ----- in this macro invocation
| |
= note: this pattern will always match, so the `else` clause is useless = note: this pattern will always match, so the `else` clause is useless
= help: consider removing the `else` clause = help: consider removing the `else` clause
= note: this warning originates in the macro `b` (in Nightly builds, run with -Z macro-backtrace for more info)
warning: irrefutable `let...else` pattern error: aborting due to 20 previous errors; 5 warnings emitted
--> $DIR/bad-let-else-statement.rs:188:19
|
LL | () => { {} }
| ___________________^
LL | |
LL | |
LL | | }
... |
LL | | (2) => {
LL | | let x = a! {} else { return; };
| |____________^
...
LL | b!(1); b!(2);
| ----- in this macro invocation
|
= note: this pattern will always match, so the `else` clause is useless
= help: consider removing the `else` clause
= note: this warning originates in the macro `b` (in Nightly builds, run with -Z macro-backtrace for more info)
error: aborting due to 20 previous errors; 18 warnings emitted
For more information about this error, try `rustc --explain E0384`.