Skip to content

Commit c1cbf9f

Browse files
authored
Unrolled build for #144451
Rollup merge of #144451 - ShoyuVanilla:loop-match-upvar, r=oli-obk fix: Reject upvar scrutinees for `loop_match` Fixes #144051 I think we should reject upvars as they are not locals but somewhat like field access
2 parents 5529041 + d87b4f2 commit c1cbf9f

File tree

3 files changed

+113
-7
lines changed

3 files changed

+113
-7
lines changed

compiler/rustc_mir_build/src/thir/cx/expr.rs

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -955,21 +955,25 @@ impl<'tcx> ThirBuildCx<'tcx> {
955955
dcx.emit_fatal(LoopMatchBadRhs { span: block_body_expr.span })
956956
};
957957

958-
fn local(expr: &rustc_hir::Expr<'_>) -> Option<hir::HirId> {
958+
fn local(
959+
cx: &mut ThirBuildCx<'_>,
960+
expr: &rustc_hir::Expr<'_>,
961+
) -> Option<hir::HirId> {
959962
if let hir::ExprKind::Path(hir::QPath::Resolved(_, path)) = expr.kind
960963
&& let Res::Local(hir_id) = path.res
964+
&& !cx.is_upvar(hir_id)
961965
{
962966
return Some(hir_id);
963967
}
964968

965969
None
966970
}
967971

968-
let Some(scrutinee_hir_id) = local(scrutinee) else {
972+
let Some(scrutinee_hir_id) = local(self, scrutinee) else {
969973
dcx.emit_fatal(LoopMatchInvalidMatch { span: scrutinee.span })
970974
};
971975

972-
if local(state) != Some(scrutinee_hir_id) {
976+
if local(self, state) != Some(scrutinee_hir_id) {
973977
dcx.emit_fatal(LoopMatchInvalidUpdate {
974978
scrutinee: scrutinee.span,
975979
lhs: state.span,
@@ -1260,10 +1264,7 @@ impl<'tcx> ThirBuildCx<'tcx> {
12601264
fn convert_var(&mut self, var_hir_id: hir::HirId) -> ExprKind<'tcx> {
12611265
// We want upvars here not captures.
12621266
// Captures will be handled in MIR.
1263-
let is_upvar = self
1264-
.tcx
1265-
.upvars_mentioned(self.body_owner)
1266-
.is_some_and(|upvars| upvars.contains_key(&var_hir_id));
1267+
let is_upvar = self.is_upvar(var_hir_id);
12671268

12681269
debug!(
12691270
"convert_var({:?}): is_upvar={}, body_owner={:?}",
@@ -1443,6 +1444,12 @@ impl<'tcx> ThirBuildCx<'tcx> {
14431444
}
14441445
}
14451446

1447+
fn is_upvar(&mut self, var_hir_id: hir::HirId) -> bool {
1448+
self.tcx
1449+
.upvars_mentioned(self.body_owner)
1450+
.is_some_and(|upvars| upvars.contains_key(&var_hir_id))
1451+
}
1452+
14461453
/// Converts a list of named fields (i.e., for struct-like struct/enum ADTs) into FieldExpr.
14471454
fn field_refs(&mut self, fields: &'tcx [hir::ExprField<'tcx>]) -> Box<[FieldExpr]> {
14481455
fields
Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
#![allow(incomplete_features)]
2+
#![feature(loop_match)]
3+
4+
#[derive(Clone, Copy)]
5+
enum State {
6+
A,
7+
B,
8+
}
9+
10+
fn main() {
11+
let mut state = State::A;
12+
13+
#[loop_match]
14+
loop {
15+
state = 'blk: {
16+
match state {
17+
State::A => {
18+
#[const_continue]
19+
break 'blk State::B;
20+
}
21+
State::B => {
22+
return;
23+
}
24+
}
25+
}
26+
}
27+
28+
|| {
29+
#[loop_match]
30+
loop {
31+
state = 'blk: {
32+
match state {
33+
//~^ ERROR invalid match on `#[loop_match]` state
34+
State::A => {
35+
#[const_continue]
36+
break 'blk State::B;
37+
}
38+
State::B => {
39+
return;
40+
}
41+
}
42+
}
43+
}
44+
};
45+
46+
|| {
47+
let mut state = state;
48+
#[loop_match]
49+
loop {
50+
state = 'blk: {
51+
match state {
52+
State::A => {
53+
#[const_continue]
54+
break 'blk State::B;
55+
}
56+
State::B => {
57+
return;
58+
}
59+
}
60+
}
61+
}
62+
};
63+
64+
move || {
65+
#[loop_match]
66+
loop {
67+
state = 'blk: {
68+
match state {
69+
//~^ ERROR invalid match on `#[loop_match]` state
70+
State::A => {
71+
#[const_continue]
72+
break 'blk State::B;
73+
}
74+
State::B => {
75+
return;
76+
}
77+
}
78+
}
79+
}
80+
};
81+
}
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
error: invalid match on `#[loop_match]` state
2+
--> $DIR/upvar-scrutinee.rs:32:23
3+
|
4+
LL | match state {
5+
| ^^^^^
6+
|
7+
= note: a local variable must be the scrutinee within a `#[loop_match]`
8+
9+
error: invalid match on `#[loop_match]` state
10+
--> $DIR/upvar-scrutinee.rs:68:23
11+
|
12+
LL | match state {
13+
| ^^^^^
14+
|
15+
= note: a local variable must be the scrutinee within a `#[loop_match]`
16+
17+
error: aborting due to 2 previous errors
18+

0 commit comments

Comments
 (0)