mirror of
https://github.com/vlang/v.git
synced 2025-09-14 06:52:36 +03:00
parent
437631e80f
commit
7d47219808
18 changed files with 190 additions and 47 deletions
|
@ -258,12 +258,12 @@ fn (mut ctx Context) parse_events() {
|
||||||
mut event := &Event(unsafe { nil })
|
mut event := &Event(unsafe { nil })
|
||||||
if ctx.read_buf[0] == 0x1b {
|
if ctx.read_buf[0] == 0x1b {
|
||||||
e, len := escape_sequence(ctx.read_buf.bytestr())
|
e, len := escape_sequence(ctx.read_buf.bytestr())
|
||||||
event = e
|
event = unsafe { e }
|
||||||
ctx.shift(len)
|
ctx.shift(len)
|
||||||
} else {
|
} else {
|
||||||
if ctx.read_all_bytes {
|
if ctx.read_all_bytes {
|
||||||
e, len := multi_char(ctx.read_buf.bytestr())
|
e, len := multi_char(ctx.read_buf.bytestr())
|
||||||
event = e
|
event = unsafe { e }
|
||||||
ctx.shift(len)
|
ctx.shift(len)
|
||||||
} else {
|
} else {
|
||||||
event = single_char(ctx.read_buf.bytestr())
|
event = single_char(ctx.read_buf.bytestr())
|
||||||
|
|
|
@ -344,7 +344,7 @@ pub fn (mut p Parser) find_sub_table(key DottedKey) !&map[string]ast.Value {
|
||||||
ky << p.root_map_key
|
ky << p.root_map_key
|
||||||
ky << key
|
ky << key
|
||||||
if p.root_map_key.len == 0 {
|
if p.root_map_key.len == 0 {
|
||||||
ky = key
|
ky = unsafe { key }
|
||||||
}
|
}
|
||||||
util.printdbg(@MOD + '.' + @STRUCT + '.' + @FN, 'locating "${ky}" in map ${ptr_str(p.root_map)}')
|
util.printdbg(@MOD + '.' + @STRUCT + '.' + @FN, 'locating "${ky}" in map ${ptr_str(p.root_map)}')
|
||||||
mut t := unsafe { &p.root_map }
|
mut t := unsafe { &p.root_map }
|
||||||
|
@ -1047,7 +1047,7 @@ pub fn (mut p Parser) double_array_of_tables_contents(target_key DottedKey) ![]a
|
||||||
// Parse `[d.e.f]`
|
// Parse `[d.e.f]`
|
||||||
p.ignore_while(space_formatting)
|
p.ignore_while(space_formatting)
|
||||||
dotted_key := p.dotted_key()!
|
dotted_key := p.dotted_key()!
|
||||||
implicit_allocation_key = dotted_key
|
implicit_allocation_key = unsafe { dotted_key }
|
||||||
if dotted_key.len > 2 {
|
if dotted_key.len > 2 {
|
||||||
implicit_allocation_key = dotted_key[2..]
|
implicit_allocation_key = dotted_key[2..]
|
||||||
}
|
}
|
||||||
|
|
|
@ -235,33 +235,6 @@ fn (mut c Checker) assign_stmt(mut node ast.AssignStmt) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if left is ast.Ident && left.is_mut() && !c.inside_unsafe {
|
|
||||||
if left_type.is_ptr() && mut right is ast.Ident && !right.is_mut()
|
|
||||||
&& right_type.is_ptr() {
|
|
||||||
c.error('`${right.name}` is immutable, cannot have a mutable reference to an immutable object',
|
|
||||||
right.pos)
|
|
||||||
} else if mut right is ast.StructInit {
|
|
||||||
typ_sym := c.table.sym(right.typ)
|
|
||||||
for init_field in right.init_fields {
|
|
||||||
if field_info := c.table.find_field_with_embeds(typ_sym, init_field.name) {
|
|
||||||
if field_info.is_mut {
|
|
||||||
if init_field.expr is ast.Ident && !init_field.expr.is_mut()
|
|
||||||
&& init_field.typ.is_ptr() {
|
|
||||||
c.note('`${init_field.expr.name}` is immutable, cannot have a mutable reference to an immutable object',
|
|
||||||
init_field.pos)
|
|
||||||
} else if init_field.expr is ast.PrefixExpr {
|
|
||||||
if init_field.expr.op == .amp
|
|
||||||
&& init_field.expr.right is ast.Ident
|
|
||||||
&& !init_field.expr.right.is_mut() {
|
|
||||||
c.note('`${init_field.expr.right.name}` is immutable, cannot have a mutable reference to an immutable object',
|
|
||||||
init_field.expr.right.pos)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
// Make sure the variable is mutable
|
// Make sure the variable is mutable
|
||||||
c.fail_if_immutable(mut left)
|
c.fail_if_immutable(mut left)
|
||||||
|
@ -275,6 +248,11 @@ fn (mut c Checker) assign_stmt(mut node ast.AssignStmt) {
|
||||||
// c.error('cannot assign a `none` value to a non-option variable', right.pos())
|
// c.error('cannot assign a `none` value to a non-option variable', right.pos())
|
||||||
// }
|
// }
|
||||||
}
|
}
|
||||||
|
if !c.inside_unsafe && !is_blank_ident && node.op in [.decl_assign, .assign]
|
||||||
|
&& left is ast.Ident && left.is_mut() {
|
||||||
|
// check if right-side is a immutable reference
|
||||||
|
c.fail_if_immutable_to_mutable(left_type, right_type, right)
|
||||||
|
}
|
||||||
if mut left is ast.Ident && left.info is ast.IdentVar && right is ast.Ident
|
if mut left is ast.Ident && left.info is ast.IdentVar && right is ast.Ident
|
||||||
&& right.name in c.global_names {
|
&& right.name in c.global_names {
|
||||||
ident_var_info := left.info as ast.IdentVar
|
ident_var_info := left.info as ast.IdentVar
|
||||||
|
|
|
@ -803,6 +803,78 @@ fn (mut c Checker) expand_iface_embeds(idecl &ast.InterfaceDecl, level int, ifac
|
||||||
return ares
|
return ares
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// fail_if_immutable_to_mutable checks if there is a immutable reference on right-side of assignment for mutable var
|
||||||
|
fn (mut c Checker) fail_if_immutable_to_mutable(left_type ast.Type, right_type ast.Type, right ast.Expr) bool {
|
||||||
|
match right {
|
||||||
|
ast.Ident {
|
||||||
|
if c.inside_unsafe || c.pref.translated || c.file.is_translated {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
if right.obj is ast.Var {
|
||||||
|
if left_type.is_ptr() && !right.is_mut() && right_type.is_ptr() {
|
||||||
|
c.note('`${right.name}` is immutable, cannot have a mutable reference to an immutable object',
|
||||||
|
right.pos)
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if !right.obj.is_mut
|
||||||
|
&& c.table.final_sym(right_type).kind in [.array, .array_fixed, .map] {
|
||||||
|
c.note('left-side of assignment expects a mutable reference, but variable `${right.name}` is immutable, declare it with `mut` to make it mutable or clone it',
|
||||||
|
right.pos)
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ast.IfExpr {
|
||||||
|
if c.inside_unsafe || c.pref.translated || c.file.is_translated {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
for branch in right.branches {
|
||||||
|
stmts := branch.stmts.filter(it is ast.ExprStmt)
|
||||||
|
if stmts.len > 0 {
|
||||||
|
last_expr := stmts.last() as ast.ExprStmt
|
||||||
|
c.fail_if_immutable_to_mutable(left_type, right_type, last_expr.expr)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ast.MatchExpr {
|
||||||
|
if c.inside_unsafe || c.pref.translated || c.file.is_translated {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
for branch in right.branches {
|
||||||
|
stmts := branch.stmts.filter(it is ast.ExprStmt)
|
||||||
|
if stmts.len > 0 {
|
||||||
|
last_expr := stmts.last() as ast.ExprStmt
|
||||||
|
c.fail_if_immutable_to_mutable(left_type, right_type, last_expr.expr)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ast.StructInit {
|
||||||
|
typ_sym := c.table.sym(right.typ)
|
||||||
|
for init_field in right.init_fields {
|
||||||
|
if field_info := c.table.find_field_with_embeds(typ_sym, init_field.name) {
|
||||||
|
if field_info.is_mut {
|
||||||
|
if init_field.expr is ast.Ident && !init_field.expr.is_mut()
|
||||||
|
&& init_field.typ.is_ptr() {
|
||||||
|
c.note('`${init_field.expr.name}` is immutable, cannot have a mutable reference to an immutable object',
|
||||||
|
init_field.pos)
|
||||||
|
} else if init_field.expr is ast.PrefixExpr {
|
||||||
|
if init_field.expr.op == .amp && init_field.expr.right is ast.Ident
|
||||||
|
&& !init_field.expr.right.is_mut() {
|
||||||
|
c.note('`${init_field.expr.right.name}` is immutable, cannot have a mutable reference to an immutable object',
|
||||||
|
init_field.expr.right.pos)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
// returns name and position of variable that needs write lock
|
// returns name and position of variable that needs write lock
|
||||||
// also sets `is_changed` to true (TODO update the name to reflect this?)
|
// also sets `is_changed` to true (TODO update the name to reflect this?)
|
||||||
fn (mut c Checker) fail_if_immutable(mut expr ast.Expr) (string, token.Pos) {
|
fn (mut c Checker) fail_if_immutable(mut expr ast.Expr) (string, token.Pos) {
|
||||||
|
@ -4800,7 +4872,7 @@ fn (mut c Checker) index_expr(mut node ast.IndexExpr) ast.Type {
|
||||||
unwrapped_sym := c.table.final_sym(unwrapped_typ)
|
unwrapped_sym := c.table.final_sym(unwrapped_typ)
|
||||||
if unwrapped_sym.kind in [.map, .array, .array_fixed] {
|
if unwrapped_sym.kind in [.map, .array, .array_fixed] {
|
||||||
typ = unwrapped_typ
|
typ = unwrapped_typ
|
||||||
typ_sym = unwrapped_sym
|
typ_sym = unsafe { unwrapped_sym }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {}
|
else {}
|
||||||
|
|
|
@ -321,12 +321,12 @@ fn (mut c Checker) infix_expr(mut node ast.InfixExpr) ast.Type {
|
||||||
if mut right_sym.info is ast.Alias && (right_sym.info.language != .c
|
if mut right_sym.info is ast.Alias && (right_sym.info.language != .c
|
||||||
&& c.mod == c.table.type_to_str(unwrapped_right_type).split('.')[0]
|
&& c.mod == c.table.type_to_str(unwrapped_right_type).split('.')[0]
|
||||||
&& (right_final_sym.is_primitive() || right_final_sym.kind == .enum)) {
|
&& (right_final_sym.is_primitive() || right_final_sym.kind == .enum)) {
|
||||||
right_sym = right_final_sym
|
right_sym = unsafe { right_final_sym }
|
||||||
}
|
}
|
||||||
if mut left_sym.info is ast.Alias && (left_sym.info.language != .c
|
if mut left_sym.info is ast.Alias && (left_sym.info.language != .c
|
||||||
&& c.mod == c.table.type_to_str(unwrapped_left_type).split('.')[0]
|
&& c.mod == c.table.type_to_str(unwrapped_left_type).split('.')[0]
|
||||||
&& (left_final_sym.is_primitive() || left_final_sym.kind == .enum)) {
|
&& (left_final_sym.is_primitive() || left_final_sym.kind == .enum)) {
|
||||||
left_sym = left_final_sym
|
left_sym = unsafe { left_final_sym }
|
||||||
}
|
}
|
||||||
|
|
||||||
if c.pref.translated && node.op in [.plus, .minus, .mul]
|
if c.pref.translated && node.op in [.plus, .minus, .mul]
|
||||||
|
|
|
@ -1,3 +1,17 @@
|
||||||
|
vlib/v/checker/tests/array_or_map_assign_err.vv:5:7: notice: left-side of assignment expects a mutable reference, but variable `a1` is immutable, declare it with `mut` to make it mutable or clone it
|
||||||
|
3 | a2 := a1
|
||||||
|
4 | mut a3 := []int{}
|
||||||
|
5 | a3 = a1
|
||||||
|
| ~~
|
||||||
|
6 |
|
||||||
|
7 | m1 := {
|
||||||
|
vlib/v/checker/tests/array_or_map_assign_err.vv:12:7: notice: left-side of assignment expects a mutable reference, but variable `m1` is immutable, declare it with `mut` to make it mutable or clone it
|
||||||
|
10 | m2 := m1
|
||||||
|
11 | mut m3 := map[string]int{}
|
||||||
|
12 | m3 = m1
|
||||||
|
| ~~
|
||||||
|
13 |
|
||||||
|
14 | _ = a2
|
||||||
vlib/v/checker/tests/array_or_map_assign_err.vv:5:5: error: use `array2 = array1.clone()` instead of `array2 = array1` (or use `unsafe`)
|
vlib/v/checker/tests/array_or_map_assign_err.vv:5:5: error: use `array2 = array1.clone()` instead of `array2 = array1` (or use `unsafe`)
|
||||||
3 | a2 := a1
|
3 | a2 := a1
|
||||||
4 | mut a3 := []int{}
|
4 | mut a3 := []int{}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
vlib/v/checker/tests/assign_immutable_reference_var_err.vv:8:11: error: `x` is immutable, cannot have a mutable reference to an immutable object
|
vlib/v/checker/tests/assign_immutable_reference_var_err.vv:8:11: notice: `x` is immutable, cannot have a mutable reference to an immutable object
|
||||||
6 |
|
6 |
|
||||||
7 | fn y(x &Foo) {
|
7 | fn y(x &Foo) {
|
||||||
8 | mut m := x
|
8 | mut m := x
|
||||||
| ^
|
| ^
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
vlib/v/checker/tests/deprecations_consts.vv:3:25: error: const `deprecated_consts.a_deprecated_const` has been deprecated since 2023-12-31; use built-in constant min_i8 instead
|
vlib/v/checker/tests/deprecations_consts.vv:4:25: error: const `deprecated_consts.a_deprecated_const` has been deprecated since 2023-12-31; use built-in constant min_i8 instead
|
||||||
1 | import deprecated_consts
|
2 |
|
||||||
2 | fn main() {
|
3 | fn main() {
|
||||||
3 | dump(deprecated_consts.a_deprecated_const)
|
4 | dump(deprecated_consts.a_deprecated_const)
|
||||||
| ~~~~~~~~~~~~~~~~~~
|
| ~~~~~~~~~~~~~~~~~~
|
||||||
4 | }
|
5 | }
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
import deprecated_consts
|
import deprecated_consts
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
dump(deprecated_consts.a_deprecated_const)
|
dump(deprecated_consts.a_deprecated_const)
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,3 +1,17 @@
|
||||||
|
vlib/v/checker/tests/fixed_array_conv.vv:3:5: notice: left-side of assignment expects a mutable reference, but variable `arr` is immutable, declare it with `mut` to make it mutable or clone it
|
||||||
|
1 | arr := [2, 3]!
|
||||||
|
2 | mut p := unsafe { nil }
|
||||||
|
3 | p = arr
|
||||||
|
| ~~~
|
||||||
|
4 | mut ip := &int(0)
|
||||||
|
5 | ip = arr
|
||||||
|
vlib/v/checker/tests/fixed_array_conv.vv:5:6: notice: left-side of assignment expects a mutable reference, but variable `arr` is immutable, declare it with `mut` to make it mutable or clone it
|
||||||
|
3 | p = arr
|
||||||
|
4 | mut ip := &int(0)
|
||||||
|
5 | ip = arr
|
||||||
|
| ~~~
|
||||||
|
6 | _ = &int(arr)
|
||||||
|
7 | _ = p
|
||||||
vlib/v/checker/tests/fixed_array_conv.vv:6:5: warning: cannot cast a fixed array (use e.g. `&arr[0]` instead)
|
vlib/v/checker/tests/fixed_array_conv.vv:6:5: warning: cannot cast a fixed array (use e.g. `&arr[0]` instead)
|
||||||
4 | mut ip := &int(0)
|
4 | mut ip := &int(0)
|
||||||
5 | ip = arr
|
5 | ip = arr
|
||||||
|
|
28
vlib/v/checker/tests/immutable_to_mutable_err.out
Normal file
28
vlib/v/checker/tests/immutable_to_mutable_err.out
Normal file
|
@ -0,0 +1,28 @@
|
||||||
|
vlib/v/checker/tests/immutable_to_mutable_err.vv:10:27: notice: left-side of assignment expects a mutable reference, but variable `arr` is immutable, declare it with `mut` to make it mutable or clone it
|
||||||
|
8 | fn main() {
|
||||||
|
9 | arr := [1, 2, 3] // declared as immutable!
|
||||||
|
10 | mut arr_mut := if true { arr } else { []int{} }
|
||||||
|
| ~~~
|
||||||
|
11 | mut arr_mut2 := match true {
|
||||||
|
12 | true { arr }
|
||||||
|
vlib/v/checker/tests/immutable_to_mutable_err.vv:12:10: notice: left-side of assignment expects a mutable reference, but variable `arr` is immutable, declare it with `mut` to make it mutable or clone it
|
||||||
|
10 | mut arr_mut := if true { arr } else { []int{} }
|
||||||
|
11 | mut arr_mut2 := match true {
|
||||||
|
12 | true { arr }
|
||||||
|
| ~~~
|
||||||
|
13 | else { [0] }
|
||||||
|
14 | }
|
||||||
|
vlib/v/checker/tests/immutable_to_mutable_err.vv:22:15: error: use `mut array2 := array1.clone()` instead of `mut array2 := array1` (or use `unsafe`)
|
||||||
|
20 |
|
||||||
|
21 | a := Test{}
|
||||||
|
22 | mut arr_mut3 := a.foo
|
||||||
|
| ~~
|
||||||
|
23 | arr_mut3[0] = 999
|
||||||
|
24 | assert a.foo == [1, 2, 3]
|
||||||
|
vlib/v/checker/tests/immutable_to_mutable_err.vv:26:15: error: use `mut array2 := array1.clone()` instead of `mut array2 := array1` (or use `unsafe`)
|
||||||
|
24 | assert a.foo == [1, 2, 3]
|
||||||
|
25 |
|
||||||
|
26 | mut arr_mut4 := a.bar
|
||||||
|
| ~~
|
||||||
|
27 | arr_mut4[0] = 999
|
||||||
|
28 | assert a.bar == [1, 2, 3]
|
31
vlib/v/checker/tests/immutable_to_mutable_err.vv
Normal file
31
vlib/v/checker/tests/immutable_to_mutable_err.vv
Normal file
|
@ -0,0 +1,31 @@
|
||||||
|
struct Test {
|
||||||
|
pub:
|
||||||
|
bar []int = [1, 2, 3]
|
||||||
|
pub mut:
|
||||||
|
foo []int = [1, 2, 3]
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
arr := [1, 2, 3] // declared as immutable!
|
||||||
|
mut arr_mut := if true { arr } else { []int{} }
|
||||||
|
mut arr_mut2 := match true {
|
||||||
|
true { arr }
|
||||||
|
else { [0] }
|
||||||
|
}
|
||||||
|
arr_mut[0] = 999
|
||||||
|
arr_mut2[1] = 999
|
||||||
|
println(arr)
|
||||||
|
println(arr)
|
||||||
|
assert arr == [1, 2, 3]
|
||||||
|
|
||||||
|
a := Test{}
|
||||||
|
mut arr_mut3 := a.foo
|
||||||
|
arr_mut3[0] = 999
|
||||||
|
assert a.foo == [1, 2, 3]
|
||||||
|
|
||||||
|
mut arr_mut4 := a.bar
|
||||||
|
arr_mut4[0] = 999
|
||||||
|
assert a.bar == [1, 2, 3]
|
||||||
|
|
||||||
|
_ := a.bar
|
||||||
|
}
|
|
@ -1,3 +1,10 @@
|
||||||
|
vlib/v/checker/tests/unsafe_fixed_array_assign.vv:10:10: notice: left-side of assignment expects a mutable reference, but variable `a` is immutable, declare it with `mut` to make it mutable or clone it
|
||||||
|
8 | }
|
||||||
|
9 | a := [&box]!
|
||||||
|
10 | mut b := a
|
||||||
|
| ^
|
||||||
|
11 | b[0].num = 0
|
||||||
|
12 | println(a)
|
||||||
vlib/v/checker/tests/unsafe_fixed_array_assign.vv:10:7: error: assignment from one fixed array to another with a pointer element type is prohibited outside of `unsafe`
|
vlib/v/checker/tests/unsafe_fixed_array_assign.vv:10:7: error: assignment from one fixed array to another with a pointer element type is prohibited outside of `unsafe`
|
||||||
8 | }
|
8 | }
|
||||||
9 | a := [&box]!
|
9 | a := [&box]!
|
||||||
|
|
|
@ -72,7 +72,7 @@ fn (mut g Gen) gen_expr_to_string(expr ast.Expr, etype ast.Type) {
|
||||||
parent_sym := g.table.sym(sym.info.parent_type)
|
parent_sym := g.table.sym(sym.info.parent_type)
|
||||||
if parent_sym.has_method('str') {
|
if parent_sym.has_method('str') {
|
||||||
typ = sym.info.parent_type
|
typ = sym.info.parent_type
|
||||||
sym = parent_sym
|
sym = unsafe { parent_sym }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
sym_has_str_method, str_method_expects_ptr, _ := sym.str_method_info()
|
sym_has_str_method, str_method_expects_ptr, _ := sym.str_method_info()
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
module main
|
module main
|
||||||
|
|
||||||
// vtest vflags: -os wasm32_emscripten
|
// vtest vflags: -os wasm32_emscripten
|
||||||
|
|
||||||
import platform_wrapper
|
import platform_wrapper
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
|
|
|
@ -87,7 +87,7 @@ fn (mut g JsGen) gen_expr_to_string(expr ast.Expr, etype ast.Type) {
|
||||||
parent_sym := g.table.sym(sym.info.parent_type)
|
parent_sym := g.table.sym(sym.info.parent_type)
|
||||||
if parent_sym.has_method('str') {
|
if parent_sym.has_method('str') {
|
||||||
typ = sym.info.parent_type
|
typ = sym.info.parent_type
|
||||||
sym = parent_sym
|
sym = unsafe { parent_sym }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
sym_has_str_method, str_method_expects_ptr, _ := sym.str_method_info()
|
sym_has_str_method, str_method_expects_ptr, _ := sym.str_method_info()
|
||||||
|
|
|
@ -2,9 +2,8 @@ const abc = 12
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
println('ok')
|
println('ok')
|
||||||
for x := abc; x<15;x++ {
|
for x := abc; x < 15; x++ {
|
||||||
println(x)
|
println(x)
|
||||||
}
|
}
|
||||||
println('ok')
|
println('ok')
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -160,7 +160,7 @@ pub fn (root &TrieNode) find(word string) int {
|
||||||
if child == unsafe { nil } {
|
if child == unsafe { nil } {
|
||||||
return -1
|
return -1
|
||||||
}
|
}
|
||||||
node = child
|
node = unsafe { child }
|
||||||
idx++
|
idx++
|
||||||
}
|
}
|
||||||
return -1
|
return -1
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue