From be204dd047e5fb65aac96cb8fb81734d2f22f895 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9my=20Rakic?= Date: Fri, 13 Feb 2026 17:10:29 +0000 Subject: [PATCH 1/2] make per-point liveness accessible It avoids round-tripping through `Location`s if you're working with `Point`s already. --- compiler/rustc_borrowck/src/polonius/mod.rs | 3 +-- compiler/rustc_borrowck/src/region_infer/values.rs | 10 +++++++++- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/compiler/rustc_borrowck/src/polonius/mod.rs b/compiler/rustc_borrowck/src/polonius/mod.rs index 0924ce25c52ea..45108bfcb79ba 100644 --- a/compiler/rustc_borrowck/src/polonius/mod.rs +++ b/compiler/rustc_borrowck/src/polonius/mod.rs @@ -182,8 +182,7 @@ impl LocalizedConstraintGraphVisitor for LoanLivenessVisitor<'_> { // // FIXME: analyze potential unsoundness, possibly in concert with a borrowck // implementation in a-mir-formality, fuzzing, or manually crafting counter-examples. - let location = self.liveness.location_from_point(node.point); - if self.liveness.is_live_at(node.region, location) { + if self.liveness.is_live_at_point(node.region, node.point) { self.live_loans.insert(node.point, loan); } } diff --git a/compiler/rustc_borrowck/src/region_infer/values.rs b/compiler/rustc_borrowck/src/region_infer/values.rs index 1dd3bc831f45a..c1fed1260340f 100644 --- a/compiler/rustc_borrowck/src/region_infer/values.rs +++ b/compiler/rustc_borrowck/src/region_infer/values.rs @@ -131,9 +131,17 @@ impl LivenessValues { } } - /// Returns whether `region` is marked live at the given `location`. + /// Returns whether `region` is marked live at the given + /// [`location`][rustc_middle::mir::Location]. pub(crate) fn is_live_at(&self, region: RegionVid, location: Location) -> bool { let point = self.location_map.point_from_location(location); + self.is_live_at_point(region, point) + } + + /// Returns whether `region` is marked live at the given + /// [`point`][rustc_mir_dataflow::points::PointIndex]. + #[inline] + pub(crate) fn is_live_at_point(&self, region: RegionVid, point: PointIndex) -> bool { if let Some(points) = &self.points { points.row(region).is_some_and(|r| r.contains(point)) } else { From 65eb2e709d1d1282b8e258281a5ee2a9edaf9a26 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9my=20Rakic?= Date: Fri, 13 Feb 2026 17:29:49 +0000 Subject: [PATCH 2/2] add another NLL problem case 3 variant --- .../nll-problem-case-3-issue-21906.nll.stderr | 23 +++++++++++++++---- .../nll-problem-case-3-issue-21906.rs | 20 ++++++++++++++++ 2 files changed, 38 insertions(+), 5 deletions(-) diff --git a/tests/ui/nll/polonius/nll-problem-case-3-issue-21906.nll.stderr b/tests/ui/nll/polonius/nll-problem-case-3-issue-21906.nll.stderr index e16300886b0b9..0ab90faabcf0f 100644 --- a/tests/ui/nll/polonius/nll-problem-case-3-issue-21906.nll.stderr +++ b/tests/ui/nll/polonius/nll-problem-case-3-issue-21906.nll.stderr @@ -35,8 +35,21 @@ LL | | } LL | | } | |_____- returning this value requires that `*map` is borrowed for `'r` +error[E0499]: cannot borrow `*map` as mutable more than once at a time + --> $DIR/nll-problem-case-3-issue-21906.rs:45:41 + | +LL | fn get_priority_mut_entry<'a, K, V>( + | -- lifetime `'a` defined here +... +LL | match map.entry(key1) { + | --- first mutable borrow occurs here +LL | Entry::Occupied(occupied) => Some(occupied.into_mut()), + | ------------------------- returning this value requires that `*map` is borrowed for `'a` +LL | Entry::Vacant(_vacant) => match map.entry(key2) { + | ^^^ second mutable borrow occurs here + error[E0499]: cannot borrow `*self` as mutable more than once at a time - --> $DIR/nll-problem-case-3-issue-21906.rs:44:21 + --> $DIR/nll-problem-case-3-issue-21906.rs:64:21 | LL | fn two(&mut self) -> &i32 { | - let's call the lifetime of this reference `'1` @@ -48,7 +61,7 @@ LL | return k; | - returning this value requires that `*self` is borrowed for `'1` error[E0502]: cannot borrow `x.data` as immutable because it is also borrowed as mutable - --> $DIR/nll-problem-case-3-issue-21906.rs:62:22 + --> $DIR/nll-problem-case-3-issue-21906.rs:82:22 | LL | fn foo(x: &mut Foo) -> Option<&mut i32> { | - let's call the lifetime of this reference `'1` @@ -61,7 +74,7 @@ LL | println!("{:?}", x.data); | ^^^^^^ immutable borrow occurs here error[E0499]: cannot borrow `*vec` as mutable more than once at a time - --> $DIR/nll-problem-case-3-issue-21906.rs:77:9 + --> $DIR/nll-problem-case-3-issue-21906.rs:97:9 | LL | fn f(vec: &mut Vec) -> &u8 { | - let's call the lifetime of this reference `'1` @@ -75,7 +88,7 @@ LL | vec.push(10); | ^^^ second mutable borrow occurs here error[E0502]: cannot borrow `*vec` as immutable because it is also borrowed as mutable - --> $DIR/nll-problem-case-3-issue-21906.rs:78:9 + --> $DIR/nll-problem-case-3-issue-21906.rs:98:9 | LL | fn f(vec: &mut Vec) -> &u8 { | - let's call the lifetime of this reference `'1` @@ -88,7 +101,7 @@ LL | n LL | vec.last().unwrap() | ^^^ immutable borrow occurs here -error: aborting due to 6 previous errors +error: aborting due to 7 previous errors Some errors have detailed explanations: E0499, E0502. For more information about an error, try `rustc --explain E0499`. diff --git a/tests/ui/nll/polonius/nll-problem-case-3-issue-21906.rs b/tests/ui/nll/polonius/nll-problem-case-3-issue-21906.rs index b025ea78f8b49..45b56e32522f0 100644 --- a/tests/ui/nll/polonius/nll-problem-case-3-issue-21906.rs +++ b/tests/ui/nll/polonius/nll-problem-case-3-issue-21906.rs @@ -29,6 +29,26 @@ fn from_the_rfc<'r, K: Hash + Eq + Copy, V: Default>( } } +// A variant that's similar to the RFC example above, but using the entry API, and requested in +// https://internals.rust-lang.org/t/get-mut-map-back-from-entry-api/24003 +fn get_priority_mut_entry<'a, K, V>( + map: &'a mut HashMap, + key1: K, + key2: K, +) -> Option<&'a mut V> +where + K: Eq + Hash, +{ + use std::collections::hash_map::Entry; + match map.entry(key1) { + Entry::Occupied(occupied) => Some(occupied.into_mut()), + Entry::Vacant(_vacant) => match map.entry(key2) { + Entry::Occupied(occupied2) => Some(occupied2.into_mut()), + Entry::Vacant(_) => None, + }, + } +} + // MCVE 1 from issue #21906 struct A { a: i32,