@@ -231,15 +231,26 @@ fn format_item_terse(_item: &ParserItem) -> Option<String> {
231231/// This could be split into two functions for clarity, but at the moment
232232/// it uses the flag `show_checks` which depends on the output format.
233233///
234+ /// This function reports the results of normal checks (e.g. assertions and
235+ /// arithmetic overflow checks) and cover properties (specified using the
236+ /// `kani::cover` macro) separately. Cover properties currently do not impact
237+ /// the overall verification success or failure.
238+ ///
234239/// TODO: We could `write!` to `result_str` instead
235240/// <https://github.com/model-checking/kani/issues/1480>
236241pub fn format_result ( properties : & Vec < Property > , show_checks : bool ) -> String {
237242 let mut result_str = String :: new ( ) ;
238- let mut number_tests_failed = 0 ;
239- let mut number_tests_unreachable = 0 ;
240- let mut number_tests_undetermined = 0 ;
243+ let mut number_checks_failed = 0 ;
244+ let mut number_checks_unreachable = 0 ;
245+ let mut number_checks_undetermined = 0 ;
241246 let mut failed_tests: Vec < & Property > = vec ! [ ] ;
242247
248+ // cover checks
249+ let mut number_covers_satisfied = 0 ;
250+ let mut number_covers_undetermined = 0 ;
251+ let mut number_covers_unreachable = 0 ;
252+ let mut number_covers_unsatisfiable = 0 ;
253+
243254 let mut index = 1 ;
244255
245256 if show_checks {
@@ -254,14 +265,30 @@ pub fn format_result(properties: &Vec<Property>, show_checks: bool) -> String {
254265
255266 match status {
256267 CheckStatus :: Failure => {
257- number_tests_failed += 1 ;
268+ number_checks_failed += 1 ;
258269 failed_tests. push ( prop) ;
259270 }
260271 CheckStatus :: Undetermined => {
261- number_tests_undetermined += 1 ;
272+ if prop. is_cover_property ( ) {
273+ number_covers_undetermined += 1 ;
274+ } else {
275+ number_checks_undetermined += 1 ;
276+ }
262277 }
263278 CheckStatus :: Unreachable => {
264- number_tests_unreachable += 1 ;
279+ if prop. is_cover_property ( ) {
280+ number_covers_unreachable += 1 ;
281+ } else {
282+ number_checks_unreachable += 1 ;
283+ }
284+ }
285+ CheckStatus :: Satisfied => {
286+ assert ! ( prop. is_cover_property( ) ) ;
287+ number_covers_satisfied += 1 ;
288+ }
289+ CheckStatus :: Unsatisfiable => {
290+ assert ! ( prop. is_cover_property( ) ) ;
291+ number_covers_unsatisfiable += 1 ;
265292 }
266293 _ => ( ) ,
267294 }
@@ -291,16 +318,23 @@ pub fn format_result(properties: &Vec<Property>, show_checks: bool) -> String {
291318 result_str. push_str ( "\n VERIFICATION RESULT:" ) ;
292319 }
293320
294- let summary = format ! ( "\n ** {number_tests_failed} of {} failed" , properties. len( ) ) ;
321+ let number_cover_properties = number_covers_satisfied
322+ + number_covers_unreachable
323+ + number_covers_unsatisfiable
324+ + number_covers_undetermined;
325+
326+ let number_properties = properties. len ( ) - number_cover_properties;
327+
328+ let summary = format ! ( "\n ** {number_checks_failed} of {} failed" , number_properties) ;
295329 result_str. push_str ( & summary) ;
296330
297331 let mut other_status = Vec :: < String > :: new ( ) ;
298- if number_tests_undetermined > 0 {
299- let undetermined_str = format ! ( "{number_tests_undetermined } undetermined" ) ;
332+ if number_checks_undetermined > 0 {
333+ let undetermined_str = format ! ( "{number_checks_undetermined } undetermined" ) ;
300334 other_status. push ( undetermined_str) ;
301335 }
302- if number_tests_unreachable > 0 {
303- let unreachable_str = format ! ( "{number_tests_unreachable } unreachable" ) ;
336+ if number_checks_unreachable > 0 {
337+ let unreachable_str = format ! ( "{number_checks_unreachable } unreachable" ) ;
304338 other_status. push ( unreachable_str) ;
305339 }
306340 if !other_status. is_empty ( ) {
@@ -310,13 +344,38 @@ pub fn format_result(properties: &Vec<Property>, show_checks: bool) -> String {
310344 }
311345 result_str. push ( '\n' ) ;
312346
347+ if number_cover_properties > 0 {
348+ // Print a summary line for cover properties
349+ let summary = format ! (
350+ "\n ** {number_covers_satisfied} of {} cover properties satisfied" ,
351+ number_cover_properties
352+ ) ;
353+ result_str. push_str ( & summary) ;
354+ let mut other_status = Vec :: < String > :: new ( ) ;
355+ if number_covers_undetermined > 0 {
356+ let undetermined_str = format ! ( "{number_covers_undetermined} undetermined" ) ;
357+ other_status. push ( undetermined_str) ;
358+ }
359+ if number_covers_unreachable > 0 {
360+ let unreachable_str = format ! ( "{number_covers_unreachable} unreachable" ) ;
361+ other_status. push ( unreachable_str) ;
362+ }
363+ if !other_status. is_empty ( ) {
364+ result_str. push_str ( " (" ) ;
365+ result_str. push_str ( & other_status. join ( "," ) ) ;
366+ result_str. push ( ')' ) ;
367+ }
368+ result_str. push ( '\n' ) ;
369+ result_str. push ( '\n' ) ;
370+ }
371+
313372 for prop in failed_tests {
314373 let failure_message = build_failure_message ( prop. description . clone ( ) , & prop. trace . clone ( ) ) ;
315374 result_str. push_str ( & failure_message) ;
316375 }
317376
318377 let verification_result =
319- if number_tests_failed == 0 { style ( "SUCCESSFUL" ) . green ( ) } else { style ( "FAILED" ) . red ( ) } ;
378+ if number_checks_failed == 0 { style ( "SUCCESSFUL" ) . green ( ) } else { style ( "FAILED" ) . red ( ) } ;
320379 let overall_result = format ! ( "\n VERIFICATION:- {verification_result}\n " ) ;
321380 result_str. push_str ( & overall_result) ;
322381
@@ -413,7 +472,7 @@ pub fn postprocess_result(properties: Vec<Property>, extra_ptr_checks: bool) ->
413472 let ( properties_without_reachs, reach_checks) = filter_reach_checks ( properties_with_undefined) ;
414473 // Filter out successful sanity checks introduced during compilation
415474 let properties_without_sanity_checks = filter_sanity_checks ( properties_without_reachs) ;
416- // Annotate properties with the results from reachability checks
475+ // Annotate properties with the results of reachability checks
417476 let properties_annotated =
418477 annotate_properties_with_reach_results ( properties_without_sanity_checks, reach_checks) ;
419478 // Remove reachability check IDs from regular property descriptions
@@ -429,7 +488,9 @@ pub fn postprocess_result(properties: Vec<Property>, extra_ptr_checks: bool) ->
429488 || has_failed_unwinding_asserts
430489 || has_reachable_undefined_functions;
431490
432- update_properties_with_reach_status ( properties_filtered, has_fundamental_failures)
491+ let updated_properties =
492+ update_properties_with_reach_status ( properties_filtered, has_fundamental_failures) ;
493+ update_results_of_cover_checks ( updated_properties)
433494}
434495
435496/// Determines if there is property with status `FAILURE` and the given description
@@ -495,7 +556,7 @@ fn get_readable_description(property: &Property) -> String {
495556 original
496557}
497558
498- /// Performs a last pass to update all properties as follows:
559+ /// Performs a pass to update all properties as follows:
499560/// 1. Descriptions are replaced with more readable ones.
500561/// 2. If there were failures that made the verification result unreliable
501562/// (e.g., a reachable unsupported construct), changes all `SUCCESS` results
@@ -525,6 +586,23 @@ fn update_properties_with_reach_status(
525586 properties
526587}
527588
589+ /// Update the results of cover properties.
590+ /// We encode cover(cond) as assert(!cond), so if the assertion
591+ /// fails, then the cover property is satisfied and vice versa.
592+ /// - SUCCESS -> UNSATISFIABLE
593+ /// - FAILURE -> SATISFIED
594+ fn update_results_of_cover_checks ( mut properties : Vec < Property > ) -> Vec < Property > {
595+ for prop in properties. iter_mut ( ) {
596+ if prop. is_cover_property ( ) {
597+ if prop. status == CheckStatus :: Success {
598+ prop. status = CheckStatus :: Unsatisfiable ;
599+ } else if prop. status == CheckStatus :: Failure {
600+ prop. status = CheckStatus :: Satisfied ;
601+ }
602+ }
603+ }
604+ properties
605+ }
528606/// Some Kani-generated asserts have a unique ID in their description of the form:
529607/// ```text
530608/// [KANI_CHECK_ID_<crate-fn-name>_<index>]
0 commit comments