Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improvements and Bug Fixes #21

Open
wants to merge 44 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
44 commits
Select commit Hold shift + click to select a range
d1d5a06
Lock crates used for testing
zgrannan Mar 13, 2025
6ea610a
remove build.rs
zgrannan Mar 13, 2025
6287c21
WIP
zgrannan Mar 14, 2025
ca685aa
Two-phase borrows
zgrannan Mar 14, 2025
0f878d3
Appease clippy
zgrannan Mar 14, 2025
4c0b1d5
Polonius fixes
zgrannan Mar 14, 2025
1a841ce
No capabilities on region projections
zgrannan Mar 14, 2025
208f559
Use dyn
zgrannan Mar 15, 2025
8ce9e46
Fix liveness computation for RP graph
zgrannan Mar 15, 2025
35adcbf
Support for havocing of nested references in fn calls
zgrannan Mar 16, 2025
21741af
Render alias edges
zgrannan Mar 16, 2025
8fc8ceb
Graph rendering improvements
zgrannan Mar 16, 2025
5893e62
Support an additional case
zgrannan Mar 17, 2025
22f37ae
another case
zgrannan Mar 17, 2025
efc4768
Fix dotgraph tooltip
zgrannan Mar 17, 2025
acd5185
Small stuff
zgrannan Mar 17, 2025
9546516
Fix visualization
zgrannan Mar 17, 2025
7d5cf5d
add additional test
zgrannan Mar 19, 2025
34e5e5a
cleanup
zgrannan Mar 20, 2025
54fd516
Add a fix for loops
zgrannan Mar 21, 2025
b6769d8
Fix for polonius
zgrannan Mar 21, 2025
8b93951
loop fixes
zgrannan Mar 22, 2025
8775218
update benchmarks
zgrannan Mar 22, 2025
0024efa
typecheck only version for comparison
zgrannan Mar 23, 2025
4f0873b
Save cached lockfiles
zgrannan Mar 23, 2025
c933b13
Add all the lockfiles
zgrannan Mar 23, 2025
80f53cf
WIP
zgrannan Mar 24, 2025
e874765
Try not merging sccs
zgrannan Mar 24, 2025
3bb36f9
Try not merging sccs
zgrannan Mar 24, 2025
34b0f16
ignore crate
zgrannan Mar 24, 2025
ee65309
loop fix
zgrannan Mar 24, 2025
f5cc50a
WIP
zgrannan Mar 24, 2025
f2ebbfa
CI fixes
zgrannan Mar 24, 2025
301920e
CI fixes
zgrannan Mar 24, 2025
bb043aa
Disable validity checks on this crate for now
zgrannan Mar 24, 2025
429cc28
WIP
zgrannan Mar 24, 2025
749e576
Fix Jonas's example
zgrannan Mar 24, 2025
372c278
Mostly fix visualization
zgrannan Mar 24, 2025
e5d2063
Maybe improvements for rpa construction
zgrannan Mar 25, 2025
1c3d5d7
Fix issues Jasper identified
zgrannan Mar 25, 2025
80989cd
Performance improvements for serde_derive
zgrannan Mar 25, 2025
f869106
Fix stupid weaken issue
zgrannan Mar 25, 2025
2f0a3e4
Fix itertools and regex-syntax
zgrannan Mar 25, 2025
ce37652
update benchmark results
zgrannan Mar 25, 2025
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
Prev Previous commit
Next Next commit
Support for havocing of nested references in fn calls
  • Loading branch information
zgrannan committed Mar 21, 2025
commit 35adcbf6078d17bf1002e79c7e82a750bb504115
21 changes: 3 additions & 18 deletions src/borrow_pcg/action/actions.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
use derive_more::Deref;

use crate::borrow_pcg::action::BorrowPCGAction;
use crate::borrow_pcg::borrow_pcg_edge::BorrowPCGEdge;
use crate::borrow_pcg::borrow_pcg_expansion::BorrowPCGExpansion;
use crate::borrow_pcg::edge::kind::BorrowPCGEdgeKind;
use crate::borrow_pcg::edge::outlives::OutlivesEdge;
use crate::borrow_pcg::graph::Conditioned;
Expand All @@ -12,7 +13,7 @@ use crate::{validity_checks_enabled, Weaken};

