mirror of
https://github.com/rust-lang/rust.git
synced 2026-04-27 18:57:42 +03:00
fix: Reject upvar scrutinees for loop_match
This commit is contained in:
@@ -955,9 +955,13 @@ fn make_mirror_unadjusted(&mut self, expr: &'tcx hir::Expr<'tcx>) -> Expr<'tcx>
|
||||
dcx.emit_fatal(LoopMatchBadRhs { span: block_body_expr.span })
|
||||
};
|
||||
|
||||
fn local(expr: &rustc_hir::Expr<'_>) -> Option<hir::HirId> {
|
||||
fn local(
|
||||
cx: &mut ThirBuildCx<'_>,
|
||||
expr: &rustc_hir::Expr<'_>,
|
||||
) -> Option<hir::HirId> {
|
||||
if let hir::ExprKind::Path(hir::QPath::Resolved(_, path)) = expr.kind
|
||||
&& let Res::Local(hir_id) = path.res
|
||||
&& !cx.is_upvar(hir_id)
|
||||
{
|
||||
return Some(hir_id);
|
||||
}
|
||||
@@ -965,11 +969,11 @@ fn local(expr: &rustc_hir::Expr<'_>) -> Option<hir::HirId> {
|
||||
None
|
||||
}
|
||||
|
||||
let Some(scrutinee_hir_id) = local(scrutinee) else {
|
||||
let Some(scrutinee_hir_id) = local(self, scrutinee) else {
|
||||
dcx.emit_fatal(LoopMatchInvalidMatch { span: scrutinee.span })
|
||||
};
|
||||
|
||||
if local(state) != Some(scrutinee_hir_id) {
|
||||
if local(self, state) != Some(scrutinee_hir_id) {
|
||||
dcx.emit_fatal(LoopMatchInvalidUpdate {
|
||||
scrutinee: scrutinee.span,
|
||||
lhs: state.span,
|
||||
@@ -1260,10 +1264,7 @@ fn convert_path_expr(&mut self, expr: &'tcx hir::Expr<'tcx>, res: Res) -> ExprKi
|
||||
fn convert_var(&mut self, var_hir_id: hir::HirId) -> ExprKind<'tcx> {
|
||||
// We want upvars here not captures.
|
||||
// Captures will be handled in MIR.
|
||||
let is_upvar = self
|
||||
.tcx
|
||||
.upvars_mentioned(self.body_owner)
|
||||
.is_some_and(|upvars| upvars.contains_key(&var_hir_id));
|
||||
let is_upvar = self.is_upvar(var_hir_id);
|
||||
|
||||
debug!(
|
||||
"convert_var({:?}): is_upvar={}, body_owner={:?}",
|
||||
@@ -1443,6 +1444,12 @@ fn capture_upvar(
|
||||
}
|
||||
}
|
||||
|
||||
fn is_upvar(&mut self, var_hir_id: hir::HirId) -> bool {
|
||||
self.tcx
|
||||
.upvars_mentioned(self.body_owner)
|
||||
.is_some_and(|upvars| upvars.contains_key(&var_hir_id))
|
||||
}
|
||||
|
||||
/// Converts a list of named fields (i.e., for struct-like struct/enum ADTs) into FieldExpr.
|
||||
fn field_refs(&mut self, fields: &'tcx [hir::ExprField<'tcx>]) -> Box<[FieldExpr]> {
|
||||
fields
|
||||
|
||||
@@ -0,0 +1,81 @@
|
||||
#![allow(incomplete_features)]
|
||||
#![feature(loop_match)]
|
||||
|
||||
#[derive(Clone, Copy)]
|
||||
enum State {
|
||||
A,
|
||||
B,
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let mut state = State::A;
|
||||
|
||||
#[loop_match]
|
||||
loop {
|
||||
state = 'blk: {
|
||||
match state {
|
||||
State::A => {
|
||||
#[const_continue]
|
||||
break 'blk State::B;
|
||||
}
|
||||
State::B => {
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|| {
|
||||
#[loop_match]
|
||||
loop {
|
||||
state = 'blk: {
|
||||
match state {
|
||||
//~^ ERROR invalid match on `#[loop_match]` state
|
||||
State::A => {
|
||||
#[const_continue]
|
||||
break 'blk State::B;
|
||||
}
|
||||
State::B => {
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|| {
|
||||
let mut state = state;
|
||||
#[loop_match]
|
||||
loop {
|
||||
state = 'blk: {
|
||||
match state {
|
||||
State::A => {
|
||||
#[const_continue]
|
||||
break 'blk State::B;
|
||||
}
|
||||
State::B => {
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
move || {
|
||||
#[loop_match]
|
||||
loop {
|
||||
state = 'blk: {
|
||||
match state {
|
||||
//~^ ERROR invalid match on `#[loop_match]` state
|
||||
State::A => {
|
||||
#[const_continue]
|
||||
break 'blk State::B;
|
||||
}
|
||||
State::B => {
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
error: invalid match on `#[loop_match]` state
|
||||
--> $DIR/upvar-scrutinee.rs:32:23
|
||||
|
|
||||
LL | match state {
|
||||
| ^^^^^
|
||||
|
|
||||
= note: a local variable must be the scrutinee within a `#[loop_match]`
|
||||
|
||||
error: invalid match on `#[loop_match]` state
|
||||
--> $DIR/upvar-scrutinee.rs:68:23
|
||||
|
|
||||
LL | match state {
|
||||
| ^^^^^
|
||||
|
|
||||
= note: a local variable must be the scrutinee within a `#[loop_match]`
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
Reference in New Issue
Block a user