// RUN: %dafny /compile:0 /print:"%t.print" /dprint:"%t.dprint" "%s" > "%t" // RUN: %diff "%s.expect" "%t" class Array { var Length: nat; } class Test { var a: Array; var b: Array; predicate valid() reads this, a, b; { a != null && b != null && a != b && // this is the kind of thing the liberal equalty rules are designed to support a.Length == b.Length } } method m0(t: T, u: U, x: int) requires t != u; // error: Cannot compare type parameters (can only compare reference types that could be the same) requires u != x; // error: the liberal equality rules apply only if the top-level type is a reference type { } method m1(t: array, a: array, b: array3, c: array3) requires t != null && a != null && b != null && c != null; requires t != a && t.Length == a.Length; requires b != c && b.Length0 == c.Length0 && b.Length1 == c.Length1 && b.Length2 == c.Length2; requires t != b; // error: these types are never the same requires a != c; // error: these types are never the same requires t != c; // error: these types are never the same requires a != b; // error: these types are never the same { } class Weird { } method m2(a: Weird, b: Weird) requires a == b; // error: second parameter can't be both bool and int. { } method m3(a: Weird, b: Weird) requires a == b; { } method m4(a: Weird, b: Weird, c: Weird) requires b != c; // error: this is like in m2 above requires a != b; // the types of a and b would be the same if T := bool requires a != c; // this is allowed by the liberal equality rules, which are simple minded; // but there isn't actually any way that the types of a and c could be the same { } // Just to make sure nothing went wrong. method m5(a: array, b: array) requires a == b; // error: never equal { } iterator Iter() { } method m6(a: Iter, b: Iter) requires a != b; { } method m7(a: T -> int, b: int -> T, c: int -> int) requires a != c; // error: arrow types don't fall under the liberal equality rules requires b != c; // error: ditto { } type Syn = Weird method m8(a: Weird, b: Syn, c: Weird, d: Syn, e: Syn) requires a != b; // no prob -- the types are always equal requires b != d; // allowed requires c != d; // allowed requires b != e; // error: these can't be the same type, ever { } datatype List = Nil | Cons(X, List) type ListSynonym = List type Wrapper = T method m9(a: array>, b: array>, c: array>, d: array>, e: array>, f: array>>) requires a != b; // error requires a != c; requires b != c; // error requires c != d; requires a != e; requires b != e; requires d != e; requires a != f; requires b != f; // error { }