From 3d420e9d7aaa42f28a2f38dd1459e5949d539da4 Mon Sep 17 00:00:00 2001 From: Ding Xiang Fei Date: Tue, 24 Jan 2023 16:06:35 +0800 Subject: [PATCH] rescope temp lifetime in let-chain into IfElse --- compiler/rustc_feature/src/unstable.rs | 2 + .../rustc_hir_typeck/src/rvalue_scopes.rs | 3 +- compiler/rustc_middle/src/ty/rvalue_scopes.rs | 17 ++- compiler/rustc_span/src/symbol.rs | 1 + ...n_conditional.test_complex.built.after.mir | 34 +++-- .../discriminant.main.GVN.32bit.diff | 3 +- .../discriminant.main.GVN.64bit.diff | 3 +- .../while_let_loops.change_loop_body.GVN.diff | 3 +- ...to_exponential_common.GVN.panic-abort.diff | 3 +- ...o_exponential_common.GVN.panic-unwind.diff | 3 +- ...e_prop.debuginfo.ReferencePropagation.diff | 6 +- ....foo.SimplifyLocals-final.panic-abort.diff | 17 ++- ...foo.SimplifyLocals-final.panic-unwind.diff | 17 ++- ...s.enums.ScalarReplacementOfAggregates.diff | 3 +- ...et.UnreachablePropagation.panic-abort.diff | 2 +- ...t.UnreachablePropagation.panic-unwind.diff | 2 +- ...in.UnreachablePropagation.panic-abort.diff | 2 +- ...n.UnreachablePropagation.panic-unwind.diff | 2 +- tests/ui/drop/drop_order_if_let_rescope.rs | 122 ++++++++++++++++++ .../feature-gate-if-let-rescope.rs | 25 ++++ .../feature-gate-if-let-rescope.stderr | 18 +++ tests/ui/nll/issue-54556-niconii.rs | 4 +- tests/ui/nll/issue-54556-niconii.stderr | 26 ---- 23 files changed, 253 insertions(+), 65 deletions(-) create mode 100644 tests/ui/drop/drop_order_if_let_rescope.rs create mode 100644 tests/ui/feature-gates/feature-gate-if-let-rescope.rs create mode 100644 tests/ui/feature-gates/feature-gate-if-let-rescope.stderr delete mode 100644 tests/ui/nll/issue-54556-niconii.stderr diff --git a/compiler/rustc_feature/src/unstable.rs b/compiler/rustc_feature/src/unstable.rs index 9641d336c3f3c..db587c7108ca1 100644 --- a/compiler/rustc_feature/src/unstable.rs +++ b/compiler/rustc_feature/src/unstable.rs @@ -495,6 +495,8 @@ declare_features! ( (unstable, half_open_range_patterns_in_slices, "1.66.0", Some(67264)), /// Allows `if let` guard in match arms. (unstable, if_let_guard, "1.47.0", Some(51114)), + /// Rescoping temporaries in `if let` to align with Rust 2024. + (unstable, if_let_rescope, "1.78.0", Some(124085)), /// Allows `impl Trait` to be used inside associated types (RFC 2515). (unstable, impl_trait_in_assoc_type, "1.70.0", Some(63063)), /// Allows `impl Trait` as output type in `Fn` traits in return position of functions. diff --git a/compiler/rustc_hir_typeck/src/rvalue_scopes.rs b/compiler/rustc_hir_typeck/src/rvalue_scopes.rs index 34ce0ab1f8b98..9dccc1e8f74a4 100644 --- a/compiler/rustc_hir_typeck/src/rvalue_scopes.rs +++ b/compiler/rustc_hir_typeck/src/rvalue_scopes.rs @@ -69,7 +69,8 @@ pub fn resolve_rvalue_scopes<'a, 'tcx>( def_id: DefId, ) -> RvalueScopes { let tcx = &fcx.tcx; - let mut rvalue_scopes = RvalueScopes::new(); + let mut rvalue_scopes = + RvalueScopes::new(tcx.features().if_let_rescope && tcx.sess.at_least_rust_2024()); debug!("start resolving rvalue scopes, def_id={def_id:?}"); debug!("rvalue_scope: rvalue_candidates={:?}", scope_tree.rvalue_candidates); for (&hir_id, candidate) in &scope_tree.rvalue_candidates { diff --git a/compiler/rustc_middle/src/ty/rvalue_scopes.rs b/compiler/rustc_middle/src/ty/rvalue_scopes.rs index 17eabec257e93..9f8b96e4d3599 100644 --- a/compiler/rustc_middle/src/ty/rvalue_scopes.rs +++ b/compiler/rustc_middle/src/ty/rvalue_scopes.rs @@ -6,12 +6,13 @@ use rustc_hir::ItemLocalMap; /// rules laid out in `rustc_hir_analysis::check::rvalue_scopes`. #[derive(TyEncodable, TyDecodable, Clone, Debug, Default, Eq, PartialEq, HashStable)] pub struct RvalueScopes { + rescope_if_let: bool, map: ItemLocalMap>, } impl RvalueScopes { - pub fn new() -> Self { - Self { map: <_>::default() } + pub fn new(rescope_if_let: bool) -> Self { + Self { rescope_if_let, map: <_>::default() } } /// Returns the scope when the temp created by `expr_id` will be cleaned up. @@ -38,7 +39,17 @@ impl RvalueScopes { debug!("temporary_scope({expr_id:?}) = {id:?} [enclosing]"); return Some(id); } - _ => id = p, + ScopeData::IfThen => { + if self.rescope_if_let { + debug!("temporary_scope({expr_id:?}) = {p:?} [enclosing]"); + return Some(p); + } + id = p; + } + ScopeData::Node + | ScopeData::CallSite + | ScopeData::Arguments + | ScopeData::Remainder(_) => id = p, } } diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index 46bae1c1e9894..44ecd22635cbe 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -964,6 +964,7 @@ symbols! { ident, if_let, if_let_guard, + if_let_rescope, if_while_or_patterns, ignore, impl_header_lifetime_elision, diff --git a/tests/mir-opt/building/logical_or_in_conditional.test_complex.built.after.mir b/tests/mir-opt/building/logical_or_in_conditional.test_complex.built.after.mir index fd8eb370ca958..d81b3441f4f93 100644 --- a/tests/mir-opt/building/logical_or_in_conditional.test_complex.built.after.mir +++ b/tests/mir-opt/building/logical_or_in_conditional.test_complex.built.after.mir @@ -19,7 +19,7 @@ fn test_complex() -> () { bb0: { StorageLive(_1); StorageLive(_2); - _2 = E::f() -> [return: bb1, unwind: bb38]; + _2 = E::f() -> [return: bb1, unwind: bb39]; } bb1: { @@ -51,7 +51,7 @@ fn test_complex() -> () { bb7: { StorageLive(_4); - _4 = always_true() -> [return: bb8, unwind: bb38]; + _4 = always_true() -> [return: bb8, unwind: bb39]; } bb8: { @@ -73,7 +73,7 @@ fn test_complex() -> () { } bb11: { - drop(_7) -> [return: bb13, unwind: bb38]; + drop(_7) -> [return: bb13, unwind: bb39]; } bb12: { @@ -87,7 +87,7 @@ fn test_complex() -> () { } bb14: { - drop(_7) -> [return: bb15, unwind: bb38]; + drop(_7) -> [return: bb15, unwind: bb39]; } bb15: { @@ -107,7 +107,7 @@ fn test_complex() -> () { } bb17: { - drop(_10) -> [return: bb19, unwind: bb38]; + drop(_10) -> [return: bb19, unwind: bb39]; } bb18: { @@ -122,11 +122,12 @@ fn test_complex() -> () { bb20: { _1 = const (); + StorageDead(_2); goto -> bb24; } bb21: { - drop(_10) -> [return: bb22, unwind: bb38]; + drop(_10) -> [return: bb22, unwind: bb39]; } bb22: { @@ -136,6 +137,7 @@ fn test_complex() -> () { } bb23: { + StorageDead(_2); _1 = const (); goto -> bb24; } @@ -144,10 +146,9 @@ fn test_complex() -> () { StorageDead(_8); StorageDead(_5); StorageDead(_4); - StorageDead(_2); StorageDead(_1); StorageLive(_11); - _11 = always_true() -> [return: bb25, unwind: bb38]; + _11 = always_true() -> [return: bb25, unwind: bb39]; } bb25: { @@ -155,7 +156,7 @@ fn test_complex() -> () { } bb26: { - goto -> bb36; + goto -> bb37; } bb27: { @@ -164,7 +165,7 @@ fn test_complex() -> () { bb28: { StorageLive(_12); - _12 = E::f() -> [return: bb29, unwind: bb38]; + _12 = E::f() -> [return: bb29, unwind: bb39]; } bb29: { @@ -196,21 +197,26 @@ fn test_complex() -> () { bb35: { _0 = const (); - goto -> bb37; + StorageDead(_12); + goto -> bb38; } bb36: { - _0 = const (); + StorageDead(_12); goto -> bb37; } bb37: { + _0 = const (); + goto -> bb38; + } + + bb38: { StorageDead(_11); - StorageDead(_12); return; } - bb38 (cleanup): { + bb39 (cleanup): { resume; } } diff --git a/tests/mir-opt/const_prop/discriminant.main.GVN.32bit.diff b/tests/mir-opt/const_prop/discriminant.main.GVN.32bit.diff index 70c3c3fe7e495..77ca70a36d694 100644 --- a/tests/mir-opt/const_prop/discriminant.main.GVN.32bit.diff +++ b/tests/mir-opt/const_prop/discriminant.main.GVN.32bit.diff @@ -32,10 +32,12 @@ bb2: { _2 = const 42_i32; + StorageDead(_3); goto -> bb4; } bb3: { + StorageDead(_3); _2 = const 10_i32; goto -> bb4; } @@ -43,7 +45,6 @@ bb4: { _1 = Add(move _2, const 0_i32); StorageDead(_2); - StorageDead(_3); _0 = const (); StorageDead(_1); return; diff --git a/tests/mir-opt/const_prop/discriminant.main.GVN.64bit.diff b/tests/mir-opt/const_prop/discriminant.main.GVN.64bit.diff index 70c3c3fe7e495..77ca70a36d694 100644 --- a/tests/mir-opt/const_prop/discriminant.main.GVN.64bit.diff +++ b/tests/mir-opt/const_prop/discriminant.main.GVN.64bit.diff @@ -32,10 +32,12 @@ bb2: { _2 = const 42_i32; + StorageDead(_3); goto -> bb4; } bb3: { + StorageDead(_3); _2 = const 10_i32; goto -> bb4; } @@ -43,7 +45,6 @@ bb4: { _1 = Add(move _2, const 0_i32); StorageDead(_2); - StorageDead(_3); _0 = const (); StorageDead(_1); return; diff --git a/tests/mir-opt/const_prop/while_let_loops.change_loop_body.GVN.diff b/tests/mir-opt/const_prop/while_let_loops.change_loop_body.GVN.diff index 9548afc9d4027..1cff0d52d9906 100644 --- a/tests/mir-opt/const_prop/while_let_loops.change_loop_body.GVN.diff +++ b/tests/mir-opt/const_prop/while_let_loops.change_loop_body.GVN.diff @@ -37,10 +37,12 @@ bb2: { _1 = const 1_i32; _0 = const (); + StorageDead(_3); goto -> bb4; } bb3: { + StorageDead(_3); StorageLive(_7); _0 = const (); StorageDead(_7); @@ -48,7 +50,6 @@ } bb4: { - StorageDead(_3); StorageDead(_1); return; } diff --git a/tests/mir-opt/funky_arms.float_to_exponential_common.GVN.panic-abort.diff b/tests/mir-opt/funky_arms.float_to_exponential_common.GVN.panic-abort.diff index 8a701641ff9ab..d6efe9b8a688e 100644 --- a/tests/mir-opt/funky_arms.float_to_exponential_common.GVN.panic-abort.diff +++ b/tests/mir-opt/funky_arms.float_to_exponential_common.GVN.panic-abort.diff @@ -103,10 +103,12 @@ StorageDead(_9); - StorageDead(_8); + nop; + StorageDead(_6); goto -> bb8; } bb6: { + StorageDead(_6); StorageLive(_16); _16 = _1; StorageLive(_17); @@ -130,7 +132,6 @@ bb8: { StorageDead(_5); StorageDead(_4); - StorageDead(_6); return; } diff --git a/tests/mir-opt/funky_arms.float_to_exponential_common.GVN.panic-unwind.diff b/tests/mir-opt/funky_arms.float_to_exponential_common.GVN.panic-unwind.diff index 5e65700ee4aae..7c93621f79f6d 100644 --- a/tests/mir-opt/funky_arms.float_to_exponential_common.GVN.panic-unwind.diff +++ b/tests/mir-opt/funky_arms.float_to_exponential_common.GVN.panic-unwind.diff @@ -103,10 +103,12 @@ StorageDead(_9); - StorageDead(_8); + nop; + StorageDead(_6); goto -> bb8; } bb6: { + StorageDead(_6); StorageLive(_16); _16 = _1; StorageLive(_17); @@ -130,7 +132,6 @@ bb8: { StorageDead(_5); StorageDead(_4); - StorageDead(_6); return; } diff --git a/tests/mir-opt/reference_prop.debuginfo.ReferencePropagation.diff b/tests/mir-opt/reference_prop.debuginfo.ReferencePropagation.diff index 05ad9dbf3cccf..6c87f14d4cfdf 100644 --- a/tests/mir-opt/reference_prop.debuginfo.ReferencePropagation.diff +++ b/tests/mir-opt/reference_prop.debuginfo.ReferencePropagation.diff @@ -127,17 +127,19 @@ StorageDead(_21); StorageDead(_20); StorageDead(_19); +- StorageDead(_12); +- StorageDead(_11); goto -> bb8; } bb7: { +- StorageDead(_12); +- StorageDead(_11); - _10 = const (); goto -> bb8; } bb8: { -- StorageDead(_12); -- StorageDead(_11); - StorageDead(_10); StorageLive(_22); StorageLive(_23); diff --git a/tests/mir-opt/simplify_locals_fixedpoint.foo.SimplifyLocals-final.panic-abort.diff b/tests/mir-opt/simplify_locals_fixedpoint.foo.SimplifyLocals-final.panic-abort.diff index c520a159f47b2..d277545150bb1 100644 --- a/tests/mir-opt/simplify_locals_fixedpoint.foo.SimplifyLocals-final.panic-abort.diff +++ b/tests/mir-opt/simplify_locals_fixedpoint.foo.SimplifyLocals-final.panic-abort.diff @@ -23,19 +23,19 @@ StorageDead(_3); StorageDead(_2); _5 = discriminant((_1.0: std::option::Option)); - switchInt(move _5) -> [1: bb1, 0: bb3, otherwise: bb5]; + switchInt(move _5) -> [1: bb1, 0: bb3, otherwise: bb7]; } bb1: { _4 = discriminant((_1.1: std::option::Option)); - switchInt(move _4) -> [0: bb2, 1: bb3, otherwise: bb5]; + switchInt(move _4) -> [0: bb2, 1: bb3, otherwise: bb7]; } bb2: { StorageLive(_6); _6 = (((_1.0: std::option::Option) as Some).0: u8); StorageDead(_6); - goto -> bb3; + drop(_1) -> [return: bb5, unwind unreachable]; } bb3: { @@ -44,10 +44,19 @@ bb4: { StorageDead(_1); - return; + goto -> bb6; } bb5: { + StorageDead(_1); + goto -> bb6; + } + + bb6: { + return; + } + + bb7: { unreachable; } } diff --git a/tests/mir-opt/simplify_locals_fixedpoint.foo.SimplifyLocals-final.panic-unwind.diff b/tests/mir-opt/simplify_locals_fixedpoint.foo.SimplifyLocals-final.panic-unwind.diff index 686581591fc4e..3bec1d6a0d686 100644 --- a/tests/mir-opt/simplify_locals_fixedpoint.foo.SimplifyLocals-final.panic-unwind.diff +++ b/tests/mir-opt/simplify_locals_fixedpoint.foo.SimplifyLocals-final.panic-unwind.diff @@ -23,19 +23,19 @@ StorageDead(_3); StorageDead(_2); _5 = discriminant((_1.0: std::option::Option)); - switchInt(move _5) -> [1: bb1, 0: bb3, otherwise: bb5]; + switchInt(move _5) -> [1: bb1, 0: bb3, otherwise: bb7]; } bb1: { _4 = discriminant((_1.1: std::option::Option)); - switchInt(move _4) -> [0: bb2, 1: bb3, otherwise: bb5]; + switchInt(move _4) -> [0: bb2, 1: bb3, otherwise: bb7]; } bb2: { StorageLive(_6); _6 = (((_1.0: std::option::Option) as Some).0: u8); StorageDead(_6); - goto -> bb3; + drop(_1) -> [return: bb5, unwind continue]; } bb3: { @@ -44,10 +44,19 @@ bb4: { StorageDead(_1); - return; + goto -> bb6; } bb5: { + StorageDead(_1); + goto -> bb6; + } + + bb6: { + return; + } + + bb7: { unreachable; } } diff --git a/tests/mir-opt/sroa/structs.enums.ScalarReplacementOfAggregates.diff b/tests/mir-opt/sroa/structs.enums.ScalarReplacementOfAggregates.diff index b5e39e632476c..3c610cb7b0f3b 100644 --- a/tests/mir-opt/sroa/structs.enums.ScalarReplacementOfAggregates.diff +++ b/tests/mir-opt/sroa/structs.enums.ScalarReplacementOfAggregates.diff @@ -27,16 +27,17 @@ _5 = ((_2 as Some).0: usize); _0 = _5; StorageDead(_5); + StorageDead(_2); goto -> bb3; } bb2: { + StorageDead(_2); _0 = const 0_usize; goto -> bb3; } bb3: { - StorageDead(_2); return; } } diff --git a/tests/mir-opt/unreachable.if_let.UnreachablePropagation.panic-abort.diff b/tests/mir-opt/unreachable.if_let.UnreachablePropagation.panic-abort.diff index 61959732720e0..751b60b37fc7f 100644 --- a/tests/mir-opt/unreachable.if_let.UnreachablePropagation.panic-abort.diff +++ b/tests/mir-opt/unreachable.if_let.UnreachablePropagation.panic-abort.diff @@ -64,8 +64,8 @@ } bb6: { - _0 = const (); StorageDead(_1); + _0 = const (); return; } } diff --git a/tests/mir-opt/unreachable.if_let.UnreachablePropagation.panic-unwind.diff b/tests/mir-opt/unreachable.if_let.UnreachablePropagation.panic-unwind.diff index 476e2f5599449..550fe6e1d6e51 100644 --- a/tests/mir-opt/unreachable.if_let.UnreachablePropagation.panic-unwind.diff +++ b/tests/mir-opt/unreachable.if_let.UnreachablePropagation.panic-unwind.diff @@ -64,8 +64,8 @@ } bb6: { - _0 = const (); StorageDead(_1); + _0 = const (); return; } } diff --git a/tests/mir-opt/unreachable_diverging.main.UnreachablePropagation.panic-abort.diff b/tests/mir-opt/unreachable_diverging.main.UnreachablePropagation.panic-abort.diff index 11d7924e7360e..9da03277646c8 100644 --- a/tests/mir-opt/unreachable_diverging.main.UnreachablePropagation.panic-abort.diff +++ b/tests/mir-opt/unreachable_diverging.main.UnreachablePropagation.panic-abort.diff @@ -60,9 +60,9 @@ } bb6: { + StorageDead(_2); _0 = const (); StorageDead(_1); - StorageDead(_2); return; } } diff --git a/tests/mir-opt/unreachable_diverging.main.UnreachablePropagation.panic-unwind.diff b/tests/mir-opt/unreachable_diverging.main.UnreachablePropagation.panic-unwind.diff index df6f5609fbfa9..1a3e46c4634b5 100644 --- a/tests/mir-opt/unreachable_diverging.main.UnreachablePropagation.panic-unwind.diff +++ b/tests/mir-opt/unreachable_diverging.main.UnreachablePropagation.panic-unwind.diff @@ -60,9 +60,9 @@ } bb6: { + StorageDead(_2); _0 = const (); StorageDead(_1); - StorageDead(_2); return; } } diff --git a/tests/ui/drop/drop_order_if_let_rescope.rs b/tests/ui/drop/drop_order_if_let_rescope.rs new file mode 100644 index 0000000000000..ae9f381820e16 --- /dev/null +++ b/tests/ui/drop/drop_order_if_let_rescope.rs @@ -0,0 +1,122 @@ +//@ run-pass +//@ edition:2024 +//@ compile-flags: -Z validate-mir -Zunstable-options + +#![feature(let_chains)] +#![feature(if_let_rescope)] + +use std::cell::RefCell; +use std::convert::TryInto; + +#[derive(Default)] +struct DropOrderCollector(RefCell>); + +struct LoudDrop<'a>(&'a DropOrderCollector, u32); + +impl Drop for LoudDrop<'_> { + fn drop(&mut self) { + println!("{}", self.1); + self.0.0.borrow_mut().push(self.1); + } +} + +impl DropOrderCollector { + fn option_loud_drop(&self, n: u32) -> Option { + Some(LoudDrop(self, n)) + } + + fn print(&self, n: u32) { + println!("{}", n); + self.0.borrow_mut().push(n) + } + + fn assert_sorted(self) { + assert!( + self.0 + .into_inner() + .into_iter() + .enumerate() + .all(|(idx, item)| idx + 1 == item.try_into().unwrap()) + ); + } + + fn if_let(&self) { + if let None = self.option_loud_drop(1) { + unreachable!(); + } else { + self.print(2); + } + + if let Some(_) = self.option_loud_drop(4) { + self.print(3); + } + + if let Some(_d) = self.option_loud_drop(6) { + self.print(5); + } + } + + fn let_chain(&self) { + // take the "then" branch + if self.option_loud_drop(1).is_some() // 1 + && self.option_loud_drop(2).is_some() // 2 + && let Some(_d) = self.option_loud_drop(4) + // 4 + { + self.print(3); // 3 + } + + // take the "else" branch + if self.option_loud_drop(5).is_some() // 1 + && self.option_loud_drop(6).is_some() // 2 + && let None = self.option_loud_drop(7) + // 3 + { + unreachable!(); + } else { + self.print(8); // 4 + } + + // let exprs interspersed + if self.option_loud_drop(9).is_some() // 1 + && let Some(_d) = self.option_loud_drop(13) // 5 + && self.option_loud_drop(10).is_some() // 2 + && let Some(_e) = self.option_loud_drop(12) + // 4 + { + self.print(11); // 3 + } + + // let exprs first + if let Some(_d) = self.option_loud_drop(18) // 5 + && let Some(_e) = self.option_loud_drop(17) // 4 + && self.option_loud_drop(14).is_some() // 1 + && self.option_loud_drop(15).is_some() + // 2 + { + self.print(16); // 3 + } + + // let exprs last + if self.option_loud_drop(19).is_some() // 1 + && self.option_loud_drop(20).is_some() // 2 + && let Some(_d) = self.option_loud_drop(23) // 5 + && let Some(_e) = self.option_loud_drop(22) + // 4 + { + self.print(21); // 3 + } + } +} + +fn main() { + println!("-- if let --"); + let collector = DropOrderCollector::default(); + collector.if_let(); + collector.assert_sorted(); + + println!("-- let chain --"); + let collector = DropOrderCollector::default(); + collector.let_chain(); + collector.assert_sorted(); +} diff --git a/tests/ui/feature-gates/feature-gate-if-let-rescope.rs b/tests/ui/feature-gates/feature-gate-if-let-rescope.rs new file mode 100644 index 0000000000000..8b735a59070e8 --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-if-let-rescope.rs @@ -0,0 +1,25 @@ +struct A; +struct B<'a, T>(&'a mut T); + +impl A { + fn f(&mut self) -> Option> { + Some(B(self)) + } +} + +impl<'a, T> Drop for B<'a, T> { + fn drop(&mut self) { + // this is needed to keep NLL's hands off and to ensure + // the inner mutable borrow stays alive + } +} + +fn main() { + let mut a = A; + if let None = a.f().as_ref() { + unreachable!() + } else { + a.f().unwrap(); + //~^ ERROR cannot borrow `a` as mutable more than once at a time + }; +} diff --git a/tests/ui/feature-gates/feature-gate-if-let-rescope.stderr b/tests/ui/feature-gates/feature-gate-if-let-rescope.stderr new file mode 100644 index 0000000000000..d441b43cf869a --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-if-let-rescope.stderr @@ -0,0 +1,18 @@ +error[E0499]: cannot borrow `a` as mutable more than once at a time + --> $DIR/feature-gate-if-let-rescope.rs:22:9 + | +LL | if let None = a.f().as_ref() { + | ----- + | | + | first mutable borrow occurs here + | a temporary with access to the first borrow is created here ... +... +LL | a.f().unwrap(); + | ^ second mutable borrow occurs here +LL | +LL | }; + | - ... and the first borrow might be used here, when that temporary is dropped and runs the destructor for type `Option>` + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0499`. diff --git a/tests/ui/nll/issue-54556-niconii.rs b/tests/ui/nll/issue-54556-niconii.rs index cae389e8ccb52..8fa3fa8f12a22 100644 --- a/tests/ui/nll/issue-54556-niconii.rs +++ b/tests/ui/nll/issue-54556-niconii.rs @@ -1,3 +1,4 @@ +//@ check-pass // This is a reduction of a concrete test illustrating a case that was // annoying to Rust developer niconii (see comment thread on #21114). // @@ -19,7 +20,7 @@ impl Mutex { fn main() { let counter = Mutex; - if let Ok(_) = counter.lock() { } //~ ERROR does not live long enough + if let Ok(_) = counter.lock() { } // With this code as written, the dynamic semantics here implies // that `Mutex::drop` for `counter` runs *before* @@ -28,4 +29,5 @@ fn main() { // // The goal of #54556 is to explain that within a compiler // diagnostic. + () } diff --git a/tests/ui/nll/issue-54556-niconii.stderr b/tests/ui/nll/issue-54556-niconii.stderr deleted file mode 100644 index 015d9e1821205..0000000000000 --- a/tests/ui/nll/issue-54556-niconii.stderr +++ /dev/null @@ -1,26 +0,0 @@ -error[E0597]: `counter` does not live long enough - --> $DIR/issue-54556-niconii.rs:22:20 - | -LL | let counter = Mutex; - | ------- binding `counter` declared here -LL | -LL | if let Ok(_) = counter.lock() { } - | ^^^^^^^------- - | | - | borrowed value does not live long enough - | a temporary with access to the borrow is created here ... -... -LL | } - | - - | | - | `counter` dropped here while still borrowed - | ... and the borrow might be used here, when that temporary is dropped and runs the destructor for type `Result, ()>` - | -help: consider adding semicolon after the expression so its temporaries are dropped sooner, before the local variables declared by the block are dropped - | -LL | if let Ok(_) = counter.lock() { }; - | + - -error: aborting due to 1 previous error - -For more information about this error, try `rustc --explain E0597`.