KonLang Tiếng Việt

Errors

What each error means and how to fix it. Every example here was given to the compiler, which rejected it with the code shown and accepted the fix.

Reading an error

K2-OWN-001: value was moved or is not initialized at game.kon:4:11
K2-RELATED: related ownership location at game.kon:3:17

The code comes first, then what went wrong, then the file, line and column. K2-RELATED names the other place involved, here the line that gave the value away.

Ownership

K2-OWN-001 Used after it was handed over

A value has one owner. After take, the old name no longer holds it.

func main(): i32 {
    var a: List<u8> = list[]
    let b = take a
    print(a.length)
    return 0
}
K2-OWN-001: value was moved or is not initialized at game.kon

Use the new name:

func main(): i32 {
    var a: List<u8> = list[]
    let b = take a
    print(b.length)
    return 0
}

K2-OWN-002 Handing over without saying so

Passing a named value to a parameter that keeps it moves the value, so the call has to show that.

func keep(a: List<u8>) {
}

func main(): i32 {
    var a: List<u8> = list[]
    keep(a)
    return 0
}
K2-OWN-002: named owning value requires explicit take at game.kon

Say take, or have the function take view if it only reads:

func keep(a: List<u8>) {
}

func main(): i32 {
    var a: List<u8> = list[]
    keep(take a)
    return 0
}

K2-OWN-004 Might already be gone here

On some way through the code the value may be gone by this point. A defer still needs what it uses, so returning that value first is one way to get here.

func make(): String {
    let t = String("x")
    defer {
        print(t)
    }
    return t
}

func main(): i32 {
    let r = make()
    return 0
}
K2-OWN-004: value is not available on every control-flow path at game.kon

Return a copy, or stop using it in the defer:

func make(): String {
    var t = String("x")
    return take t
}

func main(): i32 {
    let r = make()
    print(r)
    return 0
}

K2-BORROW-001 Changing what something else is using

While a value is lent out for edit, nothing else may read it, including another argument of the same call.

func grow(a: edit List<u8>, size: u64) {
}

func main(): i32 {
    var a: List<u8> = list[]
    grow(edit a, a.length)
    return 0
}
K2-BORROW-001: access conflicts with a live borrow at game.kon

Read it into a name first:

func grow(a: edit List<u8>, size: u64) {
}

func main(): i32 {
    var a: List<u8> = list[]
    let size = a.length
    grow(edit a, size)
    return 0
}

K2-BORROW-002 Changing something that cannot change

An edit loan needs a value declared with var.

func fill(a: edit List<u8>) {
}

func main(): i32 {
    let a: List<u8> = list[]
    fill(edit a)
    return 0
}
K2-BORROW-002: place is not mutable through this capability at game.kon

Declare it with var:

func fill(a: edit List<u8>) {
}

func main(): i32 {
    var a: List<u8> = list[]
    fill(edit a)
    return 0
}

K2-BORROW-003 Returning a borrow without saying from where

A function that returns a view has to name the parameter it comes from, so callers know how long it lasts.

func same(a: view List<u8>): view List<u8> {
    return view a
}

func main(): i32 {
    let a: List<u8> = list[]
    let b = same(a)
    return 0
}
K2-BORROW-003: returned borrow escapes its permitted origin at game.kon

Add from with the parameter:

func same(a: view List<u8>): view List<u8> from a {
    return view a
}

func main(): i32 {
    let a: List<u8> = list[]
    let b = same(a)
    print(b.length)
    return 0
}

K2-BORROW-004 A borrow outlives its owner

The owner would be freed while something still points at it, which is what this rule exists to stop.

func make(): view String {
    let t = String("x")
    return view t
}

func main(): i32 {
    let b = make()
    return 0
}
K2-BORROW-004: owner cannot be dropped while its borrow is live at game.kon

Return the value itself:

func make(): String {
    var t = String("x")
    return take t
}

func main(): i32 {
    let b = make()
    print(b)
    return 0
}

K2-CALL-001 The argument does not match the parameter

The parameter says edit but the call does not, or a temporary was passed where a named value is needed.

func fill(a: edit List<u8>) {
}

func main(): i32 {
    var a: List<u8> = list[]
    fill(a)
    return 0
}
K2-CALL-001: argument has no addressable place or has the wrong view/edit capability at game.kon

Write edit at the call, and bind a temporary to a name first:

func fill(a: edit List<u8>) {
}

func main(): i32 {
    var a: List<u8> = list[]
    fill(edit a)
    return 0
}

K2-DEFER-001 Leaving from inside a defer

A defer runs while the block is already ending, so it cannot return or move control elsewhere.

func main(): i32 {
    defer {
        return 0
    }
    return 0
}
K2-DEFER-001: defer cannot transfer this value at game.kon

Keep cleanup only in the defer:

func main(): i32 {
    defer {
        print("done")
    }
    return 0
}

K2-GUARD-001 A guard that changes something

A when guard is only a question, so it must not change anything.

func bump(a: edit i32): bool {
    a += 1
    return true
}

func main(): i32 {
    var count: i32 = 0
    let found = some(1)
    match found {
        some(v) when bump(edit count) => { print(v) }
        _ => { }
    }
    return 0
}
K2-GUARD-001: ownership guard obligation is not satisfied at game.kon

Make the change inside the arm:

func main(): i32 {
    var count: i32 = 0
    let found = some(1)
    match found {
        some(v) when v > 0 => { count += 1 }
        _ => { }
    }
    print(count)
    return 0
}

