#![feature(rustc_private)]
#[macro_use]
mod common;
use common::*;
const STRUCT: &str = verus_code_str! {
#[derive(PartialEq, Eq)]
struct Bike {
hard_tail: bool,
}
};
test_verify_one_file! {
#[test] test_impl_1 STRUCT.to_string() + verus_code_str! {
impl Bike {
pub closed spec fn is_hard_tail(&self) -> bool {
self.hard_tail
}
}
fn test_impl_1(b: Bike)
requires b.is_hard_tail()
{
assert(b.hard_tail);
}
fn test_impl_2(b: &Bike)
requires b.is_hard_tail()
{
assert(b.hard_tail);
}
} => Ok(())
}
test_verify_one_file! {
#[test] test_impl_no_self STRUCT.to_string() + verus_code_str! {
impl Bike {
fn new() -> Bike {
ensures(|result: Bike| result.hard_tail);
Bike { hard_tail: true }
}
}
} => Ok(())
}
test_verify_one_file! {
#[test] test_impl_no_self_fail_pub_private STRUCT.to_string() + verus_code_str! {
impl Bike {
pub fn new() -> Bike {
ensures(|result: Bike| result.hard_tail);
Bike { hard_tail: true }
}
}
} => Err(err) => assert_vir_error_msg(err, "disallowed: field expression for a non-visible datatype")
}
test_verify_one_file! {
#[test] test_impl_mod_1 verus_code! {
mod M1 {
use verus_builtin::*;
#[derive(PartialEq, Eq)]
pub struct Bike {
pub hard_tail: bool,
}
impl Bike {
pub open spec fn is_hard_tail(&self) -> bool {
self.hard_tail
}
pub fn new() -> Bike {
ensures(|result: Bike| result.hard_tail);
Bike { hard_tail: true }
}
}
}
mod M2 {
use super::M1::Bike;
use verus_builtin::*;
fn test_impl_1(b: Bike)
requires b.is_hard_tail()
{
assert(b.is_hard_tail());
}
fn test_impl_2() {
let b = Bike::new();
assert(b.is_hard_tail());
}
}
} => Ok(())
}
test_verify_one_file! {
#[test] test_impl_mod_priv_field verus_code! {
mod M1 {
#[derive(PartialEq, Eq)]
pub struct Bike {
hard_tail: bool,
}
impl Bike {
pub closed spec fn is_hard_tail(&self) -> bool {
self.hard_tail
}
}
}
mod M2 {
use super::M1::Bike;
use verus_builtin::*;
fn test_impl_1(b: Bike)
requires b.is_hard_tail()
{
assert(b.is_hard_tail());
}
}
} => Ok(())
}
const IMPL_GENERIC_SHARED: &str = verus_code_str! {
#[derive(PartialEq, Eq)]
struct Wrapper {
v: A,
}
impl Wrapper {
pub closed spec fn take(self) -> A {
self.v
}
}
};
test_verify_one_file! {
#[test] test_impl_generic_pass IMPL_GENERIC_SHARED.to_string() + verus_code_str! {
proof fn test_impl_1(a: int) {
let w = Wrapper { v: a };
assert(w.take() == a);
}
} => Ok(())
}
test_verify_one_file! {
#[test] test_impl_generic_fail IMPL_GENERIC_SHARED.to_string() + verus_code_str! {
proof fn test_impl_1(a: int) {
let w = Wrapper { v: a };
assert(w.take() != a); // FAILS
}
} => Err(err) => assert_one_fails(err)
}
test_verify_one_file! {
#[test] test_impl_generic_param verus_code! {
#[derive(PartialEq, Eq, Structural)]
struct Two {
a: A,
b: B,
}
#[derive(PartialEq, Eq)]
struct Wrapper {
v: A,
}
impl Wrapper {
pub closed spec fn take(self, b: B) -> Two {
Two { a: self.v, b: b }
}
}
proof fn test_impl_1(a: int) {
let w = Wrapper { v: a };
assert(w.take(12i32) == Two { a: a, b: 12i32 });
}
} => Ok(())
}
test_verify_one_file! {
#[test] test_impl_with_self verus_code! {
#[derive(PartialEq, Eq, Structural)]
struct Bike {
hard_tail: bool,
}
impl Bike {
spec fn id(self) -> Self {
self
}
}
} => Ok(())
}
test_verify_one_file! {
#[test] test_illegal_trait_impl verus_code! {
#[verifier::external]
trait T {
fn f() -> bool;
}
struct S;
impl T for S {
spec fn f() -> bool {
true
}
}
} => Err(err) => assert_vir_error_msg(err, "function for external trait must have mode `exec`")
}
test_verify_one_file! {
#[test] test_illegal_trait_impl_2 verus_code! {
struct V {
}
impl std::ops::Index for V {
type Output = bool;
fn index(&self, #[verifier::spec]idx: usize) -> &bool { &true }
}
} => Err(err) => assert_vir_error_msg(err, "function for external trait must have all parameters have mode `exec`")
}
test_verify_one_file! {
#[test] test_generic_struct verus_code! {
#[derive(PartialEq, Eq)]
struct TemplateCar {
four_doors: bool,
passengers: u64,
the_v: V,
}
impl TemplateCar {
fn template_new(v: V) -> (result: TemplateCar)
ensures
equal(result.passengers, 205),
equal(result.the_v, v),
{
TemplateCar:: { four_doors: false, passengers: 205, the_v: v }
}
fn template_get_passengers(&self) -> (result: u64)
ensures result == self.passengers
{
self.passengers
}
fn template_get_v(self) -> (result: V)
ensures equal(result, self.the_v)
{
self.the_v
}
}
fn test1() {
let c3 = TemplateCar::::template_new(5);
let p3 = c3.template_get_passengers();
assert(p3 == 205);
let v = c3.template_get_v();
assert(v == 5);
}
} => Ok(())
}
test_verify_one_file! {
#[ignore] #[test] test_erased_assoc_type_param verus_code! {
struct Foo {
v: V
}
impl Foo {
fn bar bool>(f: Ghost, v: Ghost) -> Ghost {
Ghost(f.requires((v,)))
}
fn bar2 bool>(self, f: Ghost) -> Ghost {
Ghost(f.requires((self.v,)))
}
}
fn test() {
let x: Ghost = Ghost(0u64);
let z = |y: u64| true;
Foo::::bar(Ghost(z), x);
let f = Foo:: { v: 17 };
let w = |y: u64| true;
let b: Ghost = f.bar2(Ghost(w));
}
} => Ok(())
}
test_verify_one_file! {
#[test] test_resolve_self_ty verus_code! {
struct Foo {
x: V,
}
impl Foo {
fn bar(self) -> (s: Self)
ensures equal(self, s)
{
self
}
fn bar2(self) -> (s: Self)
ensures equal(self, s)
{
Self::bar(self)
}
}
} => Ok(())
}
test_verify_one_file! {
#[test] unsafe_impl_fail_send verus_code! {
struct Foo {
x: u32,
}
unsafe impl Send for Foo { }
} => Err(e) => assert_vir_error_msg(e, "unsafe impl for `Send` is not allowed")
}
test_verify_one_file! {
#[test] unsafe_impl_fail_sync verus_code! {
struct Foo {
x: u32,
}
unsafe impl Sync for Foo { }
} => Err(e) => assert_vir_error_msg(e, "unsafe impl for `Sync` is not allowed")
}