Skip to content

Commit 0a642f6

Browse files
celinvaltedinski
authored andcommitted
Add warning for unsupported constructs (rust-lang#1095)
1 parent abdb9a0 commit 0a642f6

File tree

5 files changed

+44
-9
lines changed

5 files changed

+44
-9
lines changed

kani-compiler/src/codegen_cprover_gotoc/compiler_interface.rs

+25-1
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
66
use crate::codegen_cprover_gotoc::GotocCtx;
77
use bitflags::_core::any::Any;
8-
use cbmc::goto_program::symtab_transformer;
8+
use cbmc::goto_program::{symtab_transformer, Location};
99
use cbmc::InternedString;
1010
use kani_metadata::KaniMetadata;
1111
use kani_queries::{QueryDb, UserInput};
@@ -121,6 +121,9 @@ impl CodegenBackend for GotocCodegenBackend {
121121
}
122122
}
123123

124+
// Print compilation report.
125+
print_report(&c, tcx);
126+
124127
// perform post-processing symbol table passes
125128
let passes = self.queries.get_symbol_table_passes();
126129
let symtab = symtab_transformer::do_passes(c.symbol_table, &passes);
@@ -258,3 +261,24 @@ where
258261
serde_json::to_writer(writer, &source).unwrap();
259262
}
260263
}
264+
265+
/// Prints a report at the end of the compilation.
266+
fn print_report<'tcx>(ctx: &GotocCtx, tcx: TyCtxt<'tcx>) {
267+
// Print all unsupported constructs.
268+
if !ctx.unsupported_constructs.is_empty() {
269+
// Sort alphabetically.
270+
let unsupported: BTreeMap<String, &Vec<Location>> = ctx
271+
.unsupported_constructs
272+
.iter()
273+
.map(|(key, val)| (key.map(|s| String::from(s)), val))
274+
.collect();
275+
let mut msg = String::from("Found the following unsupported constructs:\n");
276+
unsupported.iter().for_each(|(construct, locations)| {
277+
msg += &format!(" - {} ({})\n", construct, locations.len())
278+
});
279+
msg += "\nVerification will fail if one or more of these constructs is reachable.";
280+
msg += "\nSee https://model-checking.github.io/kani/rust-feature-support.html for more \
281+
details.";
282+
tcx.sess.warn(&msg);
283+
}
284+
}

kani-compiler/src/codegen_cprover_gotoc/context/goto_ctx.rs

+3
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,8 @@ pub struct GotocCtx<'tcx> {
6161
pub proof_harnesses: Vec<HarnessMetadata>,
6262
/// a global counter for generating unique IDs for checks
6363
pub global_checks_count: u64,
64+
/// A map of unsupported constructs that were found while codegen
65+
pub unsupported_constructs: FxHashMap<InternedString, Vec<Location>>,
6466
}
6567

6668
/// Constructor
@@ -83,6 +85,7 @@ impl<'tcx> GotocCtx<'tcx> {
8385
type_map: FxHashMap::default(),
8486
proof_harnesses: vec![],
8587
global_checks_count: 0,
88+
unsupported_constructs: FxHashMap::default(),
8689
}
8790
}
8891
}

kani-compiler/src/codegen_cprover_gotoc/utils/utils.rs

+9-7
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,11 @@
33
use super::super::codegen::TypeExt;
44
use crate::codegen_cprover_gotoc::codegen::PropertyClass;
55
use crate::codegen_cprover_gotoc::GotocCtx;
6-
use cbmc::btree_string_map;
76
use cbmc::goto_program::{Expr, ExprValue, Location, Stmt, SymbolTable, Type};
7+
use cbmc::{btree_string_map, InternedString};
88
use rustc_middle::ty::layout::LayoutOf;
99
use rustc_middle::ty::Ty;
10-
use tracing::warn;
10+
use tracing::debug;
1111

1212
// Should move into rvalue
1313
//make this a member function
@@ -46,18 +46,20 @@ impl<'tcx> GotocCtx<'tcx> {
4646
/// This means that if the unimplemented feature is dynamically used by the code being verified, we will see an assertion failure.
4747
/// If it is not used, we the assertion will pass.
4848
/// This allows us to continue to make progress parsing rust code, while remaining sound (thanks to the `assert(false)`)
49-
///
50-
/// TODO: https://github.com/model-checking/kani/issues/8 assume the required validity constraints for the nondet return
51-
/// TODO: https://github.com/model-checking/kani/issues/9 Have a parameter that decides whether to `assume(0)` to block further traces or not
5249
pub fn codegen_unimplemented(
5350
&mut self,
5451
operation_name: &str,
5552
t: Type,
5653
loc: Location,
5754
url: &str,
5855
) -> Expr {
59-
// TODO: This should print a more user friendly warning format.
60-
warn!("codegen_unimplemented: {} at {}", operation_name, loc.short_string());
56+
// Save this occurrence so we can emit a warning in the compilation report.
57+
debug!("codegen_unimplemented: {} at {}", operation_name, loc.short_string());
58+
let key: InternedString = operation_name.into();
59+
if !self.unsupported_constructs.contains_key(&key) {
60+
self.unsupported_constructs.insert(key, Vec::new());
61+
}
62+
self.unsupported_constructs.get_mut(&key).unwrap().push(loc.clone());
6163

6264
let body = vec![
6365
// Assert false to alert the user that there is a path that uses an unimplemented feature.

tests/kani/Options/check_tests.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ mod test {
2020
#[test]
2121
#[kani::proof]
2222
fn test_harness() {
23-
let input: i32 = kani::nondet();
23+
let input: i32 = kani::any();
2424
kani::assume(input > 1);
2525
fn_under_verification(input);
2626
}
Original file line numberDiff line numberDiff line change
@@ -1 +1,7 @@
1+
warning: Found the following unsupported constructs:\
2+
Rvalue::ThreadLocalRef\
3+
\
4+
Verification will fail if one or more of these constructs is reachable.\
5+
See https://model-checking.github.io/kani/rust-feature-support.html for more details.
6+
17
Failed Checks: Rvalue::ThreadLocalRef is not currently supported by Kani.

0 commit comments

Comments
 (0)