What's the type of a full formed source file?
Simple check
infer("fn () -> int")
fn foo() -> int { 1 }
Methods are resolved in nested function.
infer("fn () -> int")
struct Foo { a: int }
impl (f: Foo) {
fn method() -> int {
f.a + 5
}
}
fn foo() -> int {
fn bar() -> int {
let x = Foo { a: 1 }
x.method()
}
bar()
}
Can use different generic name than declaration.
infer("fn () -> ()")
struct Foo<T> {}
impl<Y> (f: Foo<Y>) {
fn bar(x: int, y: Y) {}
}
fn main() {}
Exhaustive check
errorContains('exhaustive'); errorContains('missing case: "Color.Blue"');
enum Color { Blue, Red, Green }
fn main() -> int {
let x = Color.Red
match x {
Color.Red => 1,
Color.Green => 2,
}
}
Exhaustive check works with unqualified constructors.
errorContains('exhaustive'); errorContains('missing case: "Foo.B"');
enum Foo { A, B, Baz }
fn main() -> int {
match Foo.B {
A => 1,
Foo.Baz => 2,
}
}
Type checking still works.
errorContains("mismatch")
enum Foo { A, B, Baz }
fn foo(a: Foo) -> int { a + 1 }
fn main() {}
Const expressions are type checked
errorContains('mismatch')
const a: string = 1
Catch exhaustiveness errors.
errorContains("constructor Green not found")
enum Color { Red, Blue }
fn main() {
match Color.Red {
Red => 1,
Green => 2,
}
}
Bools missing arm
errorContains('missing case: "true"')
fn main() {
match false {
false => (),
}
}
Prevent usage of reserved words
errorContains("reserved")
fn foo(default: int) -> int {
default
}
Inference of numeric operators
errorContains("numeric type")
fn main() -> int {
false > true
1
}
Pattern matching on slice literals.
errorContains("pattern match on slice literals")
fn main() {
match [1] {
[1,2] => false,
_ => true,
}
}
For loops.
infer("fn () -> ()")
fn main() {
for x in ["a"] {
@ensure x, string
}
for (index, value) in ["a"].Enumerate() {
@ensure index, int
@ensure value, string
}
}
Expr in loops must be rangeable.
errorContains("iterate")
fn main() {
for x in 1 {
}
}
Loops with no condition
infer("fn () -> ()")
fn main() {
loop {
break
}
}
If expression with an expected type must have an else block
errorContains("if false")
fn main() {
if true {
let x = "hello"
1
}
let a = if false {
let y = "yo"
2
}
}
Method calls work for enums.
infer("fn () -> int")
enum Foo {
Bar(int)
}
impl (f: Foo) {
fn method(s: string, b: int) -> int {
match f {
Bar(a) => a + b,
}
}
}
fn main() -> int {
let f = Foo.Bar(1)
@ensure f.method("a", 2), int
let m = f.method
m("a", 2)
}
Generics in extern blocks
infer("fn () -> ()")
use reflect
fn main() {
let a = reflect.DeepEqual(1, false)
let b = reflect.DeepEqual(1, 1)
}
While loops.
infer("fn () -> ()")
fn main() {
let x = 1
while x < 10 {
@ensure x, int
}
}
Enumeration in loops expect a tuple.
errorContains("Use tuple literals")
fn main() {
let m = Map.new()
for e in m {
e.0
}
}
Access slices by index
infer("fn () -> string")
fn main() -> string {
let xs = ["a"]
xs[0]
}
Index must be int for slices
errorContains("mismatch")
fn main() {
let xs = ["a"]
xs[false]
}
Access maps by index
infer("fn () -> int")
fn main() -> int {
let xs = Map.new()
xs.Insert("a", 1)
xs["a"]
}
Index must be K for maps
errorContains("mismatch")
fn main() {
let xs = Map.new()
xs.Insert("a", 1)
xs[false]
}
Parse traits
infer("fn () -> ()")
fn main() {
interface Foo {
fn bar(x: string) -> int
}
fn check(f: Foo) -> int {
f.bar("yo")
}
}
Check if type implements trait
infer("fn () -> int")
struct Baz { x: int }
impl (b: Baz) {
fn bar(_: string) -> int {
b.x
}
}
fn main() -> int {
interface Foo {
fn bar(x: string) -> int
}
fn check(f: Foo) -> int {
f.bar("yo")
}
check(Baz { x: 1 })
}
Trait bounds
infer("fn () -> int")
struct Baz { x: int }
impl (b: Baz) {
fn bar(_: string) -> int {
b.x
}
}
fn main() -> int {
interface Foo {
fn bar(x: string) -> int
}
fn check<T: Foo>(f: T) -> int {
f.bar("yo")
}
check(Baz { x: 1 })
}
Trait bounds checked at call site
errorContains("method foo not found on type int")
fn main() {
interface Foo { fn foo() -> int }
fn check<T: Foo>(f: T) {}
check(1)
}
Variadic functions
infer("fn () -> ()")
fn main() {
fn foo(a: int, b: VarArgs<string>) {}
foo(1)
foo(1, "a")
foo(1, "a", "b", "c")
}
Variadic functions arity error
errorContains("Wrong arity")
fn main() {
fn foo(a: int, b: VarArgs<string>) {}
foo()
}
References are maintained after try call
infer("fn () -> ()")
use os
fn foo() -> Result<()> {
let f = os.Open("file")?
Ok(bar(f))
}
fn bar(f: *os.File) {}
fn main() {
foo()
}
Result with an implicit E must implement error
errorContains("method Error not found")
struct Foo {}
fn foo() -> Result<()> {
Err(Foo {})
}
Type aliases
infer("fn () -> ()")
type Foo<V> = Map<int, V>
type Complex<A, B> = Map<bool, Map<A, Map<B, string>>>
fn foo(m: Foo<string>) -> string {
m[1]
}
fn takes_map(m: Map<int, string>) -> string {
m[1]
}
fn main() {
let m: Foo<string> = Map.new()
m.Insert(1, "a")
foo(m)
takes_map(m)
let c: Complex<int, bool> = Map.new()
@ensure c, Map<bool, Map<int, Map<bool, string>>>
}
Tuple structs
infer("fn () -> Foo")
struct Foo(int)
struct Bar<T>(int, T)
fn check(f: Foo) -> int {
f.0
}
fn bar_check(b: Bar<string>) -> (int, string) {
(b.0, b.1)
}
fn main() -> Foo {
let b = Bar(1, false)
let c = Bar(1, "yo")
bar_check(c)
@ensure check(Foo(1)), int
Foo(2)
}
Type aliases to non existing types
errorContains("Type not found: Bar")
type Foo = Bar
Interfaces as arguments
infer("fn () -> fn () -> int")
use bufio
use os
fn main() -> fn () -> int {
let reader = bufio.NewReader(os.Stdin)
reader.ReadString
}
Impl blocks
infer("fn () -> ()")
enum Color { Red, Blue }
impl (c: Color) {
fn is_red() -> bool {
c == Color.Red
}
}
fn main() {
@ensure Color.is_red(Color.Red), bool
}
Impl blocks with generic types
infer("fn () -> ()")
enum Foo<T, Y> { Bar(T), Baz(Y) }
fn make_bar<T, Y>(x: T) -> Foo<T, Y> { Foo.Bar(x) }
impl<T, Y> (f: Foo<T, Y>) {
fn do_stuff(y: Y) -> Y {
@ensure f, Foo<T, Y>
match f {
Foo.Bar(x) => y,
Foo.Baz(yy) => yy,
}
}
}
fn main() {
let foo: Foo<int, bool> = make_bar(1)
foo.do_stuff(true)
}
Impl for non-existing types
errorContains("not found")
impl (u: Unknown) { }
Impl with wrong generics
errorContains("Wrong arity")
enum Foo<T, Y> { Bar }
impl<T, Y> (f: Foo<T>) { }
Generics in impl method
infer("fn () -> ()")
struct Foo<T> { bar: T }
impl<T> (f: Foo<T>) {
fn map(transform: fn (x: T) -> string) -> string {
transform(f.bar)
}
fn other() -> string {
f.map(|x| "asdf")
}
}
fn main() {
let foo = Foo { bar: 12 }
foo.other()
}
Prevent generics from getting instantiated to non existing types
errorContains("Type not found: K")
enum Foo<T, Y> { Bar(T), Baz(Y) }
impl<T, Y> (f: Foo<T, Y>) {
fn do_stuff(y: Y) -> Y {
@ensure f, Foo<T, K>
y
}
}
Unknown type in impl with generics
errorContains("Type not found: T")
struct Foo<T> {}
impl (f: Foo<T>) {}
Type errors in method chains
errorContains(".foo")
struct Foo {}
struct Bar {}
struct Baz {}
impl (f: Foo) { fn foo() -> int { 1 } }
impl (b: Bar) { fn bar() -> Baz { Baz{} } }
impl (b: Baz) { fn baz() -> Bar { Bar{} } }
fn main() {
Bar{}
.bar()
.baz()
.foo()
}
Mutable reference as method receiver
infer("fn () -> ()")
struct Foo { x: int }
impl (f: *Foo) {
fn bar() {
f.x = 5
}
}
fn main() {
let mut f = Foo { x: 3 }
f.bar()
}
Static functions
infer("fn () -> ()")
struct Foo { x: int }
fn Foo.new(x: int) -> Foo {
Foo { x }
}
impl (f: Foo) {
fn check() -> int {
f.x
}
}
fn main() {
let f = Foo.new(1);
f.check();
}
Access struct fields from package
infer("fn () -> ()")
use net.http
fn main() {
let code = http.Get("foo").Unwrap().StatusCode
@ensure code, int
}
Interface check with supertraits
infer("fn () -> ()")
use io
fn foo(r: io.Reader) {
}
fn bar() -> io.ReadCloser {
@rawgo ("")
}
fn main() {
foo(bar())
}
Well formed select
infer("fn () -> ()")
fn foo(tx: Sender<string>, rx: Receiver<int>) {
select {
let bar = rx.Recv() => {
@ensure bar, int
}
tx.Send("hi") => ()
}
}
fn main() {}