@@ -5,7 +5,10 @@ use crate::facts::{AllFacts, Loan, Origin, Point};
55use crate :: intern;
66use crate :: program:: parse_from_program;
77use crate :: tab_delim;
8- use crate :: test_util:: { assert_equal, location_insensitive_checker_for, naive_checker_for} ;
8+ use crate :: test_util:: {
9+ assert_checkers_match, assert_equal, assert_outputs_match, location_insensitive_checker_for,
10+ naive_checker_for, opt_checker_for,
11+ } ;
912use polonius_engine:: Algorithm ;
1013use rustc_hash:: FxHashMap ;
1114use std:: error:: Error ;
@@ -77,11 +80,15 @@ fn test_facts(all_facts: &AllFacts, algorithms: &[Algorithm]) {
7780 // TMP: until we reach our correctness goals, deactivate some comparisons between variants
7881 // assert_equal(&naive.loan_live_at, &opt.loan_live_at);
7982 assert_equal ( & naive. errors , & opt. errors ) ;
83+ assert_equal ( & naive. subset_errors , & opt. subset_errors ) ;
84+ assert_equal ( & naive. move_errors , & opt. move_errors ) ;
8085 }
8186
8287 // The hybrid algorithm gets the same errors as the naive version
8388 let opt = Output :: compute ( all_facts, Algorithm :: Hybrid , true ) ;
8489 assert_equal ( & naive. errors , & opt. errors ) ;
90+ assert_equal ( & naive. subset_errors , & opt. subset_errors ) ;
91+ assert_equal ( & naive. move_errors , & opt. move_errors ) ;
8592}
8693
8794fn test_fn ( dir_name : & str , fn_name : & str , algorithm : Algorithm ) -> Result < ( ) , Box < dyn Error > > {
@@ -316,25 +323,30 @@ fn smoke_test_errors() {
316323 let facts = tab_delim:: load_tab_delimited_facts ( tables, & facts_dir) . expect ( "facts" ) ;
317324
318325 let location_insensitive = Output :: compute ( & facts, Algorithm :: LocationInsensitive , true ) ;
326+ let naive = Output :: compute ( & facts, Algorithm :: Naive , true ) ;
327+ let opt = Output :: compute ( & facts, Algorithm :: DatafrogOpt , true ) ;
328+
329+ // We have to find errors with every analysis
319330 assert ! (
320331 !location_insensitive. errors. is_empty( ) ,
321332 "LocationInsensitive didn't find errors for '{}'" ,
322333 test_fn
323334 ) ;
324-
325- let naive = Output :: compute ( & facts, Algorithm :: Naive , true ) ;
326335 assert ! (
327336 !naive. errors. is_empty( ) ,
328337 "Naive didn't find errors for '{}'" ,
329338 test_fn
330339 ) ;
331-
332- let opt = Output :: compute ( & facts, Algorithm :: DatafrogOpt , true ) ;
333340 assert ! (
334341 !opt. errors. is_empty( ) ,
335342 "DatafrogOpt didn't find errors for '{}'" ,
336343 test_fn
337344 ) ;
345+
346+ // But not subset errors...
347+ assert ! ( location_insensitive. subset_errors. is_empty( ) ) ;
348+ assert ! ( naive. subset_errors. is_empty( ) ) ;
349+ assert ! ( opt. subset_errors. is_empty( ) ) ;
338350 }
339351}
340352
@@ -584,7 +596,10 @@ fn illegal_subset_error() {
584596
585597 // and in the location-insensitive results as well
586598 assert ! ( location_insensitive_checker_for( program)
587- . location_insensitive_subset_error_exists( "'b" , "'a" , ) ) ;
599+ . location_insensitive_subset_error_exists( "'b" , "'a" ) ) ;
600+
601+ // and finally the optimized-variant results should be the same as the naive ones
602+ assert_checkers_match ( & checker, & opt_checker_for ( program) ) ;
588603}
589604
590605/// This is the same test as the `illegal_subset_error` one, but specifies the `'b: 'a` subset
@@ -613,6 +628,7 @@ fn known_placeholder_origin_subset() {
613628 location_insensitive_checker_for( program) . subset_errors_count( ) ,
614629 0
615630 ) ;
631+ assert_checkers_match ( & checker, & opt_checker_for ( program) ) ;
616632}
617633
618634/// This test ensures `known_subset`s are handled transitively: a known subset `'a: 'c` should be
@@ -644,6 +660,7 @@ fn transitive_known_subset() {
644660 location_insensitive_checker_for( program) . subset_errors_count( ) ,
645661 0
646662 ) ;
663+ assert_checkers_match ( & checker, & opt_checker_for ( program) ) ;
647664}
648665
649666/// Even if `'a: 'b` is known, `'a`'s placeholder loan can flow into `'b''s supersets,
@@ -680,7 +697,10 @@ fn transitive_illegal_subset_error() {
680697 assert ! ( checker. subset_error_exists( "'b" , "'c" , "\" Mid(B0[1])\" " ) ) ;
681698 assert ! ( checker. subset_error_exists( "'a" , "'c" , "\" Mid(B0[1])\" " ) ) ;
682699
683- // And similarly in the location-insensitive analysis.
700+ // The optimized analysis results should be the same as the naive one's.
701+ assert_checkers_match ( & checker, & opt_checker_for ( program) ) ;
702+
703+ // And the location-insensitive analysis should have the same errors, without a location.
684704 let mut checker = location_insensitive_checker_for ( program) ;
685705 assert_eq ! ( checker. subset_errors_count( ) , 2 ) ;
686706 assert ! ( checker. location_insensitive_subset_error_exists( "'b" , "'c" ) ) ;
@@ -708,6 +728,10 @@ fn successes_in_subset_relations_dataset() {
708728 let insensitive = Output :: compute ( & facts, Algorithm :: LocationInsensitive , true ) ;
709729 assert ! ( insensitive. errors. is_empty( ) ) ;
710730 assert ! ( insensitive. subset_errors. is_empty( ) ) ;
731+
732+ let opt = Output :: compute ( & facts, Algorithm :: DatafrogOpt , true ) ;
733+ assert ! ( opt. errors. is_empty( ) ) ;
734+ assert ! ( opt. subset_errors. is_empty( ) ) ;
711735 }
712736}
713737
@@ -756,6 +780,10 @@ fn errors_in_subset_relations_dataset() {
756780 let insensitive_subset_errors = insensitive. subset_errors . values ( ) . next ( ) . unwrap ( ) ;
757781 assert_eq ! ( insensitive_subset_errors. len( ) , 1 ) ;
758782 assert ! ( insensitive_subset_errors. contains( & expected_subset_error) ) ;
783+
784+ // And the optimized analysis results should be the same as the naive one's.
785+ let opt = Output :: compute ( & facts, Algorithm :: Naive , true ) ;
786+ assert_outputs_match ( & naive, & opt) ;
759787}
760788
761789// There's only a single successful test in the dataset for now, but the structure of this test
@@ -783,6 +811,11 @@ fn successes_in_move_errors_dataset() {
783811 assert ! ( insensitive. errors. is_empty( ) ) ;
784812 assert ! ( insensitive. subset_errors. is_empty( ) ) ;
785813 assert ! ( insensitive. move_errors. is_empty( ) ) ;
814+
815+ let opt = Output :: compute ( & facts, Algorithm :: DatafrogOpt , true ) ;
816+ assert ! ( opt. errors. is_empty( ) ) ;
817+ assert ! ( opt. subset_errors. is_empty( ) ) ;
818+ assert ! ( opt. move_errors. is_empty( ) ) ;
786819 }
787820}
788821
0 commit comments