use super::BorrowPCGActionKind;

#[derive(Clone, Debug, Default)]
#[derive(Clone, Deref, Debug, Default)]
pub struct BorrowPCGActions<'tcx>(pub(crate) Vec<BorrowPCGAction<'tcx>>);

impl<'tcx> ToJsonWithRepacker<'tcx> for BorrowPCGActions<'tcx> {
Expand Down Expand Up @@ -68,22 +69,6 @@ impl<'tcx> BorrowPCGActions<'tcx> {
})
.collect()
}

pub fn expands(&self) -> FxHashSet<Conditioned<BorrowPCGExpansion<'tcx>>> {
self.0
.iter()
.filter_map(|action| match action.kind() {
BorrowPCGActionKind::AddEdge { edge, .. } => match edge.kind() {
BorrowPCGEdgeKind::BorrowPCGExpansion(expansion) => Some(Conditioned::new(
expansion.clone(),
edge.conditions().clone(),
)),
_ => None,
},
_ => None,
})
.collect()
}
}

impl<'tcx> BorrowPCGActions<'tcx> {
Expand Down
18 changes: 4 additions & 14 deletions src/borrow_pcg/action/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -214,9 +214,7 @@ impl<'tcx> BorrowsState<'tcx> {
true
}
BorrowPCGActionKind::MakePlaceOld(place) => self.make_place_old(place, repacker),
BorrowPCGActionKind::SetLatest(place, location) => {
self.set_latest(place, location, repacker)
}
BorrowPCGActionKind::SetLatest(place, location) => self.set_latest(place, location),
BorrowPCGActionKind::RemoveEdge(edge) => self.remove(&edge, repacker),
BorrowPCGActionKind::AddEdge {
edge,
Expand All @@ -235,7 +233,6 @@ impl<'tcx> BorrowsState<'tcx> {
) -> Result<bool, PcgError> {
let mut changed = self.insert(edge.clone());
Ok(match edge.kind {
BorrowPCGEdgeKind::Borrow(_) => changed,
BorrowPCGEdgeKind::BorrowPCGExpansion(expansion) => {
if changed {
let base = expansion.base;
Expand Down Expand Up @@ -277,20 +274,13 @@ impl<'tcx> BorrowsState<'tcx> {
}
changed
}
BorrowPCGEdgeKind::Abstraction(_) => changed,
BorrowPCGEdgeKind::Outlives(_) => changed,
BorrowPCGEdgeKind::RegionProjectionMember(_) => changed,
_ => changed,
})
}

#[must_use]
fn set_latest<T: Into<SnapshotLocation>>(
&mut self,
place: Place<'tcx>,
location: T,
repacker: PlaceRepacker<'_, 'tcx>,
) -> bool {
fn set_latest<T: Into<SnapshotLocation>>(&mut self, place: Place<'tcx>, location: T) -> bool {
let location = location.into();
self.latest.insert(place, location, repacker)
self.latest.insert(place, location)
}
}
6 changes: 3 additions & 3 deletions src/borrow_pcg/borrow_pcg_edge.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,7 @@ use super::{
borrow_pcg_expansion::BorrowPCGExpansion,
coupling_graph_constructor::CGNode,
edge::{
borrow::RemoteBorrow, outlives::OutlivesEdge,
region_projection_member::RegionProjectionMember,
borrow::RemoteBorrow, coupling::FunctionCallRegionCoupling, outlives::OutlivesEdge, region_projection_member::RegionProjectionMember
},
edge_data::EdgeData,
graph::Conditioned,
Expand Down Expand Up @@ -329,7 +328,7 @@ impl<'tcx> PCGNode<'tcx> {
PCGNode::Place(MaybeRemotePlace::Remote(_)) => None,
PCGNode::RegionProjection(rp) => {
let place = rp.place().as_local_place()?;
Some(LocalNode::RegionProjection(rp.set_base(place, repacker)))
Some(LocalNode::RegionProjection(rp.with_base(place, repacker)))
}
}
}
Expand Down Expand Up @@ -437,6 +436,7 @@ edgedata_enum!(
Abstraction(AbstractionType<'tcx>),
Outlives(OutlivesEdge<'tcx>),
RegionProjectionMember(RegionProjectionMember<'tcx>),
FunctionCallRegionCoupling(FunctionCallRegionCoupling<'tcx>),
);

pub(crate) trait ToBorrowsEdge<'tcx> {
Expand Down
2 changes: 1 addition & 1 deletion src/borrow_pcg/borrow_pcg_expansion.rs
Original file line number Diff line number Diff line change
Expand Up @@ -209,7 +209,7 @@ impl<'tcx> EdgeData<'tcx> for BorrowPCGExpansion<'tcx> {
{
base.insert(
base_projection
.set_base(base_projection.base.into(), repacker)
.with_base(base_projection.base.into(), repacker)
.into(),
);
}
Expand Down
11 changes: 4 additions & 7 deletions src/borrow_pcg/coupling_graph_constructor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,10 @@ pub trait BorrowCheckerInterface<'mir, 'tcx: 'mir> {
fn is_live(&self, node: PCGNode<'tcx>, location: Location) -> bool;
fn outlives(&self, sup: PCGRegion, sub: PCGRegion) -> bool;

fn same_region(&self, reg1: PCGRegion, reg2: PCGRegion) -> bool {
self.outlives(reg1, reg2) && self.outlives(reg2, reg1)
}

/// Returns the set of two-phase borrows that activate at `location`.
/// Each borrow in the returned set is represented by the MIR location
/// that it was created at.
Expand Down Expand Up @@ -278,13 +282,6 @@ impl<'mir, 'tcx> RegionProjectionAbstractionConstructor<'mir, 'tcx> {
},
) && !n.is_old()
});
tracing::info!(
"connect {} to {} ? (is_root: {:?}): {}",
bottom_connect.to_short_string(self.repacker),
coupled.to_short_string(self.repacker),
is_root,
should_include
);
if !should_include {
self.add_edges_from(
bg,
Expand Down
2 changes: 1 addition & 1 deletion src/borrow_pcg/domain.rs
Original file line number Diff line number Diff line change
Expand Up @@ -172,7 +172,7 @@ impl<'mir, 'tcx: 'mir> BorrowsDomain<'mir, 'tcx> {
);
}),
region_projection,
OutlivesEdgeKind::Todo,
OutlivesEdgeKind::InitialBorrows,
self.repacker,
)
.into(),
Expand Down
109 changes: 109 additions & 0 deletions src/borrow_pcg/edge/coupling.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
use crate::borrow_pcg::borrow_pcg_edge::LocalNode;
use crate::borrow_pcg::edge_data::EdgeData;
use crate::borrow_pcg::has_pcs_elem::{default_make_place_old, HasPcgElems, MakePlaceOld};
use crate::borrow_pcg::latest::Latest;
use crate::borrow_pcg::region_projection::LocalRegionProjection;
use crate::combined_pcs::{LocalNodeLike, PCGNode, PCGNodeLike};
use crate::pcg_validity_assert;
use crate::rustc_interface::data_structures::fx::FxHashSet;
use crate::utils::display::DisplayWithRepacker;
use crate::utils::maybe_old::MaybeOldPlace;
use crate::utils::validity::HasValidityCheck;
use crate::utils::{Place, PlaceRepacker};

#[derive(Clone, Debug, Eq, PartialEq, Hash)]
pub struct FunctionCallRegionCoupling<'tcx> {
pub(crate) inputs: Vec<LocalRegionProjection<'tcx>>,
pub(crate) outputs: Vec<LocalRegionProjection<'tcx>>,
}

impl <'tcx> FunctionCallRegionCoupling<'tcx> {
pub fn inputs(&self) -> &[LocalRegionProjection<'tcx>] {
&self.inputs
}
pub fn outputs(&self) -> &[LocalRegionProjection<'tcx>] {
&self.outputs
}

pub fn num_coupled_nodes(&self) -> usize {
self.inputs.len()
}
}

impl<'tcx> HasValidityCheck<'tcx> for FunctionCallRegionCoupling<'tcx> {
fn check_validity(&self, repacker: PlaceRepacker<'_, 'tcx>) -> Result<(), String> {
for input in self.inputs.iter() {
input.check_validity(repacker)?;
}
for output in self.outputs.iter() {
output.check_validity(repacker)?;
}
Ok(())
}
}

impl<'tcx> MakePlaceOld<'tcx> for FunctionCallRegionCoupling<'tcx> {
fn make_place_old(
&mut self,
place: Place<'tcx>,
latest: &Latest<'tcx>,
repacker: PlaceRepacker<'_, 'tcx>,
) -> bool {
default_make_place_old(self, place, latest, repacker)
}
}

