Skip to content

Commit

Permalink
Merge branch 'main' into llbc4
Browse files Browse the repository at this point in the history
  • Loading branch information
zhassan-aws committed Sep 19, 2024
2 parents 08134b2 + 27cee8b commit 9dd16d5
Show file tree
Hide file tree
Showing 7 changed files with 89 additions and 8 deletions.
27 changes: 21 additions & 6 deletions kani-compiler/src/kani_middle/attributes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -358,7 +358,7 @@ impl<'tcx> KaniAttributes<'tcx> {
);
}
expect_single(self.tcx, kind, &attrs);
attrs.iter().for_each(|attr| self.check_proof_attribute(attr))
attrs.iter().for_each(|attr| self.check_proof_attribute(kind, attr))
}
KaniAttributeKind::Unstable => attrs.iter().for_each(|attr| {
let _ = UnstableAttribute::try_from(*attr).map_err(|err| err.report(self.tcx));
Expand All @@ -370,6 +370,7 @@ impl<'tcx> KaniAttributes<'tcx> {
);
}
expect_single(self.tcx, kind, &attrs);
attrs.iter().for_each(|attr| self.check_proof_attribute(kind, attr))
}
KaniAttributeKind::StubVerified => {
expect_single(self.tcx, kind, &attrs);
Expand Down Expand Up @@ -583,15 +584,29 @@ impl<'tcx> KaniAttributes<'tcx> {
}

/// Check that if this item is tagged with a proof_attribute, it is a valid harness.
fn check_proof_attribute(&self, proof_attribute: &Attribute) {
fn check_proof_attribute(&self, kind: KaniAttributeKind, proof_attribute: &Attribute) {
let span = proof_attribute.span;
let tcx = self.tcx;
expect_no_args(tcx, KaniAttributeKind::Proof, proof_attribute);
if let KaniAttributeKind::Proof = kind {
expect_no_args(tcx, kind, proof_attribute);
}

if tcx.def_kind(self.item) != DefKind::Fn {
tcx.dcx().span_err(span, "the `proof` attribute can only be applied to functions");
tcx.dcx().span_err(
span,
format!(
"the '#[kani::{}]' attribute can only be applied to functions",
kind.as_ref()
),
);
} else if tcx.generics_of(self.item).requires_monomorphization(tcx) {
tcx.dcx()
.span_err(span, "the `proof` attribute cannot be applied to generic functions");
tcx.dcx().span_err(
span,
format!(
"the '#[kani::{}]' attribute cannot be applied to generic functions",
kind.as_ref()
),
);
} else {
let instance = Instance::mono(tcx, self.item);
if !super::fn_abi(tcx, instance).args.is_empty() {
Expand Down
11 changes: 11 additions & 0 deletions tests/ui/function-contracts/non_bool_contracts.expected
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
|
| #[kani::requires(a + b)]
| -----------------^^^^^--
| | |
| | expected `bool`, found `u64`
| arguments to this function are incorrect
|

|
| #[kani::ensures(|result| a % *result && b % *result == 0 && *result != 0)]
| ^^^^^^^^^^^ expected `bool`, found `u64`
13 changes: 13 additions & 0 deletions tests/ui/function-contracts/non_bool_contracts.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
// Copyright Kani Contributors
// SPDX-License-Identifier: Apache-2.0 OR MIT
// kani-flags: -Zfunction-contracts

// This tests that Kani reports the "ideal" error message when contracts are non-boolean expressions
// By "ideal," we mean that the error spans are as narrow as possible
// (c.f. https://github.com/model-checking/kani/issues/3009)

#[kani::requires(a + b)]
#[kani::ensures(|result| a % *result && b % *result == 0 && *result != 0)]
fn gcd(a: u64, b: u64) -> u64 {
0
}
17 changes: 17 additions & 0 deletions tests/ui/invalid-contract-harness/expected
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
error: only one '#[kani::proof_for_contract]' attribute is allowed per harness\
invalid.rs:\
|\
| #[kani::proof_for_contract(foo)]\
| ^^^^^^^^^^^^^^

error: functions used as harnesses cannot have any arguments\
invalid.rs:\
|\
| #[kani::proof_for_contract(foo)]
| ^^^^^^^^^^^^^^

error: the '#[kani::proof_for_contract]' attribute cannot be applied to generic functions\
invalid.rs:\
|\
| #[kani::proof_for_contract(foo)]\
| ^^^^^^^^^^^^^^
25 changes: 25 additions & 0 deletions tests/ui/invalid-contract-harness/invalid.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
// Copyright Kani Contributors
// SPDX-License-Identifier: Apache-2.0 OR MIT
// kani-flags: -Zfunction-contracts

// This test is to check Kani's error handling of invalid usages of the `proof_for_contract` harness.
// We also ensure that all errors and warnings are printed in one compilation.

#[kani::requires(true)]
fn foo() {}

#[kani::proof_for_contract(foo)]
#[kani::proof_for_contract(foo)]
fn multiple_proof_annotations() {
foo();
}

#[kani::proof_for_contract(foo)]
fn proof_with_arg(arg: bool) {
foo();
}

#[kani::proof_for_contract(foo)]
fn generic_harness<T: Default>() {
foo();
}
2 changes: 1 addition & 1 deletion tests/ui/invalid-harnesses/expected
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ invalid.rs:\
| #[kani::proof]
| ^^^^^^^^^^^^^^

error: the `proof` attribute cannot be applied to generic functions\
error: the '#[kani::proof]' attribute cannot be applied to generic functions\
invalid.rs:\
|\
| #[kani::proof]\
Expand Down
2 changes: 1 addition & 1 deletion tests/ui/mir-linker/generic-harness/expected
Original file line number Diff line number Diff line change
@@ -1 +1 @@
error: the `proof` attribute cannot be applied to generic functions
error: the '#[kani::proof]' attribute cannot be applied to generic functions

0 comments on commit 9dd16d5

Please sign in to comment.