Skip to content

Commit

Permalink
call check_proof_attribute for contract harnesses
Browse files Browse the repository at this point in the history
  • Loading branch information
carolynzech committed Sep 17, 2024
1 parent dba8f39 commit 80a4914
Show file tree
Hide file tree
Showing 5 changed files with 65 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
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 80a4914

Please sign in to comment.