impl<'tcx> HasPcgElems<MaybeOldPlace<'tcx>> for FunctionCallRegionCoupling<'tcx> {
fn pcg_elems(&mut self) -> Vec<&mut MaybeOldPlace<'tcx>> {
self.inputs
.iter_mut()
.flat_map(|rp| rp.pcg_elems())
.collect::<Vec<_>>()
.into_iter()
.chain(
self.outputs
.iter_mut()
.flat_map(|rp| rp.pcg_elems())
.collect::<Vec<_>>(),
)
.collect()
}
}

impl<'tcx> DisplayWithRepacker<'tcx> for FunctionCallRegionCoupling<'tcx> {
fn to_short_string(&self, _repacker: PlaceRepacker<'_, 'tcx>) -> String {
format!(
"FunctionCallRegionCoupling({:?}, {:?})",
self.inputs, self.outputs
)
}
}

impl<'tcx> FunctionCallRegionCoupling<'tcx> {
pub(crate) fn new(
inputs: FxHashSet<LocalRegionProjection<'tcx>>,
outputs: FxHashSet<LocalRegionProjection<'tcx>>,
) -> Self {
pcg_validity_assert!(inputs.len() == outputs.len());
Self {
inputs: inputs.into_iter().collect(),
outputs: outputs.into_iter().collect(),
}
}
}

