Skip to content

Commit 6a62871

Browse files
committedDec 17, 2023
Auto merge of #119053 - matthiaskrgr:rollup-hky3ld3, r=matthiaskrgr
Rollup of 4 pull requests Successful merges: - #118880 (More expressions correctly are marked to end with curly braces) - #118928 (fix: Overlapping spans in delimited meta-vars) - #119022 (Remove unnecessary constness from ProjectionCandidate) - #119052 (Avoid overflow in GVN constant indexing.) r? `@ghost` `@rustbot` modify labels: rollup
·
1.90.01.76.0
2 parents 4283aea + 39fe059 commit 6a62871

File tree

14 files changed

+739
-27
lines changed

14 files changed

+739
-27
lines changed
 

‎compiler/rustc_ast/src/util/classify.rs‎

Lines changed: 32 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -40,15 +40,44 @@ pub fn expr_trailing_brace(mut expr: &ast::Expr) -> Option<&ast::Expr> {
4040
| Range(_, Some(e), _)
4141
| Ret(Some(e))
4242
| Unary(_, e)
43-
| Yield(Some(e)) => {
43+
| Yield(Some(e))
44+
| Yeet(Some(e))
45+
| Become(e) => {
4446
expr = e;
4547
}
4648
Closure(closure) => {
4749
expr = &closure.body;
4850
}
4951
Gen(..) | Block(..) | ForLoop(..) | If(..) | Loop(..) | Match(..) | Struct(..)
50-
| TryBlock(..) | While(..) => break Some(expr),
51-
_ => break None,
52+
| TryBlock(..) | While(..) | ConstBlock(_) => break Some(expr),
53+
54+
// FIXME: These can end in `}`, but changing these would break stable code.
55+
InlineAsm(_) | OffsetOf(_, _) | MacCall(_) | IncludedBytes(_) | FormatArgs(_) => {
56+
break None;
57+
}
58+
59+
Break(_, None)
60+
| Range(_, None, _)
61+
| Ret(None)
62+
| Yield(None)
63+
| Array(_)
64+
| Call(_, _)
65+
| MethodCall(_)
66+
| Tup(_)
67+
| Lit(_)
68+
| Cast(_, _)
69+
| Type(_, _)
70+
| Await(_, _)
71+
| Field(_, _)
72+
| Index(_, _, _)
73+
| Underscore
74+
| Path(_, _)
75+
| Continue(_)
76+
| Repeat(_, _)
77+
| Paren(_)
78+
| Try(_)
79+
| Yeet(None)
80+
| Err => break None,
5281
}
5382
}
5483
}

