Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 1 addition & 2 deletions compiler/rustc_borrowck/src/polonius/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
}
Expand Down
10 changes: 9 additions & 1 deletion compiler/rustc_borrowck/src/region_infer/values.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down
23 changes: 18 additions & 5 deletions tests/ui/nll/polonius/nll-problem-case-3-issue-21906.nll.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -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`
Expand All @@ -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`
Expand All @@ -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>) -> &u8 {
| - let's call the lifetime of this reference `'1`
Expand All @@ -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>) -> &u8 {
| - let's call the lifetime of this reference `'1`
Expand All @@ -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`.
20 changes: 20 additions & 0 deletions tests/ui/nll/polonius/nll-problem-case-3-issue-21906.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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<K, V>,
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,
Expand Down
Loading