K2-GUARD-003 A guard that allocates

A guard must not allocate memory either.

func main(): i32 {
    let found = some(1)
    match found {
        some(v) when String("a").byteLength > 0 => { print(v) }
        _ => { }
    }
    return 0
}
K2-GUARD-003: ownership guard obligation is not satisfied at game.kon

Work the answer out before the match:

func main(): i32 {
    let found = some(1)
    let name = String("a")
    let named = name.byteLength > 0
    match found {
        some(v) when named => { print(v) }
        _ => { }
    }
    return 0
}

Syntax, names and types

These give a code and one word, with the exact line.

K2-SYN-003 The code cannot be read here

Common causes are a semicolon, two statements on one line, or old fn syntax. Literal braces in text are written {{ and }}.

func main(): i32 {
    let a = 1; let b = 2
    return 0
}
K2-SYN-003: syntax at game.kon

One statement per line:

func main(): i32 {
    let a: i32 = 1
    let b: i32 = 2
    print(a + b)
    return 0
}

K2-TYPE-002 The types do not match

Numbers never convert by themselves. An expression starting with a plain number may need a type too: write x + 1 rather than 1 + x. This code is also used, with the word name, for a name that does not exist, is not pub in the imported file, or is .length on text, where .byteLength is what you want.

func main(): i32 {
    let a: i32 = 1
    let b: u8 = a
    return 0
}
K2-TYPE-002: type at game.kon

Convert with as:

func main(): i32 {
    let a: i32 = 1
    let b = a as u8
    print(b)
    return 0
}

K2-TYPE-001 The type cannot be worked out

An empty list could hold anything, so say what.

func main(): i32 {
    let a = list[]
    return 0
}
K2-TYPE-001: type at game.kon

Write the type:

func main(): i32 {
    let a: List<u8> = list[]
    print(a.length)
    return 0
}

K2-MATCH-001 A case is missing from match

A match has to cover every case.

enum Light {
    Red
    Green
}

func main(): i32 {
    let light = Light.Red
    match light {
        Light.Red => { print(1) }
    }
    return 0
}
K2-MATCH-001: match at game.kon

Add the rest, or _ for all of them:

enum Light {
    Red
    Green
}

func main(): i32 {
    let light = Light.Red
    match light {
        Light.Red => { print(1) }
        Light.Green => { print(2) }
    }
    return 0
}

K2-UNSAFE-001 A foreign call outside unsafe

The compiler cannot check C code, so calling it has to be marked.

extern "C" func abs(value: i32): i32

func main(): i32 {
    print(abs(-1))
    return 0
}
K2-UNSAFE-001: unsafe at game.kon

Put it in unsafe:

extern "C" func abs(value: i32): i32

func main(): i32 {
    var result: i32 = 0
    unsafe {
        result = abs(-1)
    }
    print(result)
    return 0
}

K2-IFACE-001 A type does not do what its interface asks

A type marked implements needs every method of that interface.

interface Named {
    func label(view self): i32
}

struct Cat implements Named {
    lives: i32
}

func main(): i32 {
    return 0
}
K2-IFACE-001: interface at game.kon

Add the method:

interface Named {
    func label(view self): i32
}

struct Cat implements Named {
    lives: i32

    func label(view self): i32 {
        return self.lives
    }
}

func main(): i32 {
    return 0
}

K2-CONST-001 A constant that cannot be worked out

A constant has to be computable when compiling, so constants cannot depend on each other in a circle.

const A: i32 = B
const B: i32 = A

func main(): i32 {
    return 0
}
K2-CONST-001: const at game.kon

Give it a starting value:

const A: i32 = 1
const B: i32 = A

func main(): i32 {
    print(B)
    return 0
}

K2-ALIAS-002 A type name used twice

Each type name means one thing. K2-ALIAS-001 is the same family, for an alias that refers to itself.

type Count = i32
type Count = u32

func main(): i32 {
    return 0
}
K2-ALIAS-002: alias at game.kon

Use two names:

type Count = i32
type Total = u32

func main(): i32 {
    return 0
}

K2-FFI-001 A type C cannot take

Only simple values cross to C so far, not owned values such as String.

extern "C" func show(value: String)

func main(): i32 {
    return 0
}
K2-FFI-001: ffi at game.kon

Send simple values:

extern "C" func abs(value: i32): i32

func main(): i32 {
    return 0
}

K2-FRONTEND-001 Not supported by the compiler yet

Valid in the specification, but the compiler cannot do it yet. The status page lists what is missing.

func main(): i32 {
    let n: i32 = 2
    print("n = {n}")
    return 0
}
K2-FRONTEND-001: unsupported at game.kon

Write it another way:

func main(): i32 {
    let n: i32 = 2
    print("n =")
    print(n)
    return 0
}

While running

These stop the program instead of letting it continue with bad data. An index past the end and division by zero stop it with no message for now; the exit code shows a crash.

You seeMeans
K2-BOUNDSA text slice outside the text.
K2-UTF8A text slice that would cut a character in two.

While building

You seeMeans
K2-LINKLinking failed. If you import a file with C functions by a plain path, it needs --link; std/ imports do not.
K2-OUTPUTThe output file would overwrite the source or the compiler, or the build folder could not be made.
K2-CODEGEN, K2-OPTIMIZEThe code passed its checks, but generating or optimizing it failed. This points at the compiler, not at your code.