// RUN: %dafny /compile:0 /print:"%t.print" /dprint:"%t.dprint" "%s" > "%t" // RUN: %diff "%s.expect" "%t" class C { function F(c: C, d: D): bool { true } method M(x: int) returns (y: int, c: C) requires F(D.A, this); // 2 errors requires F(4, 5); // 2 errors requires F(this, D.A); // good { } method Caller() { var m,n := M(true); // error on in-parameter n,m := M(m); // 2 errors on out-parameters } } datatype D = A datatype NeverendingList = Cons(int, NeverendingList) // error: no grounding constructor datatype MutuallyRecursiveDataType = FromANumber(int) | // this is the base case Else(TheCounterpart, C) datatype TheCounterpart = TreeLike(TheCounterpart, TheCounterpart) | More(MutuallyRecursiveDataType) // these 'ReverseOrder_' order tests may be called white-box unit tests datatype ReverseOrder_MutuallyRecursiveDataType = FromANumber(int) | // this is the base case Else(ReverseOrder_TheCounterpart, C) datatype ReverseOrder_TheCounterpart = TreeLike(ReverseOrder_TheCounterpart, ReverseOrder_TheCounterpart) | More(ReverseOrder_MutuallyRecursiveDataType) // --------------------- class ArrayTests { ghost method G(a: array) requires a != null && 10 <= a.Length; modifies a; { a[7] := 13; // error: array elements are not ghost locations } } // --------------------- method DuplicateVarName(x: int) returns (y: int) { var z: int; var z: int; // error: redeclaration of local var x := x; // redeclaration of in-parameter is fine var x := x; // error: but a redeclaration of that local is not fine { var x := x; // an inner local variable of the same name is fine var x := x; // error: but a redeclaration thereof is not okay var y := y; // duplicating an out-parameter here is fine } var y := y; // error: redeclaration of an out-parameter is not allowed (it is // treated like an outermost-scoped local in this regard) } method ScopeTests() { var x := x; // error: the 'x' in the RHS is not in scope var y: real :| y == y; // fine, 'y' is in scope in the RHS var z := DuplicateVarName(z); // error: the 'z' in the RHS is not in scope var w0, w1 := IntTransform(w1), IntTransform(w0); // errors two var c := new MyClass.Init(null); // fine var d := new MyClass.Init(c); // fine var e := new MyClass.Init(e); // error: the 'e' in the RHS is not in scope e := new MyClass.Init(e); // fine (no variable is being introduced here) e.c := new MyClass.Init(e); // also fine } function IntTransform(w: int): int class MyClass { var c: MyClass; constructor Init(c: MyClass) } // --------------------- method InitCalls() { var c := new C.F(null, null); // error: F is not a method var d := new C.M(8); // error: M has out parameters var e := new C.Caller(); } // --------------------- method ArrayRangeAssignments(a: array, c: C) requires a != null && 10 <= a.Length; { a[0..5] := new C; // error: this is not allowed a[1..4] := *; // error: this is not allowed a[2..3] := c; // error: this is not allowed var s: seq := [null,null,null,null,null]; s[0..5] := new C; // error: this is not allowed s[1..4] := *; // error: this is not allowed s[2..3] := c; // error: this is not allowed } // --------------------- tests of restrictions on subranges (nat) method K() { var s: set; // error: not allowed to instantiate 'set' with 'nat' var d: MutuallyRecursiveDataType; // error: not allowed to instantiate with 'nat' var a := new nat[100]; // error: not allowed the type array var b := new nat[100,200]; // error: not allowed the type array2 // constructors var ci0 := new Expl_Class.Init(0, 0); // error: subrange not allowed here var ci1 := new Expl_Class; // error var ci2 := new Expl_Class.Init(0, 0); // error // collection types (sets are above) and array types var m0: multiset; // error var m1: seq; // error var m2: map; // error var m3: map; // error var n: seq>; // error var o: array; // error var o': array2; // error // tuple types var tu0: (nat); // no problem, this just means 'nat' var tu1: (nat,int); // error var tu2: (int,nat); // error // function types var fn: nat -> int; // error var gn: int -> nat; // error var hn: (int,nat) -> int; // error // the following tests test NameSegment and ExprDotName in types: var k: Expl_Class; // error var k': Expl_Module.E; // error // the following tests test NameSegment and ExprDotName in expressions: var e0 := Expl_M(0); // error var e1 := Expl_F(0); // error var ec := new Expl_Class; ec.Init(0, 0); // error Expl_Class.DoIt(0, 0); // error Expl_Class.DoIt(0, 0); // error Expl_Module.E.N(0, 0); // error Expl_Module.E.N(0, 0); // error } method Expl_M(x: T) returns (y: T) function method Expl_F(x: T): T class Expl_Class { method Init(t: T, u: U) static method DoIt(t: T, u: U) } module Expl_Module { class E { static method N(t: T, u: U) } } // --------------------- more ghost tests, for assign-such-that statements method M() { ghost var b: bool; ghost var k: int, l: int; var m: int; k :| k < 10; k, m :| 0 <= k < m; // error: LHS has non-ghost and RHS has ghost m :| m < 10; // Because of the ghost guard, these 'if' statements are ghost contexts, so only // assignments to ghosts are allowed. if (b) { k :| k < 10; // should be allowed k, l :| 0 <= k < l; // ditto } if (b) { m :| m < 10; // error: not allowed in ghost context k, m :| 0 <= k < m; // error: not allowed in ghost context } } ghost method GhostM() returns (x: int) { x :| true; // no problem (but there once was a problem with this case, where an error was generated for no reason) } // ------------------ cycles that could arise from proxy assignments --------- module ProxyCycles { datatype Dt = Ctor(X -> Dt) method M0() { var dt: Dt; var f := x => x; dt := Ctor(f); // error: cannot infer a type for f } method M1() { var dt: Dt; var f := x => x; dt := Ctor(f); // error: cannot infer a type for f } function method F(x: X): set method N() { var x; x := F(x); // error: cannot infer type for x } }