diff --git a/compiler/rustc_hir_typeck/src/expr_use_visitor.rs b/compiler/rustc_hir_typeck/src/expr_use_visitor.rs index 2e993cf7db95..b35f62df82b7 100644 --- a/compiler/rustc_hir_typeck/src/expr_use_visitor.rs +++ b/compiler/rustc_hir_typeck/src/expr_use_visitor.rs @@ -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>, + 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 diff --git a/tests/crashes/119786.rs b/tests/crashes/119786-1.rs similarity index 100% rename from tests/crashes/119786.rs rename to tests/crashes/119786-1.rs diff --git a/tests/crashes/119786-2.rs b/tests/crashes/119786-2.rs new file mode 100644 index 000000000000..76c5deb4605a --- /dev/null +++ b/tests/crashes/119786-2.rs @@ -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() {} diff --git a/tests/crashes/119786-3.rs b/tests/crashes/119786-3.rs new file mode 100644 index 000000000000..34bb90fd0fae --- /dev/null +++ b/tests/crashes/119786-3.rs @@ -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() {} diff --git a/tests/mir-opt/async_closure_fake_read_for_by_move.foo-{closure#0}-{closure#0}.built.after.mir b/tests/mir-opt/async_closure_fake_read_for_by_move.foo-{closure#0}-{closure#0}.built.after.mir index b43af549b232..9ff1a90ab820 100644 --- a/tests/mir-opt/async_closure_fake_read_for_by_move.foo-{closure#0}-{closure#0}.built.after.mir +++ b/tests/mir-opt/async_closure_fake_read_for_by_move.foo-{closure#0}-{closure#0}.built.after.mir @@ -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; } diff --git a/tests/mir-opt/async_closure_fake_read_for_by_move.foo-{closure#0}-{synthetic#0}.built.after.mir b/tests/mir-opt/async_closure_fake_read_for_by_move.foo-{closure#0}-{synthetic#0}.built.after.mir index 5623b6d64e97..4b745caf48c5 100644 --- a/tests/mir-opt/async_closure_fake_read_for_by_move.foo-{closure#0}-{synthetic#0}.built.after.mir +++ b/tests/mir-opt/async_closure_fake_read_for_by_move.foo-{closure#0}-{synthetic#0}.built.after.mir @@ -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]; } diff --git a/tests/ui/closures/2229_closure_analysis/match/match-edge-cases_2.stderr b/tests/ui/closures/2229_closure_analysis/match/match-edge-cases_2.stderr index d82db0481a06..3f5fe9eda423 100644 --- a/tests/ui/closures/2229_closure_analysis/match/match-edge-cases_2.stderr +++ b/tests/ui/closures/2229_closure_analysis/match/match-edge-cases_2.stderr @@ -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 diff --git a/tests/ui/closures/2229_closure_analysis/match/patterns-capture-analysis.rs b/tests/ui/closures/2229_closure_analysis/match/patterns-capture-analysis.rs index a9d2777d93f1..16cb9d7355da 100644 --- a/tests/ui/closures/2229_closure_analysis/match/patterns-capture-analysis.rs +++ b/tests/ui/closures/2229_closure_analysis/match/patterns-capture-analysis.rs @@ -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 [_, .. ,_] => {}, _ => {} } diff --git a/tests/ui/closures/2229_closure_analysis/match/patterns-capture-analysis.stderr b/tests/ui/closures/2229_closure_analysis/match/patterns-capture-analysis.stderr index 4b9d6fad0e50..73c685e15276 100644 --- a/tests/ui/closures/2229_closure_analysis/match/patterns-capture-analysis.stderr +++ b/tests/ui/closures/2229_closure_analysis/match/patterns-capture-analysis.stderr @@ -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 | | diff --git a/tests/ui/closures/at-pattern-weirdness-issue-137553.rs b/tests/ui/closures/at-pattern-weirdness-issue-137553.rs new file mode 100644 index 000000000000..7c934d4a1433 --- /dev/null +++ b/tests/ui/closures/at-pattern-weirdness-issue-137553.rs @@ -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(); +} diff --git a/tests/ui/type-alias-impl-trait/issue-96572-unconstrained.rs b/tests/ui/type-alias-impl-trait/issue-96572-unconstrained.rs index 7f0f6a214aae..383d9108eb90 100644 --- a/tests/ui/type-alias-impl-trait/issue-96572-unconstrained.rs +++ b/tests/ui/type-alias-impl-trait/issue-96572-unconstrained.rs @@ -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));