Skip to content

Commit 714a052

Browse files
authored
Merge pull request #78 from lqd/the-symmetrycity-of-our-city
Remove symmetries in the `subset` relation
2 parents a26cc26 + c5e426d commit 714a052

File tree

3 files changed

+70
-0
lines changed

3 files changed

+70
-0
lines changed

polonius-engine/src/output/datafrog_opt.rs

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,20 @@ pub(super) fn compute<Region: Atom, Loan: Atom, Point: Atom>(
109109

110110
// .. and then start iterating rules!
111111
while iteration.changed() {
112+
// Cleanup step: remove symmetries
113+
// - remove regions which are `subset`s of themselves
114+
//
115+
// FIXME: investigate whether is there a better way to do that without complicating
116+
// the rules too much, because it would also require temporary variables and
117+
// impact performance. Until then, the big reduction in tuples improves performance
118+
// a lot, even if we're potentially adding a small number of tuples
119+
// per round just to remove them in the next round.
120+
subset
121+
.recent
122+
.borrow_mut()
123+
.elements
124+
.retain(|&(r1, r2, _)| r1 != r2);
125+
112126
// remap fields to re-index by the different keys
113127
subset_r1p.from_map(&subset, |&(r1, r2, p)| ((r1, p), r2));
114128
subset_p.from_map(&subset, |&(r1, r2, p)| (p, (r1, r2)));
@@ -319,6 +333,10 @@ pub(super) fn compute<Region: Atom, Loan: Atom, Point: Atom>(
319333
}
320334

321335
let subset = subset.complete();
336+
assert!(
337+
subset.iter().filter(|&(r1, r2, _)| r1 == r2).count() == 0,
338+
"unwanted subset symmetries"
339+
);
322340
for (r1, r2, location) in &subset.elements {
323341
result
324342
.subset

polonius-engine/src/output/naive.rs

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,20 @@ pub(super) fn compute<Region: Atom, Loan: Atom, Point: Atom>(
7777

7878
// .. and then start iterating rules!
7979
while iteration.changed() {
80+
// Cleanup step: remove symmetries
81+
// - remove regions which are `subset`s of themselves
82+
//
83+
// FIXME: investigate whether is there a better way to do that without complicating
84+
// the rules too much, because it would also require temporary variables and
85+
// impact performance. Until then, the big reduction in tuples improves performance
86+
// a lot, even if we're potentially adding a small number of tuples
87+
// per round just to remove them in the next round.
88+
subset
89+
.recent
90+
.borrow_mut()
91+
.elements
92+
.retain(|&(r1, r2, _)| r1 != r2);
93+
8094
// remap fields to re-index by keys.
8195
subset_r1p.from_map(&subset, |&(r1, r2, p)| ((r1, p), r2));
8296
subset_r2p.from_map(&subset, |&(r1, r2, p)| ((r2, p), r1));
@@ -125,6 +139,10 @@ pub(super) fn compute<Region: Atom, Loan: Atom, Point: Atom>(
125139

126140
if dump_enabled {
127141
let subset = subset.complete();
142+
assert!(
143+
subset.iter().filter(|&(r1, r2, _)| r1 == r2).count() == 0,
144+
"unwanted subset symmetries"
145+
);
128146
for (r1, r2, location) in &subset.elements {
129147
result
130148
.subset

src/test.rs

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,40 @@ fn test_sensitive_passes_issue_47680() -> Result<(), Error> {
7676
}
7777
}
7878

79+
#[test]
80+
fn no_subset_symmetries_exist() -> Result<(), Error> {
81+
try {
82+
let facts_dir = Path::new(env!("CARGO_MANIFEST_DIR"))
83+
.join("inputs")
84+
.join("issue-47680")
85+
.join("nll-facts")
86+
.join("main");
87+
let tables = &mut intern::InternerTables::new();
88+
let all_facts = tab_delim::load_tab_delimited_facts(tables, &facts_dir)?;
89+
90+
let subset_symmetries_exist = |output: &Output<Region, Loan, Point>| {
91+
for (_, subsets) in &output.subset {
92+
for (r1, rs) in subsets {
93+
if rs.contains(&r1) {
94+
return true;
95+
}
96+
}
97+
}
98+
false
99+
};
100+
101+
let naive = Output::compute(&all_facts, Algorithm::Naive, true);
102+
assert!(!subset_symmetries_exist(&naive));
103+
104+
// FIXME: the issue-47680 dataset is suboptimal here as DatafrogOpt does not
105+
// produce subset symmetries for it. It does for clap, and it was used to manually verify
106+
// that the assert in verbose mode didn't trigger. Therefore, switch to this dataset
107+
// whenever it's fast enough to be enabled in tests, or somehow create a test facts program
108+
// or reduce it from clap.
109+
let opt = Output::compute(&all_facts, Algorithm::DatafrogOpt, true);
110+
assert!(!subset_symmetries_exist(&opt));
111+
}
112+
}
79113

80114
// The following 3 tests, `send_is_not_static_std_sync`, `escape_upvar_nested`, and `issue_31567`
81115
// are extracted from rustc's test suite, and fail because of differences between the Naive

0 commit comments

Comments
 (0)