Dafny - Propagate ensures clause? - preconditions

What I'm having issue with is two different methods in two different classes not cooperating, the set-up is as following:
class A{
method b()
ensures statement
{
// Do something
}
}
class C{
method d()
requires statement
{
// Do something
}
}
And a main that calls them as following:
method Main(){
var a: new A;
var c: new C;
a.b();
c.d(); // Error: possible violation of function precondition
}
Why doesn't method d recognize that method b ensures its precondition? If it's a limitation on Dafny's prover how would I go about fixing this issue?
Edit:
Messed up the syntax when I was creating this example, so the test program works. The real one however still got issues. The specific class I'm struggling with is mentioned below:
class TokenController{
var database : map<int, Token>;
// Create a new token if one of the following is true:
// * Token is null
// * Invalid token
//
// Returns true if it was created, false otherwise.
method createToken(key:int, securityLevel:int) returns (res: bool)
modifies this`database;
requires Defines.LOW() <= securityLevel <= Defines.HIGH();
ensures key in database;
ensures database[key] != null;
ensures database[key].isValid;
ensures old(key!in database) || old(database[key] == null) || old(!database[key].isValid) <==> res;
{
if(key !in database || database[key] == null || !database[key].isValid){
var token := new Token.Token;
token.init(key, securityLevel);
// Add it to the map
database := database[key:=token];
res := true;
}
else{
res := false;
}
}
// Returns true if keyt matches the one in the database and the token is valid. Otherwise false.
predicate method validToken(key:int)
requires keyin database;
requires database[key] != null;
reads this`database;
reads this.database[key];
{
database[key].fingerprint == key && database[key].isValid
}
}
In main it's called as following:
var tokenRes : bool;
tokenRes := tokenController.createToken(0, 0);
tokenRes := tokenController.validToken(0); // Error: possible violation of function precondition

Related

Dafny "call might violate context's modifies clause"

