-
Notifications
You must be signed in to change notification settings - Fork 109
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
New failure on small linked list example #598
Comments
Interestingly, if one removes the
|
Thanks for the speedy response! As far as I can tell this doesn't seem to be an example in which triggering unfoldings of function definitions should be particularly problematic; the convenient strategy from Viper only makes a difference over limited functions (which should still be working) if one needs unfolding to more than depth 1, and that doesn't seem to arise in this example. |
After a bit of playing around with the Viper I've reduced the example to: domain Snap$Option {
function List_next_disc(self: Snap$Option): Bool
function Snap_None(): Snap$Option
function Snap_Some(_0: Snap$List): Snap$Option
function snap_Option_Some(self: Snap$Option): Snap$List
axiom Snap$Option$0$discriminant_axiom {
!List_next_disc(Snap_None())
}
axiom Snap$Option$1$discriminant_axiom {
(forall _0: Snap$List :: { Snap_Some(_0) } List_next_disc(Snap_Some(_0)))
}
axiom Snap$Option$1$field$f$0$axiom {
(forall _0: Snap$List :: { snap_Option_Some(Snap_Some(_0)) } snap_Option_Some(Snap_Some(_0)) == _0)
}
}
domain Snap$List {
function Snap_List(_0: Int, _1: Snap$Option): Snap$List
function snap_List_next(self: Snap$List): Snap$Option
axiom Snap$List$0$field$next$axiom {
(forall _0: Int, _1: Snap$Option :: { snap_List_next(Snap_List(_0, _1)) } snap_List_next(Snap_List(_0, _1)) == _1)
}
}
field is_some: Bool
field enum_Some: Ref
field next: Ref
field val: Int
function get_is_some(self: Ref): Bool
requires acc(Option(self), read())
ensures List_next_disc(to_snap_OptBoxList(self)) == result
{
unfolding acc(Option(self), read()) in self.is_some
}
function len(_1: Snap$List): Int
{
!List_next_disc(snap_List_next(_1)) ? 1 : 1 + len(snap_Option_Some(snap_List_next(_1)))
}
function to_snap_OptBoxList(self: Ref): Snap$Option
requires acc(Option(self), read())
{
unfolding acc(Option(self), read()) in (self.is_some ? Snap_Some(to_snap_List(self.enum_Some)) : Snap_None())
}
function to_snap_List(self: Ref): Snap$List
requires acc(List(self), read())
{
unfolding acc(List(self), read()) in Snap_List(self.val, to_snap_OptBoxList(self.next))
}
function read(): Perm
ensures none < result
ensures result < write
predicate Option(self: Ref) {
acc(self.is_some, write) && acc(self.enum_Some, write) && (self.is_some ==> acc(List(self.enum_Some), write))
}
predicate List(self: Ref) {
acc(self.val, write) && acc(self.next, write) && acc(Option(self.next), write)
}
method m_push(l: Ref) returns ()
requires acc(List(l), write) && unfolding acc(List(l), write) in !get_is_some(l.next)
{
var l2: Ref
inhale acc(Option(l2), write)
inhale get_is_some(l2)
unfold acc(Option(l2), write)
inhale acc(List(l2.enum_Some), write)
unfold acc(List(l2.enum_Some), write)
inhale acc(Option(l2.enum_Some.next), write)
inhale !get_is_some(l2.enum_Some.next)
fold acc(List(l2.enum_Some), write)
//assert len(to_snap_List(l2.enum_Some)) == 1
fold acc(Option(l2), write)
unfold acc(List(l), write)
l.next := l2
fold acc(List(l), write)
assert len(to_snap_List(l)) == old(len(to_snap_List(l))) + 1
} This fails on the final |
The following example previously worked on a Prusti install I have here, but after running "Prusti: update dependencies" I get a failure for the postcondition on
push
:The text was updated successfully, but these errors were encountered: