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
}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
}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
}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
}Đọ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
}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
}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
}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
}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
}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
}Đư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
}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
}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
}Đổ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
}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
}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
}Đặ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
}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
}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
}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
}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
}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ấy | Nghĩa là |
|---|---|
K2-BOUNDS | Cắt chữ ra ngoài phạm vi. |
K2-UTF8 | Cắt chữ làm đôi một ký tự. |
Khi build
| Bạn thấy | Nghĩa là |
|---|---|
K2-LINK | Link 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-OUTPUT | File 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-OPTIMIZE | Code đã 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. |