I'm new to Dafny. I'm getting the error: call might violate context's modifies clause on the line where Seek() calls Step() in the following code:
class Tape {
var val : int;
constructor() {
this.val := 0;
}
method Write(x : int)
modifies this
{
this.val := x;
}
}
class Simulator {
var tape : Tape;
var step_num : nat;
constructor() {
this.tape := new Tape();
this.step_num := 0;
}
method Step()
modifies this, this.tape
ensures this.step_num > old(this.step_num)
{
this.tape.Write(1);
this.step_num := this.step_num + 1;
}
method Seek(target_step_num : int)
modifies this, this.tape
{
while this.step_num < target_step_num {
this.Step();
}
}
}
I don't understand what's going on here because I explicitly annotated Seek() with modifies this, this.tape.
Looking around online I see some talk about "freshness" and I get the impression that this has to do with ensuring that I have permission to access this.tape, but I don't understand how to fix it. Thanks!
You need invariant that this.tape is not reassigned to something else in methods. Adding ensures this.tape == old(this.tape) post condition in Seek and Step and also adding invariant this.tape == old(this.tape) fixes it.
FWIW, in addition to Divyanshu's excellent answer, I also discovered that I could fix this issue by defining tape as a const:
class Simulator {
const tape : Tape;
var step_num : nat;
...
In this case, it appears that const means that the pointer/reference will never be modified (that it will never point to a different Tape object), not that the Tape object itself will be unmodified.

dart nullability checking method [duplicate]

This question already has answers here:
"The operator can’t be unconditionally invoked because the receiver can be null" error after migrating to Dart null-safety
(3 answers)
Closed 12 months ago.
I have migrated my Dart code to NNBD / Null Safety. Some of it looks like this:
class Foo {
String? _a;
void foo() {
if (_a != null) {
_a += 'a';
}
}
}
class Bar {
Bar() {
_a = 'a';
}
String _a;
}
This causes two analysis errors. For _a += 'a';:
An expression whose value can be 'null' must be null-checked before it can be dereferenced.
Try checking that the value isn't 'null' before dereferencing it.
For Bar() {:
Non-nullable instance field '_a' must be initialized.
Try adding an initializer expression, or add a field initializer in this constructor, or mark it 'late'.
In both cases I have already done exactly what the error suggests! What's up with that?
I'm using Dart 2.12.0-133.2.beta (Tue Dec 15).
Edit: I found this page which says:
The analyzer can’t model the flow of your whole application, so it can’t predict the values of global variables or class fields.
But that doesn't make sense to me - there's only one possible flow control path from if (_a != null) to _a += 'a'; in this case - there's no async code and Dart is single-threaded - so it doesn't matter that _a isn't local.
And the error message for Bar() explicitly states the possibility of initialising the field in the constructor.
The problem is that class fields can be overridden even if it is marked as final. The following example illustrates the problem:
class A {
final String? text = 'hello';
String? getText() {
if (text != null) {
return text;
} else {
return 'WAS NULL!';
}
}
}
class B extends A {
bool first = true;
#override
String? get text {
if (first) {
first = false;
return 'world';
} else {
return null;
}
}
}
void main() {
print(A().getText()); // hello
print(B().getText()); // null
}
The B class overrides the text final field so it returns a value the first time it is asked but returns null after this. You cannot write your A class in such a way that you can prevent this form of overrides from being allowed.
So we cannot change the return value of getText from String? to String even if it looks like we checks the text field for null before returning it.
An expression whose value can be 'null' must be null-checked before it can be dereferenced. Try checking that the value isn't 'null' before dereferencing it.
It seems like this really does only work for local variables. This code has no errors:
class Foo {
String? _a;
void foo() {
final a = _a;
if (a != null) {
a += 'a';
_a = a;
}
}
}
It kind of sucks though. My code is now filled with code that just copies class members to local variables and back again. :-/
Non-nullable instance field '_a' must be initialized. Try adding an initializer expression, or add a field initializer in this constructor, or mark it 'late'.
Ah so it turns out a "field initializer" is actually like this:
class Bar {
Bar() : _a = 'a';
String _a;
}
There are few ways to deal with this situation. I've given a detailed answer here so I'm only writing the solutions from it:
Use local variable (Recommended)
void foo() {
var a = this.a; // <-- Local variable
if (a != null) {
a += 'a';
this.a = a;
}
}
Use ??
void foo() {
var a = (this.a ?? '') + 'a';
this.a = a;
}
Use Bang operator (!)
You should only use this solution when you're 100% sure that the variable (a) is not null at the time you're using it.
void foo() {
a = a! + 'a'; // <-- Bang operator
}
To answer your second question:
Non-nullable fields should always be initialized. There are generally three ways of initializing them:
In the declaration:
class Bar {
String a = 'a';
}
In the initializing formal
class Bar {
String a;
Bar({required this.a});
}
In the initializer list:
class Bar {
String a;
Bar(String b) : a = b;
}
You can create your classes in null-safety like this
class JobDoc {
File? docCam1;
File? docCam2;
File? docBarcode;
File? docSignature;
JobDoc({this.docCam1, this.docCam2, this.docBarcode, this.docSignature});
JobDoc.fromJson(Map<String, dynamic> json) {
docCam1 = json['docCam1'] ?? null;
docCam2 = json['docCam2'] ?? null;
docBarcode = json['docBarcode'] ?? null;
docSignature = json['docSignature'] ?? null;
}
}

Dafny call may violate context's modifies clause when using factory pattern

When calling methods which modify fields in a class, I get an error iff the class was created with a factory:
class Counter {
var i: int;
constructor() {
i := 0;
}
method Count()
modifies this
{
i := i + 1;
}
}
method CounterFactory() returns (r: Counter)
{
r := new Counter();
}
method Main() {
var counter := CounterFactory();
counter.Count(); // <~~ Error: call may violate context's modifies clause
}
When I replace the line directly above the error with var counter := new Counter();, the verifier doesn't complain.
CounterFactory() needs a postcondition to show that the returned object is new. The working method looks like this:
method CounterFactory() returns (r: Counter)
ensures fresh(r)
{
r := new Counter();
}

Implicit declarations

I'm trying to create a grammar, using implicit declarations. After reading the a forum entry (http://www.eclipse.org/forums/index.php?t=msg&S=2e4a29d7fff0322e71b35e3a3aa63e3f&th=198813&goto=634090#msg_634090) I wrote my own LinkingService:
public class OntMLLinkingService extends DefaultLinkingService {
private final Map<Rule, Resource> implicitVariables = new HashMap<>();
public List<EObject> getLinkedObjects(EObject context, EReference ref, INode node) throws IllegalNodeException {
List<EObject> linking = super.getLinkedObjects(context, ref, node);
if (!linking.isEmpty())
return linking;
if (context instanceof VariableReference && ref.equals(OntMLPackage.eINSTANCE.getVariableReference_Variable())) {
// Find the rule, the references is used in
EObject container = context.eContainer();
while (!(container instanceof Rule))
container = container.eContainer();
Rule rule = (Rule) container;
// Check, if a resource was already created for the rule
Resource res = implicitVariables.get(rule);
if (res == null) {
// Create and register new resource
res =
rule.eResource().getResourceSet()
.createResource(URI.createURI("http://wwwcs.vs.hs-rm.de/OntML/Variable/" + UUID.randomUUID()));
implicitVariables.put(rule, res);
}
// Get the cross ref string
final String crossRefString = getCrossRefNodeAsString(node);
if (crossRefString != null && !crossRefString.equals("")) {
// Search for the variable in the resource
Optional<Variable> existingVar =
res.getContents().stream().map(eobj -> (Variable) eobj).filter(var -> var.getName().equals(crossRefString))
.findAny();
if (!existingVar.isPresent()) {
// Create and register new variable, if the variable does not exist yet
Variable newvar = OntMLFactory.eINSTANCE.createVariable();
newvar.setName(crossRefString);
res.getContents().add(newvar);
}
}
// Add all contents of the resource to the linked objects
linking.addAll(res.getContents());
}
return linking;
}
}
I've debugged the "getLinkedObjects" method and everything seems to work fine, but my editor won't show errors anymore, even though I write invalid code and my compiler gets a null pointer, when invoking the "getName" method of any "Variable". I think it's a problem with the LazyLinker and EMF proxies.

Dart argument definition test deprecated?

On Dart 1.0.0, I just tried:
class MyClass {
int x;
bool b;
MyClass(int x, [bool b = true]) {
if(?b) {
// ...
}
}
}
And am getting a compiler error on the ?b part:
The argument definition test ('?' operator) has been deprecated
So what's the "new" way of testing for whether or not an argument was supplied?
There is no way to test if an argument was provided or not. The main-reason for its removal was, that it was very complex to forward calls this way.
The generally preferred way is to use null as "not given". This doesn't always work (for example if null is a valid value), and won't catch bad arguments. If null is used, then the parameter must not have a default-value. Otherwise the parameter is not null but takes the default-value:
foo([x = true, y]) => print("$x, $y");
foo(); // prints "true, null"
So in your case you should probably do:
class MyClass {
int x;
bool b;
MyClass(int x, [bool b]) {
if(b == null) { // treat as if not given.
// ...
}
}
}
This makes new MyClass(5, null) and new MyClass(5) identical. If you really need to catch the first case, you have to work around the type-system:
class _Sentinel { const _Sentinel(); }
...
MyClass(int x, [b = const _Sentinel()]) {
if (b == const _Sentinel()) b = true;
...
}
This way you can check if an argument has been provided. In return you lose the type on b.
The argument definition test operator was deprecated because it was redundant with checking for null; an optional parameter that was omitted would get the value null, and the caller could've passed null explicitly anyway. So instead use == null:
class MyClass {
int x;
bool b;
MyClass(int x, [bool b]) {
if (b == null) {
// throw exception or assign default value for b
}
}
}

Resources