impl<'tcx> EdgeData<'tcx> for FunctionCallRegionCoupling<'tcx> {
fn blocked_nodes(&self, repacker: PlaceRepacker<'_, 'tcx>) -> FxHashSet<PCGNode<'tcx>> {
self.inputs
.iter()
.map(|rp| rp.to_pcg_node(repacker))
.collect()
}

fn blocked_by_nodes(&self, repacker: PlaceRepacker<'_, 'tcx>) -> FxHashSet<LocalNode<'tcx>> {
self.outputs
.iter()
.map(|rp| rp.to_local_node(repacker))
.collect()
}
}
2 changes: 2 additions & 0 deletions src/borrow_pcg/edge/kind.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ use crate::borrow_pcg::edge::borrow::BorrowEdge;
use crate::utils::PlaceRepacker;

use super::borrow::RemoteBorrow;
use super::coupling::FunctionCallRegionCoupling;
use super::outlives::OutlivesEdge;
use super::region_projection_member::RegionProjectionMember;

Expand All @@ -14,6 +15,7 @@ pub enum BorrowPCGEdgeKind<'tcx> {
Abstraction(AbstractionType<'tcx>),
Outlives(OutlivesEdge<'tcx>),
RegionProjectionMember(RegionProjectionMember<'tcx>),
FunctionCallRegionCoupling(FunctionCallRegionCoupling<'tcx>),
}

impl<'tcx> From<RemoteBorrow<'tcx>> for BorrowPCGEdgeKind<'tcx> {
Expand Down
1 change: 1 addition & 0 deletions src/borrow_pcg/edge/mod.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
pub mod abstraction;
pub mod borrow;
pub mod coupling;
pub mod kind;
pub mod outlives;
pub mod region_projection_member;
24 changes: 15 additions & 9 deletions src/borrow_pcg/edge/outlives.rs
Original file line number Diff line number Diff line change
Expand Up @@ -114,31 +114,37 @@ pub enum OutlivesEdgeKind {
/// for `{y|'a} -> {x|'b}` of this kind is created if 'a outlives 'b.
///
/// `toplevel` is true for edges to x↓'x, false otherwise.
BorrowOutlives { toplevel: bool },
BorrowOutlives {
toplevel: bool,
},
/// If e.g {x|'a} -> {y|'b} is a BorrowsOutlives, then {*x|'a} -> {*y|'b} is a DerefBorrowsOutlives
/// (it's introduced if e.g. *y is expanded in the PCG)
DerefBorrowOutlives,
/// TODO: Provide more useful kinds, this enum variant should be removed
Todo,
/// Initial borrows edge
InitialBorrows,
CopySharedRef,
HavocRegion
}

impl std::fmt::Display for OutlivesEdgeKind {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
OutlivesEdgeKind::Aggregate {
field_idx,
target_rp_index,
} => write!(f, "Aggregate({field_idx}, {target_rp_index})"),
field_idx,
target_rp_index,
} => write!(f, "Aggregate({field_idx}, {target_rp_index})"),
OutlivesEdgeKind::Borrow => write!(f, "Borrow"),
OutlivesEdgeKind::DerefRegionProjection => write!(f, "DerefRegionProjection"),
OutlivesEdgeKind::Ref => write!(f, "Ref"),
OutlivesEdgeKind::ContractRef => write!(f, "ContractRef"),
OutlivesEdgeKind::ConstRef => write!(f, "ConstRef"),
OutlivesEdgeKind::BorrowOutlives { toplevel } => {
write!(f, "BorrowOutlives({toplevel})")
}
OutlivesEdgeKind::Todo => write!(f, "Todo"),
write!(f, "BorrowOutlives({toplevel})")
}
OutlivesEdgeKind::DerefBorrowOutlives => write!(f, "DerefBorrowOutlives"),
OutlivesEdgeKind::InitialBorrows => write!(f, "InitialBorrows"),
OutlivesEdgeKind::CopySharedRef => write!(f, "CopySharedRef"),
OutlivesEdgeKind::HavocRegion => write!(f, "HavocRegion"),
}
}
}
26 changes: 16 additions & 10 deletions src/borrow_pcg/graph/aliases.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ use crate::{
edge::{kind::BorrowPCGEdgeKind, outlives::OutlivesEdgeKind},
region_projection::RegionIdx,
},
combined_pcs::{PCGNode, PCGNodeLike},
combined_pcs::{LocalNodeLike, PCGNode, PCGNodeLike},
rustc_interface::data_structures::fx::FxHashSet,
utils::{display::DisplayWithRepacker, HasPlace, PlaceRepacker},
};
Expand Down Expand Up @@ -80,15 +80,15 @@ impl<'tcx> BorrowsGraph<'tcx> {
&mut FxHashSet::default(),
true,
));
if let PCGNode::Place(p) = local_node {
if let Some(rp) = p.deref_to_rp(repacker) {
results.extend(self.direct_aliases(
rp.try_to_local_node(repacker).unwrap(),
repacker,
&mut FxHashSet::default(),
true,
));
}
if let PCGNode::Place(p) = local_node
&& let Some(rp) = p.deref_to_rp(repacker)
{
results.extend(self.direct_aliases(
rp.to_local_node(repacker),
repacker,
&mut FxHashSet::default(),
true,
));
}
}
}
Expand Down Expand Up @@ -166,6 +166,11 @@ impl<'tcx> BorrowsGraph<'tcx> {
);
}
},
BorrowPCGEdgeKind::FunctionCallRegionCoupling(edge) => {
for input in edge.inputs.iter() {
extend(input.to_pcg_node(repacker), seen, &mut result, false);
}
}
_ => todo!(),
}
}
Expand Down Expand Up @@ -232,6 +237,7 @@ fn test_aliases() {
&body.body,
tcx,
);
// *_2 aliases _4 at bb3[1]
assert!(aliases.contains(&temp4));
assert!(aliases.contains(&x));
});
Expand Down
Loading