Skip to content

Commit b4657d4

Browse files
danielsntedinski
authored andcommitted
Add an __VERIFIER_expected_fail() intrinsic, and use it in a test (rust-lang#229)
* Add an __VERIFIER_expected_fail() intrinsic, and use it in a test * PR comments
1 parent 3467030 commit b4657d4

File tree

3 files changed

+46
-1
lines changed

3 files changed

+46
-1
lines changed

compiler/rustc_codegen_llvm/src/gotoc/hooks.rs

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,46 @@ fn name_is(tcx: TyCtxt<'tcx>, instance: Instance<'tcx>, expected: &str) -> bool
7474
false
7575
}
7676

77+
struct ExpectFail;
78+
impl<'tcx> GotocHook<'tcx> for ExpectFail {
79+
fn hook_applies(&self, tcx: TyCtxt<'tcx>, instance: Instance<'tcx>) -> bool {
80+
let def_path = tcx.def_path(instance.def.def_id());
81+
if let Some(data) = def_path.data.last() {
82+
match data.data.name() {
83+
DefPathDataName::Named(name) => {
84+
return name.to_string().starts_with("__VERIFIER_expect_fail");
85+
}
86+
DefPathDataName::Anon { .. } => (),
87+
}
88+
}
89+
false
90+
}
91+
92+
fn handle(
93+
&self,
94+
tcx: &mut GotocCtx<'tcx>,
95+
_instance: Instance<'tcx>,
96+
mut fargs: Vec<Expr>,
97+
_assign_to: Option<Place<'tcx>>,
98+
target: Option<BasicBlock>,
99+
span: Option<Span>,
100+
) -> Stmt {
101+
assert_eq!(fargs.len(), 2);
102+
let target = target.unwrap();
103+
let cond = fargs.remove(0).cast_to(Type::bool());
104+
//TODO: actually use the error message passed by the user.
105+
let msg = "EXPECTED FAIL";
106+
let loc = tcx.codegen_span_option2(span);
107+
Stmt::block(
108+
vec![
109+
Stmt::assert(cond, msg, loc.clone()),
110+
Stmt::goto(tcx.current_fn().find_label(&target), loc.clone()),
111+
],
112+
loc,
113+
)
114+
}
115+
}
116+
77117
struct Assume;
78118
impl<'tcx> GotocHook<'tcx> for Assume {
79119
fn hook_applies(&self, tcx: TyCtxt<'tcx>, instance: Instance<'tcx>) -> bool {
@@ -616,6 +656,7 @@ pub fn type_and_fn_hooks<'tcx>() -> (GotocTypeHooks<'tcx>, GotocHooks<'tcx>) {
616656
hooks: vec![
617657
Rc::new(Panic), //Must go first, so it overrides Nevers
618658
Rc::new(Assume),
659+
Rc::new(ExpectFail),
619660
Rc::new(Intrinsic),
620661
Rc::new(MemReplace),
621662
Rc::new(MemSwap),

src/test/cbmc/Assume/main_fail.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,5 +6,5 @@ include!("../../rmc-prelude.rs");
66
fn main() {
77
let i: i32 = __nondet();
88
__VERIFIER_assume(i < 10);
9-
assert!(i > 20);
9+
__VERIFIER_expect_fail(i > 20, "Blocked by assumption above.");
1010
}

src/test/rmc-prelude.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,10 @@ fn __VERIFIER_assume(cond: bool) {
55
unimplemented!()
66
}
77

8+
fn __VERIFIER_expect_fail(cond: bool) {
9+
unimplemented!()
10+
}
11+
812
fn __nondet<T>() -> T {
913
unimplemented!()
1014
}

0 commit comments

Comments
 (0)