‎compiler/rustc_expand/src/mbe/macro_rules.rs‎

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -236,6 +236,13 @@ fn expand_macro<'cx>(
236236
target_sp.open = source_sp.open.with_ctxt(ctxt);
237237
target_sp.close = source_sp.close.with_ctxt(ctxt);
238238
}
239+
(
240+
TokenTree::Delimited(target_sp, ..),
241+
mbe::TokenTree::MetaVar(source_sp, ..),
242+
) => {
243+
target_sp.open = source_sp.with_ctxt(ctxt);
244+
target_sp.close = source_sp.with_ctxt(ctxt).shrink_to_hi();
245+
}
239246
_ => {
240247
let sp = rhs_tt.span().with_ctxt(ctxt);
241248
tt.set_span(sp);

‎compiler/rustc_middle/src/traits/select.rs‎

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -125,10 +125,8 @@ pub enum SelectionCandidate<'tcx> {
125125

126126
/// This is a trait matching with a projected type as `Self`, and we found
127127
/// an applicable bound in the trait definition. The `usize` is an index
128-
/// into the list returned by `tcx.item_bounds`. The constness is the
129-
/// constness of the bound in the trait.
130-
// FIXME(effects) do we need this constness
131-
ProjectionCandidate(usize, ty::BoundConstness),
128+
/// into the list returned by `tcx.item_bounds`.
129+
ProjectionCandidate(usize),
132130

133131
/// Implementation of a `Fn`-family trait by one of the anonymous types
134132
/// generated for an `||` expression.

‎compiler/rustc_mir_transform/src/gvn.rs‎

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -644,12 +644,10 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
644644
{
645645
if let Some(offset) = self.evaluated[idx].as_ref()
646646
&& let Ok(offset) = self.ecx.read_target_usize(offset)
647+
&& let Some(min_length) = offset.checked_add(1)
647648
{
648-
projection.to_mut()[i] = ProjectionElem::ConstantIndex {
649-
offset,
650-
min_length: offset + 1,
651-
from_end: false,
652-
};
649+
projection.to_mut()[i] =
650+
ProjectionElem::ConstantIndex { offset, min_length, from_end: false };
653651
} else if let Some(new_idx) = self.try_as_local(idx, location) {
654652
projection.to_mut()[i] = ProjectionElem::Index(new_idx);
655653
self.reused_locals.insert(new_idx);

‎compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs‎

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -154,10 +154,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
154154
.infcx
155155
.probe(|_| self.match_projection_obligation_against_definition_bounds(obligation));
156156

157-
// FIXME(effects) proper constness needed?
158-
candidates.vec.extend(
159-
result.into_iter().map(|idx| ProjectionCandidate(idx, ty::BoundConstness::NotConst)),
160-
);
157+
candidates.vec.extend(result.into_iter().map(|idx| ProjectionCandidate(idx)));
161158
}
162159

163160
/// Given an obligation like `<SomeTrait for T>`, searches the obligations that the caller
@@ -585,7 +582,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
585582
}
586583

587584
ty::Alias(ty::Opaque, _) => {
588-
if candidates.vec.iter().any(|c| matches!(c, ProjectionCandidate(..))) {
585+
if candidates.vec.iter().any(|c| matches!(c, ProjectionCandidate(_))) {
589586
// We do not generate an auto impl candidate for `impl Trait`s which already
590587
// reference our auto trait.
591588
//

‎compiler/rustc_trait_selection/src/traits/select/confirmation.rs‎

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
7171
ImplSource::Builtin(BuiltinImplSource::Misc, data)
7272
}
7373

74-
ProjectionCandidate(idx, _) => {
74+
ProjectionCandidate(idx) => {
7575
let obligations = self.confirm_projection_candidate(obligation, idx)?;
7676
ImplSource::Param(obligations)
7777
}
@@ -1313,7 +1313,6 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
13131313
// If we have a projection type, make sure to normalize it so we replace it
13141314
// with a fresh infer variable
13151315
ty::Alias(ty::Projection | ty::Inherent, ..) => {
1316-
// FIXME(effects) this needs constness
13171316
let predicate = normalize_with_depth_to(
13181317
self,
13191318
obligation.param_env,
@@ -1344,7 +1343,6 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
13441343
// since it's either not `const Drop` (and we raise an error during selection),
13451344
// or it's an ADT (and we need to check for a custom impl during selection)
13461345
_ => {
1347-
// FIXME(effects) this needs constness
13481346
let predicate = self_ty.rebind(ty::TraitPredicate {
13491347
trait_ref: ty::TraitRef::from_lang_item(
13501348
self.tcx(),

‎compiler/rustc_trait_selection/src/traits/select/mod.rs‎

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1883,7 +1883,7 @@ impl<'tcx> SelectionContext<'_, 'tcx> {
18831883
| BuiltinCandidate { .. }
18841884
| TraitAliasCandidate
18851885
| ObjectCandidate(_)
1886-
| ProjectionCandidate(..),
1886+
| ProjectionCandidate(_),
18871887
) => {
18881888
// We have a where clause so don't go around looking
18891889
// for impls. Arbitrarily give param candidates priority
@@ -1893,7 +1893,7 @@ impl<'tcx> SelectionContext<'_, 'tcx> {
18931893
// here (see issue #50825).
18941894
DropVictim::drop_if(!is_global(other_cand))
18951895
}
1896-
(ObjectCandidate(_) | ProjectionCandidate(..), ParamCandidate(ref victim_cand)) => {
1896+
(ObjectCandidate(_) | ProjectionCandidate(_), ParamCandidate(ref victim_cand)) => {
18971897
// Prefer these to a global where-clause bound
18981898
// (see issue #50825).
18991899
if is_global(victim_cand) { DropVictim::Yes } else { DropVictim::No }
@@ -1921,20 +1921,20 @@ impl<'tcx> SelectionContext<'_, 'tcx> {
19211921
)
19221922
}
19231923

1924-
(ProjectionCandidate(i, _), ProjectionCandidate(j, _))
1924+
(ProjectionCandidate(i), ProjectionCandidate(j))
19251925
| (ObjectCandidate(i), ObjectCandidate(j)) => {
19261926
// Arbitrarily pick the lower numbered candidate for backwards
19271927
// compatibility reasons. Don't let this affect inference.
19281928
DropVictim::drop_if(i < j && !has_non_region_infer)
19291929
}
1930-
(ObjectCandidate(_), ProjectionCandidate(..))
1931-
| (ProjectionCandidate(..), ObjectCandidate(_)) => {
1930+
(ObjectCandidate(_), ProjectionCandidate(_))
1931+
| (ProjectionCandidate(_), ObjectCandidate(_)) => {
19321932
bug!("Have both object and projection candidate")
19331933
}
19341934

19351935
// Arbitrarily give projection and object candidates priority.
19361936
(
1937-
ObjectCandidate(_) | ProjectionCandidate(..),
1937+
ObjectCandidate(_) | ProjectionCandidate(_),
19381938
ImplCandidate(..)
19391939
| AutoImplCandidate
19401940
| ClosureCandidate { .. }
@@ -1964,7 +1964,7 @@ impl<'tcx> SelectionContext<'_, 'tcx> {
19641964
| TraitUpcastingUnsizeCandidate(_)
19651965
| BuiltinCandidate { .. }
19661966
| TraitAliasCandidate,
1967-
ObjectCandidate(_) | ProjectionCandidate(..),
1967+
ObjectCandidate(_) | ProjectionCandidate(_),
19681968
) => DropVictim::No,
19691969

19701970
(&ImplCandidate(other_def), &ImplCandidate(victim_def)) => {
Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
- // MIR for `constant_index_overflow` before GVN
2+
+ // MIR for `constant_index_overflow` after GVN
3+
4+
fn constant_index_overflow(_1: &[T]) -> () {
5+
debug x => _1;
6+
let mut _0: ();
7+
let _2: usize;
8+
let mut _4: bool;
9+
let mut _5: usize;
10+
let mut _6: usize;
11+
let mut _7: &[T];
12+
let _8: usize;
13+
let mut _9: usize;
14+
let mut _10: bool;
15+
let _11: usize;
16+
let mut _12: usize;
17+
let mut _13: bool;
18+
let mut _14: T;
19+
scope 1 {
20+
debug a => _2;
21+
let _3: T;
22+
scope 2 {
23+
debug b => _3;
24+
}
25+
}
26+
27+
bb0: {
28+
- StorageLive(_2);
29+
- _2 = const _ as usize (IntToInt);
30+
+ nop;
31+
+ _2 = const usize::MAX;
32+
StorageLive(_3);
33+
StorageLive(_4);
34+
StorageLive(_5);
35+
- _5 = _2;
36+
+ _5 = const usize::MAX;
37+
StorageLive(_6);
38+
StorageLive(_7);
39+
_7 = &(*_1);
40+
_6 = core::slice::<impl [T]>::len(move _7) -> [return: bb1, unwind unreachable];
41+
}
42+
43+
bb1: {
44+
StorageDead(_7);
45+
- _4 = Lt(move _5, move _6);
46+
+ _4 = Lt(const usize::MAX, move _6);
47+
switchInt(move _4) -> [0: bb4, otherwise: bb2];
48+
}
49+
50+
bb2: {
51+
StorageDead(_6);
52+
StorageDead(_5);
53+
StorageLive(_8);
54+
- _8 = _2;
55+
+ _8 = const usize::MAX;
56+
_9 = Len((*_1));
57+
- _10 = Lt(_8, _9);
58+
- assert(move _10, "index out of bounds: the length is {} but the index is {}", move _9, _8) -> [success: bb3, unwind unreachable];
59+
+ _10 = Lt(const usize::MAX, _9);
60+
+ assert(move _10, "index out of bounds: the length is {} but the index is {}", move _9, const usize::MAX) -> [success: bb3, unwind unreachable];
61+
}
62+
63+
bb3: {
64+
- _3 = (*_1)[_8];
65+
+ _3 = (*_1)[_2];
66+
StorageDead(_8);
67+
goto -> bb6;
68+
}
69+
70+
bb4: {
71+
StorageDead(_6);
72+
StorageDead(_5);
73+
StorageLive(_11);
74+
_11 = const 0_usize;
75+
_12 = Len((*_1));
76+
- _13 = Lt(_11, _12);
77+
- assert(move _13, "index out of bounds: the length is {} but the index is {}", move _12, _11) -> [success: bb5, unwind unreachable];
78+
+ _13 = Lt(const 0_usize, _12);
79+
+ assert(move _13, "index out of bounds: the length is {} but the index is {}", move _12, const 0_usize) -> [success: bb5, unwind unreachable];
80+
}
81+
82+
bb5: {
83+
- _3 = (*_1)[_11];
84+
+ _3 = (*_1)[0 of 1];
85+
StorageDead(_11);
86+
goto -> bb6;
87+
}
88+
89+
bb6: {
90+
StorageDead(_4);
91+
StorageLive(_14);
92+
_14 = _3;
93+
_0 = opaque::<T>(move _14) -> [return: bb7, unwind unreachable];
94+
}
95+
96+
bb7: {
97+
StorageDead(_14);
98+
StorageDead(_3);
99+
- StorageDead(_2);
100+
+ nop;
101+
return;
102+
}
103+
}
104+
Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
- // MIR for `constant_index_overflow` before GVN
2+
+ // MIR for `constant_index_overflow` after GVN
3+
4+
fn constant_index_overflow(_1: &[T]) -> () {
5+
debug x => _1;
6+
let mut _0: ();
7+
let _2: usize;
8+
let mut _4: bool;
9+
let mut _5: usize;
10+
let mut _6: usize;
11+
let mut _7: &[T];
12+
let _8: usize;
13+
let mut _9: usize;
14+
let mut _10: bool;
15+
let _11: usize;
16+
let mut _12: usize;
17+
let mut _13: bool;
18+
let mut _14: T;
19+
scope 1 {
20+
debug a => _2;
21+
let _3: T;
22+
scope 2 {
23+
debug b => _3;
24+
}
25+
}
26+
27+
bb0: {
28+
- StorageLive(_2);
29+
- _2 = const _ as usize (IntToInt);
30+
+ nop;
31+
+ _2 = const usize::MAX;
32+
StorageLive(_3);
33+
StorageLive(_4);
34+
StorageLive(_5);
35+
- _5 = _2;
36+
+ _5 = const usize::MAX;
37+
StorageLive(_6);
38+
StorageLive(_7);
39+
_7 = &(*_1);
40+
_6 = core::slice::<impl [T]>::len(move _7) -> [return: bb1, unwind continue];
41+
}
42+
43+
bb1: {
44+
StorageDead(_7);
45+
- _4 = Lt(move _5, move _6);
46+
+ _4 = Lt(const usize::MAX, move _6);
47+
switchInt(move _4) -> [0: bb4, otherwise: bb2];
48+
}
49+
50+
bb2: {
51+
StorageDead(_6);
52+
StorageDead(_5);
53+
StorageLive(_8);
54+
- _8 = _2;
55+
+ _8 = const usize::MAX;
56+
_9 = Len((*_1));
57+
- _10 = Lt(_8, _9);
58+
- assert(move _10, "index out of bounds: the length is {} but the index is {}", move _9, _8) -> [success: bb3, unwind continue];
59+
+ _10 = Lt(const usize::MAX, _9);
60+
+ assert(move _10, "index out of bounds: the length is {} but the index is {}", move _9, const usize::MAX) -> [success: bb3, unwind continue];
61+
}
62+
63+
bb3: {
64+
- _3 = (*_1)[_8];
65+
+ _3 = (*_1)[_2];
66+
StorageDead(_8);
67+
goto -> bb6;
68+
}
69+
70+
bb4: {
71+
StorageDead(_6);
72+
StorageDead(_5);
73+
StorageLive(_11);
74+
_11 = const 0_usize;
75+
_12 = Len((*_1));
76+
- _13 = Lt(_11, _12);
77+
- assert(move _13, "index out of bounds: the length is {} but the index is {}", move _12, _11) -> [success: bb5, unwind continue];
78+
+ _13 = Lt(const 0_usize, _12);
79+
+ assert(move _13, "index out of bounds: the length is {} but the index is {}", move _12, const 0_usize) -> [success: bb5, unwind continue];
80+
}
81+
82+
bb5: {
83+
- _3 = (*_1)[_11];
84+
+ _3 = (*_1)[0 of 1];
85+
StorageDead(_11);
86+
goto -> bb6;
87+
}
88+
89+
bb6: {
90+
StorageDead(_4);
91+
StorageLive(_14);
92+
_14 = _3;
93+
_0 = opaque::<T>(move _14) -> [return: bb7, unwind continue];
94+
}
95+
96+
bb7: {
97+
StorageDead(_14);
98+
StorageDead(_3);
99+
- StorageDead(_2);
100+
+ nop;
101+
return;
102+
}
103+
}
104+

‎tests/mir-opt/gvn.rs‎

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -609,6 +609,22 @@ fn indirect_static() {
609609
})
610610
}
611611

612+
/// Verify that having constant index `u64::MAX` does not yield to an overflow in rustc.
613+
fn constant_index_overflow<T: Copy>(x: &[T]) {
614+
// CHECK-LABEL: fn constant_index_overflow(
615+
// CHECK: debug a => [[a:_.*]];
616+
// CHECK: debug b => [[b:_.*]];
617+
// CHECK: [[a]] = const usize::MAX;
618+
// CHECK-NOT: = (*_1)[{{.*}} of 0];
619+
// CHECK: [[b]] = (*_1)[[[a]]];
620+
// CHECK-NOT: = (*_1)[{{.*}} of 0];
621+
// CHECK: [[b]] = (*_1)[0 of 1];
622+
// CHECK-NOT: = (*_1)[{{.*}} of 0];
623+
let a = u64::MAX as usize;
624+
let b = if a < x.len() { x[a] } else { x[0] };
625+
opaque(b)
626+
}
627+
612628
fn main() {
613629
subexpression_elimination(2, 4, 5);
614630
wrap_unwrap(5);
@@ -627,6 +643,7 @@ fn main() {
627643
repeat();
628644
fn_pointers();
629645
indirect_static();
646+
constant_index_overflow(&[5, 3]);
630647
}
631648

632649
#[inline(never)]
@@ -653,3 +670,4 @@ fn identity<T>(x: T) -> T {
653670
// EMIT_MIR gvn.repeat.GVN.diff
654671
// EMIT_MIR gvn.fn_pointers.GVN.diff
655672
// EMIT_MIR gvn.indirect_static.GVN.diff
673+
// EMIT_MIR gvn.constant_index_overflow.GVN.diff

‎tests/ui/macros/issue-118786.rs‎

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
// compile-flags: --crate-type lib -O -C debug-assertions=yes
2+
3+
// Regression test for issue 118786
4+
5+
macro_rules! make_macro {
6+
($macro_name:tt) => {
7+
macro_rules! $macro_name {
8+
//~^ ERROR macros that expand to items must be delimited with braces or followed by a semicolon
9+
//~| ERROR macro expansion ignores token `{` and any following
10+
//~| ERROR cannot find macro `macro_rules` in this scope
11+
() => {}
12+
}
13+
}
14+
}
15+
16+
make_macro!((meow));
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
error: macros that expand to items must be delimited with braces or followed by a semicolon
2+
--> $DIR/issue-118786.rs:7:22
3+
|
4+
LL | macro_rules! $macro_name {
5+
| ^^^^^^^^^^^
6+
|
7+
help: change the delimiters to curly braces
8+
|
9+
LL | macro_rules! {} {
10+
| ~ +
11+
help: add a semicolon
12+
|
13+
LL | macro_rules! $macro_name; {
14+
| +
15+
16+
error: macro expansion ignores token `{` and any following
17+
--> $DIR/issue-118786.rs:7:34
18+
|
19+
LL | macro_rules! $macro_name {
20+
| ^
21+
...
22+
LL | make_macro!((meow));
23+
| ------------------- caused by the macro expansion here
24+
|
25+
= note: the usage of `make_macro!` is likely invalid in item context
26+
27+
error: cannot find macro `macro_rules` in this scope
28+
--> $DIR/issue-118786.rs:7:9
29+
|
30+
LL | macro_rules! $macro_name {
31+
| ^^^^^^^^^^^
32+
...
33+
LL | make_macro!((meow));
34+
| ------------------- in this macro invocation
35+
|
36+
note: maybe you have forgotten to define a name for this `macro_rules!`
37+
--> $DIR/issue-118786.rs:7:9
38+
|
39+
LL | macro_rules! $macro_name {
40+
| ^^^^^^^^^^^
41+
...
42+
LL | make_macro!((meow));
43+
| ------------------- in this macro invocation
44+
= note: this error originates in the macro `make_macro` (in Nightly builds, run with -Z macro-backtrace for more info)
45+
46+
error: aborting due to 3 previous errors
47+
Lines changed: 164 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,164 @@
1+
#![feature(inline_const)]
2+
#![feature(yeet_expr)]
3+
#![allow(incomplete_features)] // Necessary for now, while explicit_tail_calls is incomplete
4+
#![feature(explicit_tail_calls)]
5+
6+
fn a() {
7+
let foo = {
8+
1
9+
} else {
10+
//~^ ERROR right curly brace `}` before `else` in a `let...else` statement not allowed
11+
return;
12+
};
13+
}
14+
15+
fn b() {
16+
let foo = for i in 1..2 {
17+
break;
18+
} else {
19+
//~^ ERROR `for...else` loops are not supported
20+
return;
21+
};
22+
}
23+
24+
fn c() {
25+
let foo = if true {
26+
1
27+
} else {
28+
0
29+
} else {
30+
//~^ ERROR right curly brace `}` before `else` in a `let...else` statement not allowed
31+
return;
32+
};
33+
}
34+
35+
fn d() {
36+
let foo = loop {
37+
break;
38+
} else {
39+
//~^ ERROR loop...else` loops are not supported
40+
return;
41+
};
42+
}
43+
44+
fn e() {
45+
let foo = match true {
46+
true => 1,
47+
false => 0
48+
} else {
49+
//~^ ERROR right curly brace `}` before `else` in a `let...else` statement not allowed
50+
return;
51+
};
52+
}
53+
54+
struct X {a: i32}
55+
fn f() {
56+
let foo = X {
57+
a: 1
58+
} else {
59+
//~^ ERROR right curly brace `}` before `else` in a `let...else` statement not allowed
60+
return;
61+
};
62+
}
63+
64+
fn g() {
65+
let foo = while false {
66+
break;
67+
} else {
68+
//~^ ERROR `while...else` loops are not supported
69+
return;
70+
};
71+
}
72+
73+
fn h() {
74+
let foo = const {
75+
1
76+
} else {
77+
//~^ ERROR right curly brace `}` before `else` in a `let...else` statement not allowed
78+
return;
79+
};
80+
}
81+
82+
fn i() {
83+
let foo = &{
84+
1
85+
} else {
86+
//~^ ERROR right curly brace `}` before `else` in a `let...else` statement not allowed
87+
return;
88+
};
89+
}
90+
91+
fn j() {
92+
let bar = 0;
93+
let foo = bar = {
94+
1
95+
} else {
96+
//~^ ERROR right curly brace `}` before `else` in a `let...else` statement not allowed
97+
return;
98+
};
99+
}
100+
101+
fn k() {
102+
let foo = 1 + {
103+
1
104+
} else {
105+
//~^ ERROR right curly brace `}` before `else` in a `let...else` statement not allowed
106+
return;
107+
};
108+
}
109+
110+
fn l() {
111+
let foo = 1..{
112+
1
113+
} else {
114+
//~^ ERROR right curly brace `}` before `else` in a `let...else` statement not allowed
115+
return;
116+
};
117+
}
118+
119+
fn m() {
120+
let foo = return {
121+
()
122+
} else {
123+
//~^ ERROR right curly brace `}` before `else` in a `let...else` statement not allowed
124+
return;
125+
};
126+
}
127+
128+
fn n() {
129+
let foo = -{
130+
1
131+
} else {
132+
//~^ ERROR right curly brace `}` before `else` in a `let...else` statement not allowed
133+
return;
134+
};
135+
}
136+
137+
fn o() -> Result<(), ()> {
138+
let foo = do yeet {
139+
()
140+
} else {
141+
//~^ ERROR right curly brace `}` before `else` in a `let...else` statement not allowed
142+
return Ok(());
143+
};
144+
}
145+
146+
fn p() {
147+
let foo = become {
148+
()
149+
} else {
150+
//~^ ERROR right curly brace `}` before `else` in a `let...else` statement not allowed
151+
return;
152+
};
153+
}
154+
155+
fn q() {
156+
let foo = |x: i32| {
157+
x
158+
} else {
159+
//~^ ERROR right curly brace `}` before `else` in a `let...else` statement not allowed
160+
return;
161+
};
162+
}
163+
164+
fn main() {}
Lines changed: 232 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,232 @@
1+
error: right curly brace `}` before `else` in a `let...else` statement not allowed
2+
--> $DIR/bad-let-else-statement.rs:9:5
3+
|
4+
LL | } else {
5+
| ^
6+
|
7+
help: wrap the expression in parentheses
8+
|
9+
LL ~ let foo = ({
10+
LL | 1
11+
LL ~ }) else {
12+
|
13+
14+
error: `for...else` loops are not supported
15+
--> $DIR/bad-let-else-statement.rs:18:7
16+
|
17+
LL | let foo = for i in 1..2 {
18+
| --- `else` is attached to this loop
19+
LL | break;
20+
LL | } else {
21+
| _______^
22+
LL | |
23+
LL | | return;
24+
LL | | };
25+
| |_____^
26+
|
27+
= note: consider moving this `else` clause to a separate `if` statement and use a `bool` variable to control if it should run
28+
29+
error: right curly brace `}` before `else` in a `let...else` statement not allowed
30+
--> $DIR/bad-let-else-statement.rs:29:5
31+
|
32+
LL | } else {
33+
| ^
34+
|
35+
help: wrap the expression in parentheses
36+
|
37+
LL ~ let foo = (if true {
38+
LL | 1
39+
LL | } else {
40+
LL | 0
41+
LL ~ }) else {
42+
|
43+
44+
error: `loop...else` loops are not supported
45+
--> $DIR/bad-let-else-statement.rs:38:7
46+
|
47+
LL | let foo = loop {
48+
| ---- `else` is attached to this loop
49+
LL | break;
50+
LL | } else {
51+
| _______^
52+
LL | |
53+
LL | | return;
54+
LL | | };
55+
| |_____^
56+
|
57+
= note: consider moving this `else` clause to a separate `if` statement and use a `bool` variable to control if it should run
58+
59+
error: right curly brace `}` before `else` in a `let...else` statement not allowed
60+
--> $DIR/bad-let-else-statement.rs:48:5
61+
|
62+
LL | } else {
63+
| ^
64+
|
65+
help: wrap the expression in parentheses
66+
|
67+
LL ~ let foo = (match true {
68+
LL | true => 1,
69+
LL | false => 0
70+
LL ~ }) else {
71+
|
72+
73+
error: right curly brace `}` before `else` in a `let...else` statement not allowed
74+
--> $DIR/bad-let-else-statement.rs:58:5
75+
|
76+
LL | } else {
77+
| ^
78+
|
79+
help: wrap the expression in parentheses
80+
|
81+
LL ~ let foo = (X {
82+
LL | a: 1
83+
LL ~ }) else {
84+
|
85+
86+
error: `while...else` loops are not supported
87+
--> $DIR/bad-let-else-statement.rs:67:7
88+
|
89+
LL | let foo = while false {
90+
| ----- `else` is attached to this loop
91+
LL | break;
92+
LL | } else {
93+
| _______^
94+
LL | |
95+
LL | | return;
96+
LL | | };
97+
| |_____^
98+
|
99+
= note: consider moving this `else` clause to a separate `if` statement and use a `bool` variable to control if it should run
100+
101+
error: right curly brace `}` before `else` in a `let...else` statement not allowed
102+
--> $DIR/bad-let-else-statement.rs:76:5
103+
|
104+
LL | } else {
105+
| ^
106+
|
107+
help: wrap the expression in parentheses
108+
|
109+
LL ~ let foo = (const {
110+
LL | 1
111+
LL ~ }) else {
112+
|
113+
114+
error: right curly brace `}` before `else` in a `let...else` statement not allowed
115+
--> $DIR/bad-let-else-statement.rs:85:5
116+
|
117+
LL | } else {
118+
| ^
119+
|
120+
help: wrap the expression in parentheses
121+
|
122+
LL ~ let foo = &({
123+
LL | 1
124+
LL ~ }) else {
125+
|
126+
127+
error: right curly brace `}` before `else` in a `let...else` statement not allowed
128+
--> $DIR/bad-let-else-statement.rs:95:5
129+
|
130+
LL | } else {
131+
| ^
132+
|
133+
help: wrap the expression in parentheses
134+
|
135+
LL ~ let foo = bar = ({
136+
LL | 1
137+
LL ~ }) else {
138+
|
139+
140+
error: right curly brace `}` before `else` in a `let...else` statement not allowed
141+
--> $DIR/bad-let-else-statement.rs:104:5
142+
|
143+
LL | } else {
144+
| ^
145+
|
146+
help: wrap the expression in parentheses
147+
|
148+
LL ~ let foo = 1 + ({
149+
LL | 1
150+
LL ~ }) else {
151+
|
152+
153+
error: right curly brace `}` before `else` in a `let...else` statement not allowed
154+
--> $DIR/bad-let-else-statement.rs:113:5
155+
|
156+
LL | } else {
157+
| ^
158+
|
159+
help: wrap the expression in parentheses
160+
|
161+
LL ~ let foo = 1..({
162+
LL | 1
163+
LL ~ }) else {
164+
|
165+
166+
error: right curly brace `}` before `else` in a `let...else` statement not allowed
167+
--> $DIR/bad-let-else-statement.rs:122:5
168+
|
169+
LL | } else {
170+
| ^
171+
|
172+
help: wrap the expression in parentheses
173+
|
174+
LL ~ let foo = return ({
175+
LL | ()
176+
LL ~ }) else {
177+
|
178+
179+
error: right curly brace `}` before `else` in a `let...else` statement not allowed
180+
--> $DIR/bad-let-else-statement.rs:131:5
181+
|
182+
LL | } else {
183+
| ^
184+
|
185+
help: wrap the expression in parentheses
186+
|
187+
LL ~ let foo = -({
188+
LL | 1
189+
LL ~ }) else {
190+
|
191+
192+
error: right curly brace `}` before `else` in a `let...else` statement not allowed
193+
--> $DIR/bad-let-else-statement.rs:140:5
194+
|
195+
LL | } else {
196+
| ^
197+
|
198+
help: wrap the expression in parentheses
199+
|
200+
LL ~ let foo = do yeet ({
201+
LL | ()
202+
LL ~ }) else {
203+
|
204+
205+
error: right curly brace `}` before `else` in a `let...else` statement not allowed
206+
--> $DIR/bad-let-else-statement.rs:149:5
207+
|
208+
LL | } else {
209+
| ^
210+
|
211+
help: wrap the expression in parentheses
212+
|
213+
LL ~ let foo = become ({
214+
LL | ()
215+
LL ~ }) else {
216+
|
217+
218+
error: right curly brace `}` before `else` in a `let...else` statement not allowed
219+
--> $DIR/bad-let-else-statement.rs:158:5
220+
|
221+
LL | } else {
222+
| ^
223+
|
224+
help: wrap the expression in parentheses
225+
|
226+
LL ~ let foo = |x: i32| ({
227+
LL | x
228+
LL ~ }) else {
229+
|
230+
231+
error: aborting due to 17 previous errors
232+

0 commit comments

Comments
 (0)
Please sign in to comment.