ExprUseVisitor: remove maybe_read_scrutinee
The split between walk_pat and maybe_read_scrutinee has now become redundant. Due to this change, one testcase within the testsuite has become similar enough to a known ICE to also break. I am leaving this as future work, as it requires feature(type_alias_impl_trait)
This commit is contained in:
parent
9cb47c6e8e
commit
e25803acea
11 changed files with 152 additions and 262 deletions
|
|
@ -7,9 +7,7 @@
|
|||
|
||||
use std::cell::{Ref, RefCell};
|
||||
use std::ops::Deref;
|
||||
use std::slice::from_ref;
|
||||
|
||||
use hir::Expr;
|
||||
use hir::def::DefKind;
|
||||
use hir::pat_util::EnumerateAndAdjustIterator as _;
|
||||
use rustc_abi::{FIRST_VARIANT, FieldIdx, VariantIdx};
|
||||
|
|
@ -313,7 +311,8 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx
|
|||
|
||||
let param_place = self.cat_rvalue(param.hir_id, param_ty);
|
||||
|
||||
self.walk_irrefutable_pat(¶m_place, param.pat)?;
|
||||
self.fake_read_scrutinee(¶m_place, false)?;
|
||||
self.walk_pat(¶m_place, param.pat, false)?;
|
||||
}
|
||||
|
||||
self.consume_expr(body.value)?;
|
||||
|
|
@ -455,13 +454,9 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx
|
|||
|
||||
hir::ExprKind::Match(discr, arms, _) => {
|
||||
let discr_place = self.cat_expr(discr)?;
|
||||
self.maybe_read_scrutinee(
|
||||
discr,
|
||||
discr_place.clone(),
|
||||
arms.iter().map(|arm| arm.pat),
|
||||
)?;
|
||||
self.fake_read_scrutinee(&discr_place, true)?;
|
||||
self.walk_expr(discr)?;
|
||||
|
||||
// treatment of the discriminant is handled while walking the arms.
|
||||
for arm in arms {
|
||||
self.walk_arm(&discr_place, arm)?;
|
||||
}
|
||||
|
|
@ -598,116 +593,25 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx
|
|||
Ok(())
|
||||
}
|
||||
|
||||
fn maybe_read_scrutinee<'t>(
|
||||
#[instrument(skip(self), level = "debug")]
|
||||
fn fake_read_scrutinee(
|
||||
&self,
|
||||
discr: &Expr<'_>,
|
||||
discr_place: PlaceWithHirId<'tcx>,
|
||||
pats: impl Iterator<Item = &'t hir::Pat<'t>>,
|
||||
discr_place: &PlaceWithHirId<'tcx>,
|
||||
refutable: bool,
|
||||
) -> Result<(), Cx::Error> {
|
||||
// Matching should not always be considered a use of the place, hence
|
||||
// discr does not necessarily need to be borrowed.
|
||||
// We only want to borrow discr if the pattern contain something other
|
||||
// than wildcards.
|
||||
let mut needs_to_be_read = false;
|
||||
for pat in pats {
|
||||
self.cat_pattern(discr_place.clone(), pat, &mut |place, pat| {
|
||||
match &pat.kind {
|
||||
PatKind::Missing => unreachable!(),
|
||||
PatKind::Binding(.., opt_sub_pat) => {
|
||||
// If the opt_sub_pat is None, then the binding does not count as
|
||||
// a wildcard for the purpose of borrowing discr.
|
||||
if opt_sub_pat.is_none() {
|
||||
needs_to_be_read = true;
|
||||
}
|
||||
}
|
||||
PatKind::Never => {
|
||||
// A never pattern reads the value.
|
||||
// FIXME(never_patterns): does this do what I expect?
|
||||
needs_to_be_read = true;
|
||||
}
|
||||
PatKind::Expr(PatExpr { kind: PatExprKind::Path(qpath), hir_id, span }) => {
|
||||
// A `Path` pattern is just a name like `Foo`. This is either a
|
||||
// named constant or else it refers to an ADT variant
|
||||
let closure_def_id = match discr_place.place.base {
|
||||
PlaceBase::Upvar(upvar_id) => Some(upvar_id.closure_expr_id),
|
||||
_ => None,
|
||||
};
|
||||
|
||||
let res = self.cx.typeck_results().qpath_res(qpath, *hir_id);
|
||||
match res {
|
||||
Res::Def(DefKind::Const, _) | Res::Def(DefKind::AssocConst, _) => {
|
||||
// Named constants have to be equated with the value
|
||||
// being matched, so that's a read of the value being matched.
|
||||
//
|
||||
// FIXME: We don't actually reads for ZSTs.
|
||||
needs_to_be_read = true;
|
||||
}
|
||||
_ => {
|
||||
// Otherwise, this is a struct/enum variant, and so it's
|
||||
// only a read if we need to read the discriminant.
|
||||
needs_to_be_read |=
|
||||
self.is_multivariant_adt(place.place.ty(), *span);
|
||||
}
|
||||
}
|
||||
}
|
||||
PatKind::TupleStruct(..) | PatKind::Struct(..) | PatKind::Tuple(..) => {
|
||||
// For `Foo(..)`, `Foo { ... }` and `(...)` patterns, check if we are matching
|
||||
// against a multivariant enum or struct. In that case, we have to read
|
||||
// the discriminant. Otherwise this kind of pattern doesn't actually
|
||||
// read anything (we'll get invoked for the `...`, which may indeed
|
||||
// perform some reads).
|
||||
|
||||
let place_ty = place.place.ty();
|
||||
needs_to_be_read |= self.is_multivariant_adt(place_ty, pat.span);
|
||||
}
|
||||
PatKind::Expr(_) | PatKind::Range(..) => {
|
||||
// If the PatKind is a Lit or a Range then we want
|
||||
// to borrow discr.
|
||||
needs_to_be_read = true;
|
||||
}
|
||||
PatKind::Slice(lhs, wild, rhs) => {
|
||||
// We don't need to test the length if the pattern is `[..]`
|
||||
if matches!((lhs, wild, rhs), (&[], Some(_), &[]))
|
||||
// Arrays have a statically known size, so
|
||||
// there is no need to read their length
|
||||
|| place.place.ty().peel_refs().is_array()
|
||||
{
|
||||
} else {
|
||||
needs_to_be_read = true;
|
||||
}
|
||||
}
|
||||
PatKind::Or(_)
|
||||
| PatKind::Box(_)
|
||||
| PatKind::Deref(_)
|
||||
| PatKind::Ref(..)
|
||||
| PatKind::Guard(..)
|
||||
| PatKind::Wild
|
||||
| PatKind::Err(_) => {
|
||||
// If the PatKind is Or, Box, or Ref, the decision is made later
|
||||
// as these patterns contains subpatterns
|
||||
// If the PatKind is Wild or Err, the decision is made based on the other patterns
|
||||
// being examined
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
})?
|
||||
}
|
||||
|
||||
if needs_to_be_read {
|
||||
self.borrow_expr(discr, BorrowKind::Immutable)?;
|
||||
let cause = if refutable {
|
||||
FakeReadCause::ForMatchedPlace(closure_def_id)
|
||||
} else {
|
||||
let closure_def_id = match discr_place.place.base {
|
||||
PlaceBase::Upvar(upvar_id) => Some(upvar_id.closure_expr_id),
|
||||
_ => None,
|
||||
};
|
||||
FakeReadCause::ForLet(closure_def_id)
|
||||
};
|
||||
|
||||
self.delegate.borrow_mut().fake_read(
|
||||
&discr_place,
|
||||
FakeReadCause::ForMatchedPlace(closure_def_id),
|
||||
discr_place.hir_id,
|
||||
);
|
||||
self.delegate.borrow_mut().fake_read(discr_place, cause, discr_place.hir_id);
|
||||
|
||||
// We always want to walk the discriminant. We want to make sure, for instance,
|
||||
// that the discriminant has been initialized.
|
||||
self.walk_expr(discr)?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
|
@ -724,12 +628,11 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx
|
|||
self.walk_expr(expr)?;
|
||||
let expr_place = self.cat_expr(expr)?;
|
||||
f()?;
|
||||
self.fake_read_scrutinee(&expr_place, els.is_some())?;
|
||||
self.walk_pat(&expr_place, pat, false)?;
|
||||
if let Some(els) = els {
|
||||
// borrowing because we need to test the discriminant
|
||||
self.maybe_read_scrutinee(expr, expr_place.clone(), from_ref(pat).iter())?;
|
||||
self.walk_block(els)?;
|
||||
}
|
||||
self.walk_irrefutable_pat(&expr_place, pat)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
|
@ -901,16 +804,6 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx
|
|||
discr_place: &PlaceWithHirId<'tcx>,
|
||||
arm: &hir::Arm<'_>,
|
||||
) -> Result<(), Cx::Error> {
|
||||
let closure_def_id = match discr_place.place.base {
|
||||
PlaceBase::Upvar(upvar_id) => Some(upvar_id.closure_expr_id),
|
||||
_ => None,
|
||||
};
|
||||
|
||||
self.delegate.borrow_mut().fake_read(
|
||||
discr_place,
|
||||
FakeReadCause::ForMatchedPlace(closure_def_id),
|
||||
discr_place.hir_id,
|
||||
);
|
||||
self.walk_pat(discr_place, arm.pat, arm.guard.is_some())?;
|
||||
|
||||
if let Some(ref e) = arm.guard {
|
||||
|
|
@ -921,27 +814,6 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx
|
|||
Ok(())
|
||||
}
|
||||
|
||||
/// Walks a pat that occurs in isolation (i.e., top-level of fn argument or
|
||||
/// let binding, and *not* a match arm or nested pat.)
|
||||
fn walk_irrefutable_pat(
|
||||
&self,
|
||||
discr_place: &PlaceWithHirId<'tcx>,
|
||||
pat: &hir::Pat<'_>,
|
||||
) -> Result<(), Cx::Error> {
|
||||
let closure_def_id = match discr_place.place.base {
|
||||
PlaceBase::Upvar(upvar_id) => Some(upvar_id.closure_expr_id),
|
||||
_ => None,
|
||||
};
|
||||
|
||||
self.delegate.borrow_mut().fake_read(
|
||||
discr_place,
|
||||
FakeReadCause::ForLet(closure_def_id),
|
||||
discr_place.hir_id,
|
||||
);
|
||||
self.walk_pat(discr_place, pat, false)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// The core driver for walking a pattern
|
||||
///
|
||||
/// This should mirror how pattern-matching gets lowered to MIR, as
|
||||
|
|
@ -1984,6 +1856,7 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx
|
|||
/// Here, we cannot perform such an accurate checks, because querying
|
||||
/// whether a type is inhabited requires that it has been fully inferred,
|
||||
/// which cannot be guaranteed at this point.
|
||||
#[instrument(skip(self, span), level = "debug")]
|
||||
fn is_multivariant_adt(&self, ty: Ty<'tcx>, span: Span) -> bool {
|
||||
if let ty::Adt(def, _) = self.cx.structurally_resolve_type(span, ty).kind() {
|
||||
// Note that if a non-exhaustive SingleVariant is defined in another crate, we need
|
||||
|
|
|
|||
15
tests/crashes/119786-2.rs
Normal file
15
tests/crashes/119786-2.rs
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
//@ known-bug: #119786
|
||||
//@ edition:2021
|
||||
|
||||
fn enum_upvar() {
|
||||
type T = impl Copy;
|
||||
let foo: T = Some((1u32, 2u32));
|
||||
let x = move || {
|
||||
match foo {
|
||||
None => (),
|
||||
Some(_) => (),
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
pub fn main() {}
|
||||
15
tests/crashes/119786-3.rs
Normal file
15
tests/crashes/119786-3.rs
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
//@ known-bug: #119786
|
||||
//@ edition:2021
|
||||
|
||||
fn enum_upvar() {
|
||||
type T = impl Copy;
|
||||
let foo: T = Some((1u32, 2u32));
|
||||
let x = move || {
|
||||
match foo {
|
||||
None => (),
|
||||
Some((a, b)) => (),
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
pub fn main() {}
|
||||
|
|
@ -4,18 +4,16 @@ fn foo::{closure#0}::{closure#0}(_1: {async closure body@$DIR/async_closure_fake
|
|||
yields ()
|
||||
{
|
||||
debug _task_context => _2;
|
||||
debug f => (*(_1.0: &&Foo));
|
||||
debug f => (*(_1.0: &Foo));
|
||||
let mut _0: ();
|
||||
let mut _3: &Foo;
|
||||
let mut _4: &&Foo;
|
||||
let mut _5: &&&Foo;
|
||||
let mut _6: isize;
|
||||
let mut _7: bool;
|
||||
let mut _5: isize;
|
||||
let mut _6: bool;
|
||||
|
||||
bb0: {
|
||||
PlaceMention((*(_1.0: &&Foo)));
|
||||
_6 = discriminant((*(*(_1.0: &&Foo))));
|
||||
switchInt(move _6) -> [0: bb2, otherwise: bb1];
|
||||
_5 = discriminant((*(_1.0: &Foo)));
|
||||
switchInt(move _5) -> [0: bb2, otherwise: bb1];
|
||||
}
|
||||
|
||||
bb1: {
|
||||
|
|
@ -32,17 +30,15 @@ yields ()
|
|||
}
|
||||
|
||||
bb4: {
|
||||
FakeRead(ForMatchedPlace(None), (*(_1.0: &&Foo)));
|
||||
unreachable;
|
||||
}
|
||||
|
||||
bb5: {
|
||||
_3 = &fake shallow (*(*(_1.0: &&Foo)));
|
||||
_4 = &fake shallow (*(_1.0: &&Foo));
|
||||
_5 = &fake shallow (_1.0: &&Foo);
|
||||
StorageLive(_7);
|
||||
_7 = const true;
|
||||
switchInt(move _7) -> [0: bb8, otherwise: bb7];
|
||||
_3 = &fake shallow (*(_1.0: &Foo));
|
||||
_4 = &fake shallow (_1.0: &Foo);
|
||||
StorageLive(_6);
|
||||
_6 = const true;
|
||||
switchInt(move _6) -> [0: bb8, otherwise: bb7];
|
||||
}
|
||||
|
||||
bb6: {
|
||||
|
|
@ -50,10 +46,9 @@ yields ()
|
|||
}
|
||||
|
||||
bb7: {
|
||||
StorageDead(_7);
|
||||
StorageDead(_6);
|
||||
FakeRead(ForMatchGuard, _3);
|
||||
FakeRead(ForMatchGuard, _4);
|
||||
FakeRead(ForMatchGuard, _5);
|
||||
_0 = const ();
|
||||
goto -> bb10;
|
||||
}
|
||||
|
|
@ -63,7 +58,7 @@ yields ()
|
|||
}
|
||||
|
||||
bb9: {
|
||||
StorageDead(_7);
|
||||
StorageDead(_6);
|
||||
goto -> bb6;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -4,18 +4,16 @@ fn foo::{closure#0}::{synthetic#0}(_1: {async closure body@$DIR/async_closure_fa
|
|||
yields ()
|
||||
{
|
||||
debug _task_context => _2;
|
||||
debug f => (_1.0: &Foo);
|
||||
debug f => (*(_1.0: &Foo));
|
||||
let mut _0: ();
|
||||
let mut _3: &Foo;
|
||||
let mut _4: &&Foo;
|
||||
let mut _5: &&&Foo;
|
||||
let mut _6: isize;
|
||||
let mut _7: bool;
|
||||
let mut _5: isize;
|
||||
let mut _6: bool;
|
||||
|
||||
bb0: {
|
||||
PlaceMention((_1.0: &Foo));
|
||||
_6 = discriminant((*(_1.0: &Foo)));
|
||||
switchInt(move _6) -> [0: bb2, otherwise: bb1];
|
||||
_5 = discriminant((*(_1.0: &Foo)));
|
||||
switchInt(move _5) -> [0: bb2, otherwise: bb1];
|
||||
}
|
||||
|
||||
bb1: {
|
||||
|
|
@ -29,24 +27,22 @@ yields ()
|
|||
|
||||
bb3: {
|
||||
_3 = &fake shallow (*(_1.0: &Foo));
|
||||
_4 = &fake shallow (_1.0: &Foo);
|
||||
nop;
|
||||
StorageLive(_7);
|
||||
_7 = const true;
|
||||
switchInt(move _7) -> [0: bb5, otherwise: bb4];
|
||||
StorageLive(_6);
|
||||
_6 = const true;
|
||||
switchInt(move _6) -> [0: bb5, otherwise: bb4];
|
||||
}
|
||||
|
||||
bb4: {
|
||||
StorageDead(_7);
|
||||
StorageDead(_6);
|
||||
FakeRead(ForMatchGuard, _3);
|
||||
FakeRead(ForMatchGuard, _4);
|
||||
FakeRead(ForMatchGuard, _5);
|
||||
_0 = const ();
|
||||
goto -> bb6;
|
||||
}
|
||||
|
||||
bb5: {
|
||||
StorageDead(_7);
|
||||
StorageDead(_6);
|
||||
falseEdge -> [real: bb1, imaginary: bb1];
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ error[E0505]: cannot move out of `ts` because it is borrowed
|
|||
LL | let _b = || { match ts {
|
||||
| -- -- borrow occurs due to use in closure
|
||||
| |
|
||||
| borrow of `ts` occurs here
|
||||
| borrow of `ts.x` occurs here
|
||||
...
|
||||
LL | let mut mut_ts = ts;
|
||||
| ^^ move out of `ts` occurs here
|
||||
|
|
|
|||
|
|
@ -14,7 +14,6 @@ fn test_1_should_capture() {
|
|||
//~| ERROR Min Capture analysis includes:
|
||||
match variant {
|
||||
//~^ NOTE: Capturing variant[] -> Immutable
|
||||
//~| NOTE: Capturing variant[] -> Immutable
|
||||
//~| NOTE: Min Capture variant[] -> Immutable
|
||||
Some(_) => {}
|
||||
_ => {}
|
||||
|
|
@ -65,9 +64,8 @@ fn test_6_should_capture_single_variant() {
|
|||
//~^ ERROR First Pass analysis includes:
|
||||
//~| ERROR Min Capture analysis includes:
|
||||
match variant {
|
||||
//~^ NOTE: Capturing variant[] -> Immutable
|
||||
//~| NOTE: Capturing variant[(0, 0)] -> Immutable
|
||||
//~| NOTE: Min Capture variant[] -> Immutable
|
||||
//~^ NOTE: Capturing variant[(0, 0)] -> Immutable
|
||||
//~| NOTE: Min Capture variant[(0, 0)] -> Immutable
|
||||
SingleVariant::Points(a) => {
|
||||
println!("{:?}", a);
|
||||
}
|
||||
|
|
@ -133,7 +131,6 @@ fn test_5_should_capture_multi_variant() {
|
|||
//~| ERROR Min Capture analysis includes:
|
||||
match variant {
|
||||
//~^ NOTE: Capturing variant[] -> Immutable
|
||||
//~| NOTE: Capturing variant[] -> Immutable
|
||||
//~| NOTE: Min Capture variant[] -> Immutable
|
||||
MVariant::A => {}
|
||||
_ => {}
|
||||
|
|
@ -151,9 +148,8 @@ fn test_7_should_capture_slice_len() {
|
|||
//~^ ERROR First Pass analysis includes:
|
||||
//~| ERROR Min Capture analysis includes:
|
||||
match slice {
|
||||
//~^ NOTE: Capturing slice[] -> Immutable
|
||||
//~| NOTE: Capturing slice[Deref] -> Immutable
|
||||
//~| NOTE: Min Capture slice[] -> Immutable
|
||||
//~^ NOTE: Capturing slice[Deref] -> Immutable
|
||||
//~| NOTE: Min Capture slice[Deref] -> Immutable
|
||||
[_,_,_] => {},
|
||||
_ => {}
|
||||
}
|
||||
|
|
@ -164,9 +160,8 @@ fn test_7_should_capture_slice_len() {
|
|||
//~^ ERROR First Pass analysis includes:
|
||||
//~| ERROR Min Capture analysis includes:
|
||||
match slice {
|
||||
//~^ NOTE: Capturing slice[] -> Immutable
|
||||
//~| NOTE: Capturing slice[Deref] -> Immutable
|
||||
//~| NOTE: Min Capture slice[] -> Immutable
|
||||
//~^ NOTE: Capturing slice[Deref] -> Immutable
|
||||
//~| NOTE: Min Capture slice[Deref] -> Immutable
|
||||
[] => {},
|
||||
_ => {}
|
||||
}
|
||||
|
|
@ -177,9 +172,8 @@ fn test_7_should_capture_slice_len() {
|
|||
//~^ ERROR First Pass analysis includes:
|
||||
//~| ERROR Min Capture analysis includes:
|
||||
match slice {
|
||||
//~^ NOTE: Capturing slice[] -> Immutable
|
||||
//~| NOTE: Capturing slice[Deref] -> Immutable
|
||||
//~| NOTE: Min Capture slice[] -> Immutable
|
||||
//~^ NOTE: Capturing slice[Deref] -> Immutable
|
||||
//~| NOTE: Min Capture slice[Deref] -> Immutable
|
||||
[_, .. ,_] => {},
|
||||
_ => {}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -14,11 +14,6 @@ note: Capturing variant[] -> Immutable
|
|||
|
|
||||
LL | match variant {
|
||||
| ^^^^^^^
|
||||
note: Capturing variant[] -> Immutable
|
||||
--> $DIR/patterns-capture-analysis.rs:15:15
|
||||
|
|
||||
LL | match variant {
|
||||
| ^^^^^^^
|
||||
|
||||
error: Min Capture analysis includes:
|
||||
--> $DIR/patterns-capture-analysis.rs:12:5
|
||||
|
|
@ -38,7 +33,7 @@ LL | match variant {
|
|||
| ^^^^^^^
|
||||
|
||||
error: First Pass analysis includes:
|
||||
--> $DIR/patterns-capture-analysis.rs:31:5
|
||||
--> $DIR/patterns-capture-analysis.rs:30:5
|
||||
|
|
||||
LL | / || {
|
||||
LL | |
|
||||
|
|
@ -49,7 +44,7 @@ LL | | };
|
|||
| |_____^
|
||||
|
||||
error: First Pass analysis includes:
|
||||
--> $DIR/patterns-capture-analysis.rs:50:5
|
||||
--> $DIR/patterns-capture-analysis.rs:49:5
|
||||
|
|
||||
LL | / || {
|
||||
LL | |
|
||||
|
|
@ -60,7 +55,7 @@ LL | | };
|
|||
| |_____^
|
||||
|
||||
error: First Pass analysis includes:
|
||||
--> $DIR/patterns-capture-analysis.rs:64:5
|
||||
--> $DIR/patterns-capture-analysis.rs:63:5
|
||||
|
|
||||
LL | / || {
|
||||
LL | |
|
||||
|
|
@ -70,19 +65,14 @@ LL | | match variant {
|
|||
LL | | };
|
||||
| |_____^
|
||||
|
|
||||
note: Capturing variant[] -> Immutable
|
||||
--> $DIR/patterns-capture-analysis.rs:67:15
|
||||
|
|
||||
LL | match variant {
|
||||
| ^^^^^^^
|
||||
note: Capturing variant[(0, 0)] -> Immutable
|
||||
--> $DIR/patterns-capture-analysis.rs:67:15
|
||||
--> $DIR/patterns-capture-analysis.rs:66:15
|
||||
|
|
||||
LL | match variant {
|
||||
| ^^^^^^^
|
||||
|
||||
error: Min Capture analysis includes:
|
||||
--> $DIR/patterns-capture-analysis.rs:64:5
|
||||
--> $DIR/patterns-capture-analysis.rs:63:5
|
||||
|
|
||||
LL | / || {
|
||||
LL | |
|
||||
|
|
@ -92,14 +82,14 @@ LL | | match variant {
|
|||
LL | | };
|
||||
| |_____^
|
||||
|
|
||||
note: Min Capture variant[] -> Immutable
|
||||
--> $DIR/patterns-capture-analysis.rs:67:15
|
||||
note: Min Capture variant[(0, 0)] -> Immutable
|
||||
--> $DIR/patterns-capture-analysis.rs:66:15
|
||||
|
|
||||
LL | match variant {
|
||||
| ^^^^^^^
|
||||
|
||||
error: First Pass analysis includes:
|
||||
--> $DIR/patterns-capture-analysis.rs:84:5
|
||||
--> $DIR/patterns-capture-analysis.rs:82:5
|
||||
|
|
||||
LL | / || {
|
||||
LL | |
|
||||
|
|
@ -110,7 +100,7 @@ LL | | };
|
|||
| |_____^
|
||||
|
||||
error: First Pass analysis includes:
|
||||
--> $DIR/patterns-capture-analysis.rs:96:5
|
||||
--> $DIR/patterns-capture-analysis.rs:94:5
|
||||
|
|
||||
LL | / || {
|
||||
LL | |
|
||||
|
|
@ -121,7 +111,7 @@ LL | | };
|
|||
| |_____^
|
||||
|
||||
error: First Pass analysis includes:
|
||||
--> $DIR/patterns-capture-analysis.rs:109:5
|
||||
--> $DIR/patterns-capture-analysis.rs:107:5
|
||||
|
|
||||
LL | / || {
|
||||
LL | |
|
||||
|
|
@ -132,7 +122,7 @@ LL | | };
|
|||
| |_____^
|
||||
|
||||
error: First Pass analysis includes:
|
||||
--> $DIR/patterns-capture-analysis.rs:131:5
|
||||
--> $DIR/patterns-capture-analysis.rs:129:5
|
||||
|
|
||||
LL | / || {
|
||||
LL | |
|
||||
|
|
@ -143,18 +133,13 @@ LL | | };
|
|||
| |_____^
|
||||
|
|
||||
note: Capturing variant[] -> Immutable
|
||||
--> $DIR/patterns-capture-analysis.rs:134:15
|
||||
|
|
||||
LL | match variant {
|
||||
| ^^^^^^^
|
||||
note: Capturing variant[] -> Immutable
|
||||
--> $DIR/patterns-capture-analysis.rs:134:15
|
||||
--> $DIR/patterns-capture-analysis.rs:132:15
|
||||
|
|
||||
LL | match variant {
|
||||
| ^^^^^^^
|
||||
|
||||
error: Min Capture analysis includes:
|
||||
--> $DIR/patterns-capture-analysis.rs:131:5
|
||||
--> $DIR/patterns-capture-analysis.rs:129:5
|
||||
|
|
||||
LL | / || {
|
||||
LL | |
|
||||
|
|
@ -165,13 +150,13 @@ LL | | };
|
|||
| |_____^
|
||||
|
|
||||
note: Min Capture variant[] -> Immutable
|
||||
--> $DIR/patterns-capture-analysis.rs:134:15
|
||||
--> $DIR/patterns-capture-analysis.rs:132:15
|
||||
|
|
||||
LL | match variant {
|
||||
| ^^^^^^^
|
||||
|
||||
error: First Pass analysis includes:
|
||||
--> $DIR/patterns-capture-analysis.rs:150:5
|
||||
--> $DIR/patterns-capture-analysis.rs:147:5
|
||||
|
|
||||
LL | / || {
|
||||
LL | |
|
||||
|
|
@ -181,19 +166,14 @@ LL | | match slice {
|
|||
LL | | };
|
||||
| |_____^
|
||||
|
|
||||
note: Capturing slice[] -> Immutable
|
||||
--> $DIR/patterns-capture-analysis.rs:153:15
|
||||
|
|
||||
LL | match slice {
|
||||
| ^^^^^
|
||||
note: Capturing slice[Deref] -> Immutable
|
||||
--> $DIR/patterns-capture-analysis.rs:153:15
|
||||
--> $DIR/patterns-capture-analysis.rs:150:15
|
||||
|
|
||||
LL | match slice {
|
||||
| ^^^^^
|
||||
|
||||
error: Min Capture analysis includes:
|
||||
--> $DIR/patterns-capture-analysis.rs:150:5
|
||||
--> $DIR/patterns-capture-analysis.rs:147:5
|
||||
|
|
||||
LL | / || {
|
||||
LL | |
|
||||
|
|
@ -203,14 +183,14 @@ LL | | match slice {
|
|||
LL | | };
|
||||
| |_____^
|
||||
|
|
||||
note: Min Capture slice[] -> Immutable
|
||||
--> $DIR/patterns-capture-analysis.rs:153:15
|
||||
note: Min Capture slice[Deref] -> Immutable
|
||||
--> $DIR/patterns-capture-analysis.rs:150:15
|
||||
|
|
||||
LL | match slice {
|
||||
| ^^^^^
|
||||
|
||||
error: First Pass analysis includes:
|
||||
--> $DIR/patterns-capture-analysis.rs:163:5
|
||||
--> $DIR/patterns-capture-analysis.rs:159:5
|
||||
|
|
||||
LL | / || {
|
||||
LL | |
|
||||
|
|
@ -220,19 +200,14 @@ LL | | match slice {
|
|||
LL | | };
|
||||
| |_____^
|
||||
|
|
||||
note: Capturing slice[] -> Immutable
|
||||
--> $DIR/patterns-capture-analysis.rs:166:15
|
||||
|
|
||||
LL | match slice {
|
||||
| ^^^^^
|
||||
note: Capturing slice[Deref] -> Immutable
|
||||
--> $DIR/patterns-capture-analysis.rs:166:15
|
||||
--> $DIR/patterns-capture-analysis.rs:162:15
|
||||
|
|
||||
LL | match slice {
|
||||
| ^^^^^
|
||||
|
||||
error: Min Capture analysis includes:
|
||||
--> $DIR/patterns-capture-analysis.rs:163:5
|
||||
--> $DIR/patterns-capture-analysis.rs:159:5
|
||||
|
|
||||
LL | / || {
|
||||
LL | |
|
||||
|
|
@ -242,14 +217,14 @@ LL | | match slice {
|
|||
LL | | };
|
||||
| |_____^
|
||||
|
|
||||
note: Min Capture slice[] -> Immutable
|
||||
--> $DIR/patterns-capture-analysis.rs:166:15
|
||||
note: Min Capture slice[Deref] -> Immutable
|
||||
--> $DIR/patterns-capture-analysis.rs:162:15
|
||||
|
|
||||
LL | match slice {
|
||||
| ^^^^^
|
||||
|
||||
error: First Pass analysis includes:
|
||||
--> $DIR/patterns-capture-analysis.rs:176:5
|
||||
--> $DIR/patterns-capture-analysis.rs:171:5
|
||||
|
|
||||
LL | / || {
|
||||
LL | |
|
||||
|
|
@ -259,19 +234,14 @@ LL | | match slice {
|
|||
LL | | };
|
||||
| |_____^
|
||||
|
|
||||
note: Capturing slice[] -> Immutable
|
||||
--> $DIR/patterns-capture-analysis.rs:179:15
|
||||
|
|
||||
LL | match slice {
|
||||
| ^^^^^
|
||||
note: Capturing slice[Deref] -> Immutable
|
||||
--> $DIR/patterns-capture-analysis.rs:179:15
|
||||
--> $DIR/patterns-capture-analysis.rs:174:15
|
||||
|
|
||||
LL | match slice {
|
||||
| ^^^^^
|
||||
|
||||
error: Min Capture analysis includes:
|
||||
--> $DIR/patterns-capture-analysis.rs:176:5
|
||||
--> $DIR/patterns-capture-analysis.rs:171:5
|
||||
|
|
||||
LL | / || {
|
||||
LL | |
|
||||
|
|
@ -281,14 +251,14 @@ LL | | match slice {
|
|||
LL | | };
|
||||
| |_____^
|
||||
|
|
||||
note: Min Capture slice[] -> Immutable
|
||||
--> $DIR/patterns-capture-analysis.rs:179:15
|
||||
note: Min Capture slice[Deref] -> Immutable
|
||||
--> $DIR/patterns-capture-analysis.rs:174:15
|
||||
|
|
||||
LL | match slice {
|
||||
| ^^^^^
|
||||
|
||||
error: First Pass analysis includes:
|
||||
--> $DIR/patterns-capture-analysis.rs:194:5
|
||||
--> $DIR/patterns-capture-analysis.rs:188:5
|
||||
|
|
||||
LL | / || {
|
||||
LL | |
|
||||
|
|
|
|||
41
tests/ui/closures/at-pattern-weirdness-issue-137553.rs
Normal file
41
tests/ui/closures/at-pattern-weirdness-issue-137553.rs
Normal file
|
|
@ -0,0 +1,41 @@
|
|||
//@ edition:2024
|
||||
//@ check-pass
|
||||
|
||||
// Background:
|
||||
fn f1() {
|
||||
let mut a = (21, 37);
|
||||
// only captures a.0, example compiles fine
|
||||
let mut f = || {
|
||||
let (ref mut x, _) = a;
|
||||
*x = 42;
|
||||
};
|
||||
a.1 = 69;
|
||||
f();
|
||||
}
|
||||
|
||||
// This used to error out:
|
||||
fn f2() {
|
||||
let mut a = (21, 37);
|
||||
// used to capture all of a, now captures only a.0
|
||||
let mut f = || {
|
||||
match a {
|
||||
(ref mut x, _) => *x = 42,
|
||||
}
|
||||
};
|
||||
a.1 = 69;
|
||||
f();
|
||||
}
|
||||
|
||||
// This was inconsistent with the following:
|
||||
fn main() {
|
||||
let mut a = (21, 37);
|
||||
// the useless @-pattern would cause it to capture only a.0. now the
|
||||
// behavior is consistent with the case that doesn't use the @-pattern
|
||||
let mut f = || {
|
||||
match a {
|
||||
(ref mut x @ _, _) => *x = 42,
|
||||
}
|
||||
};
|
||||
a.1 = 69;
|
||||
f();
|
||||
}
|
||||
|
|
@ -23,15 +23,6 @@ fn upvar() {
|
|||
};
|
||||
}
|
||||
|
||||
fn enum_upvar() {
|
||||
type T = impl Copy;
|
||||
let foo: T = Some((1u32, 2u32));
|
||||
let x = move || match foo {
|
||||
None => (),
|
||||
Some((a, b)) => (),
|
||||
};
|
||||
}
|
||||
|
||||
fn r#struct() {
|
||||
#[derive(Copy, Clone)]
|
||||
struct Foo((u32, u32));
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue