KonLang English

Mã lỗi

Ý nghĩa của từng lỗi và cách sửa. Mọi ví dụ ở đây đều đã được đưa cho compiler: bản sai bị từ chối đúng mã lỗi, bản sửa được chấp nhận.

Đọc thông báo lỗi

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

Đầu tiên là mã lỗi, rồi đến điều sai, rồi file, dòng và cột. K2-RELATED chỉ chỗ liên quan còn lại, ở đây là dòng đã giao giá trị đi.

Ownership

K2-OWN-001 Dùng sau khi đã giao đi

Mỗi giá trị chỉ có một chủ. Sau take, tên cũ không còn giữ nó nữa.

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

Dùng tên mới:

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

K2-OWN-002 Giao đi mà không ghi rõ

Truyền một giá trị có tên vào tham số giữ luôn nó là chuyển quyền sở hữu, nên lời gọi phải ghi rõ điều đó.

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

Ghi take, hoặc đổi hàm sang view nếu nó chỉ đọc:

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

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

K2-OWN-004 Có thể đã không còn ở đây

Theo một đường chạy nào đó, giá trị có thể đã không còn ở điểm này. defer vẫn cần những gì nó dùng, nên trả về giá trị đó trước là một cách gặp lỗi này.

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

Trả về bản sao, hoặc bỏ việc dùng nó trong defer:

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

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

K2-BORROW-001 Sửa thứ đang được dùng ở chỗ khác

Khi một giá trị đang được cho mượn bằng edit, không gì khác được đọc nó, kể cả tham số khác trong cùng lời gọi.

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

Đọc vào một biến trước:

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 Sửa thứ không được sửa

Mượn bằng edit cần giá trị khai báo bằng 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

Khai báo bằng var:

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

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

K2-BORROW-003 Trả về thứ mượn mà không ghi nguồn

Hàm trả về view phải ghi rõ nó lấy từ tham số nào, để nơi gọi biết nó tồn tại đến khi nào.

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

Thêm from và tên tham số:

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 Thứ mượn sống lâu hơn chủ

Chủ sẽ bị giải phóng trong khi vẫn có thứ trỏ tới nó, và đây chính là điều quy tắc này ngăn chặn.

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

Trả về chính giá trị:

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

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

K2-CALL-001 Tham số truyền vào không khớp

Tham số ghi edit nhưng lời gọi không ghi, hoặc truyền giá trị tạm vào chỗ cần giá trị có tên.

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

Ghi edit ở lời gọi, và gán giá trị tạm vào biến trước:

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

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

K2-DEFER-001 Thoát từ trong defer

defer chạy khi khối lệnh đã đang kết thúc, nên không thể return hay nhảy đi chỗ khác.

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

Trong defer chỉ để việc dọn dẹp:

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

K2-GUARD-001 Điều kiện when làm thay đổi dữ liệu

Điều kiện when chỉ để hỏi, nên không được thay đổi gì.

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

Đưa thay đổi vào trong nhánh:

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 Điều kiện when cấp phát bộ nhớ

Điều kiện when cũng không được cấp phát bộ nhớ.

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

Tính sẵn câu trả lời trước 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
}

Cú pháp, tên và kiểu

Các lỗi này gồm mã và một từ, kèm đúng dòng.

K2-SYN-003 Không đọc được code ở chỗ này

Thường do dấu chấm phẩy, hai câu lệnh trên một dòng, hoặc cú pháp fn cũ. Dấu ngoặc nhọn trong chữ phải viết {{ và }}.

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

Mỗi dòng một câu lệnh:

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

K2-TYPE-002 Kiểu không khớp

Số không tự đổi kiểu. Biểu thức bắt đầu bằng số trơn có thể cần kiểu: viết x + 1 thay vì 1 + x. Mã này cũng dùng, kèm từ name, cho tên không tồn tại, không có pub trong file được import, hoặc .length trên chữ, mà đúng ra là .byteLength.

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

Đổi bằng as:

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

K2-TYPE-001 Không suy ra được kiểu

List rỗng có thể chứa bất cứ thứ gì, nên phải ghi rõ.

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

Ghi kiểu:

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

K2-MATCH-001 match thiếu trường hợp

match phải xử lý đủ mọi trường hợp.

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

Thêm phần còn lại, hoặc dùng _ cho tất cả:

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 Gọi hàm ngoài mà không có unsafe

Compiler không kiểm tra được code C, nên lời gọi phải được đánh dấu.

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

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

Đặt trong 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 Kiểu chưa làm đủ những gì interface yêu cầu

Kiểu ghi implements phải có đủ mọi method của 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

Thêm 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 Hằng số không tính được

Hằng số phải tính được lúc biên dịch, nên các hằng số không thể phụ thuộc nhau theo vòng tròn.

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

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

Cho nó một giá trị khởi đầu:

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

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

K2-ALIAS-002 Tên kiểu bị dùng hai lần

Mỗi tên kiểu chỉ có một nghĩa. K2-ALIAS-001 cùng họ này, dùng cho alias tự trỏ về chính nó.

type Count = i32
type Count = u32

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

Dùng hai tên:

type Count = i32
type Total = u32

func main(): i32 {
    return 0
}

K2-FFI-001 Kiểu mà C không nhận được

Hiện chỉ giá trị đơn giản mới qua được C, chưa nhận giá trị sở hữu như String.

extern "C" func show(value: String)

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

Gửi giá trị đơn giản:

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

func main(): i32 {
    return 0
}

K2-FRONTEND-001 Compiler chưa hỗ trợ

Hợp lệ theo spec, nhưng compiler chưa làm được. Trang Trạng thái liệt kê những gì còn thiếu.

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

Viết theo cách khác:

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

Khi chạy

Các lỗi này dừng chương trình thay vì để nó chạy tiếp với dữ liệu sai. Chỉ số vượt quá cuối và chia cho 0 hiện dừng mà không có thông báo; mã thoát cho thấy chương trình đã sập.

Bạn thấyNghĩa là
K2-BOUNDSCắt chữ ra ngoài phạm vi.
K2-UTF8Cắt chữ làm đôi một ký tự.

Khi build

Bạn thấyNghĩa là
K2-LINKLink thất bại. Nếu import file có hàm C bằng đường dẫn thường thì cần --link; import std/ thì không.
K2-OUTPUTFile xuất ra sẽ ghi đè mã nguồn hoặc compiler, hoặc không tạo được thư mục build.
K2-CODEGEN, K2-OPTIMIZECode đã qua kiểm tra, nhưng bước sinh mã hoặc tối ưu thất bại. Lỗi này thường do compiler, không phải code của bạn.