Skip to content

Commit e85c871

Browse files
committed
emit an error when a match arm has a guard
1 parent 0788b2c commit e85c871

File tree

5 files changed

+53
-15
lines changed

5 files changed

+53
-15
lines changed

compiler/rustc_mir_build/messages.ftl

+4-1
Original file line numberDiff line numberDiff line change
@@ -217,11 +217,14 @@ mir_build_literal_in_range_out_of_bounds =
217217
literal out of range for `{$ty}`
218218
.label = this value does not fit into the type `{$ty}` whose range is `{$min}..={$max}`
219219
220+
mir_build_loop_match_arm_with_guard =
221+
match arms that are part of a `#[loop_match]` cannot have guards
222+
220223
mir_build_loop_match_bad_rhs =
221224
this expression must be a single `match` wrapped in a labeled block
222225
223226
mir_build_loop_match_bad_statements =
224-
statements are not allowed in this position within a `loop_match`
227+
statements are not allowed in this position within a `#[loop_match]`
225228
226229
mir_build_loop_match_invalid_match =
227230
invalid match on `loop_match` state

compiler/rustc_mir_build/src/builder/expr/into.rs

+13-9
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ use tracing::{debug, instrument};
1717
use crate::builder::expr::category::{Category, RvalueFunc};
1818
use crate::builder::matches::{DeclareLetBindings, HasMatchGuard};
1919
use crate::builder::{BlockAnd, BlockAndExtension, BlockFrame, Builder, NeedsTemporary};
20+
use crate::errors::LoopMatchArmWithGuard;
2021

2122
impl<'a, 'tcx> Builder<'a, 'tcx> {
2223
/// Compile `expr`, storing the result into `destination`, which
@@ -268,15 +269,18 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
268269
unpack!(body_block = this.as_place_builder(body_block, state));
269270
let scrutinee_span = this.thir.exprs[state].span;
270271
let match_start_span = scrutinee_span; // span.shrink_to_lo().to(scrutinee_span); FIXME
271-
let patterns = arms
272-
.iter()
273-
.map(|&arm_id| {
274-
// FIXME nice error for guards (which are not allowed)
275-
let arm = &this.thir[arm_id];
276-
assert!(arm.guard.is_none());
277-
(&*arm.pattern, HasMatchGuard::No)
278-
})
279-
.collect();
272+
273+
let mut patterns = Vec::with_capacity(arms.len());
274+
for &arm_id in arms.iter() {
275+
let arm = &this.thir[arm_id];
276+
277+
if let Some(guard) = arm.guard {
278+
let span = this.thir.exprs[guard].span;
279+
this.tcx.dcx().emit_fatal(LoopMatchArmWithGuard { span })
280+
}
281+
282+
patterns.push((&*arm.pattern, HasMatchGuard::No));
283+
}
280284

281285
let built_tree = this.lower_match_tree(
282286
body_block,

compiler/rustc_mir_build/src/errors.rs

+7
Original file line numberDiff line numberDiff line change
@@ -1200,6 +1200,13 @@ pub(crate) struct LoopMatchMissingAssignment {
12001200
pub span: Span,
12011201
}
12021202

1203+
#[derive(Diagnostic)]
1204+
#[diag(mir_build_loop_match_arm_with_guard)]
1205+
pub(crate) struct LoopMatchArmWithGuard {
1206+
#[primary_span]
1207+
pub span: Span,
1208+
}
1209+
12031210
#[derive(Diagnostic)]
12041211
#[diag(mir_build_const_continue_missing_value)]
12051212
pub(crate) struct ConstContinueMissingValue {

tests/ui/loop-match/invalid.rs

+20-2
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ fn bad_statements_1() {
4141
#[loop_match]
4242
loop {
4343
1;
44-
//~^ ERROR statements are not allowed in this position within a `loop_match`
44+
//~^ ERROR statements are not allowed in this position within a `#[loop_match]`
4545
state = 'blk: {
4646
match State::A {
4747
_ => State::B,
@@ -56,7 +56,7 @@ fn bad_statements_2() {
5656
loop {
5757
state = 'blk: {
5858
1;
59-
//~^ ERROR statements are not allowed in this position within a `loop_match`
59+
//~^ ERROR statements are not allowed in this position within a `#[loop_match]`
6060
match State::A {
6161
_ => State::B,
6262
}
@@ -142,3 +142,21 @@ fn break_without_value_unit() {
142142
}
143143
}
144144
}
145+
146+
fn arm_has_guard(cond: bool) {
147+
let state = State::A;
148+
#[loop_match]
149+
'a: loop {
150+
state = 'blk: {
151+
match state {
152+
State::A => {
153+
#[const_continue]
154+
break 'blk State::B;
155+
}
156+
State::B if cond => break 'a,
157+
//~^ ERROR match arms that are part of a `#[loop_match]` cannot have guards
158+
_ => break 'a,
159+
}
160+
}
161+
}
162+
}

tests/ui/loop-match/invalid.stderr

+9-3
Original file line numberDiff line numberDiff line change
@@ -26,13 +26,13 @@ LL | match State::A {
2626
|
2727
= note: only matches on local variables are valid
2828

29-
error: statements are not allowed in this position within a `loop_match`
29+
error: statements are not allowed in this position within a `#[loop_match]`
3030
--> $DIR/invalid.rs:43:9
3131
|
3232
LL | 1;
3333
| ^^
3434

35-
error: statements are not allowed in this position within a `loop_match`
35+
error: statements are not allowed in this position within a `#[loop_match]`
3636
--> $DIR/invalid.rs:58:13
3737
|
3838
LL | 1;
@@ -80,6 +80,12 @@ error: a `#[const_continue]` must break to a label with a value
8080
LL | break 'blk;
8181
| ^^^^^^^^^^
8282

83-
error: aborting due to 11 previous errors
83+
error: match arms that are part of a `#[loop_match]` cannot have guards
84+
--> $DIR/invalid.rs:156:29
85+
|
86+
LL | State::B if cond => break 'a,
87+
| ^^^^
88+
89+
error: aborting due to 12 previous errors
8490

8591
For more information about this error, try `rustc --explain E0308`.

0 commit comments

Comments
 (0)