map: add `move` method (#8660)
parent
65f2420516
commit
84a16d8684
|
@ -207,7 +207,7 @@ pub struct map {
|
||||||
mut:
|
mut:
|
||||||
// Highest even index in the hashtable
|
// Highest even index in the hashtable
|
||||||
even_index u32
|
even_index u32
|
||||||
// Number of cached hashbits left for rehasing
|
// Number of cached hashbits left for rehashing
|
||||||
cached_hashbits byte
|
cached_hashbits byte
|
||||||
// Used for right-shifting out used hashbits
|
// Used for right-shifting out used hashbits
|
||||||
shift byte
|
shift byte
|
||||||
|
@ -346,6 +346,14 @@ fn new_map_init_2(hash_fn MapHashFn, key_eq_fn MapEqFn, clone_fn MapCloneFn, fre
|
||||||
return out
|
return out
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn (mut m map) move() map {
|
||||||
|
r := *m
|
||||||
|
unsafe {
|
||||||
|
C.memset(m, 0, sizeof(map))
|
||||||
|
}
|
||||||
|
return r
|
||||||
|
}
|
||||||
|
|
||||||
[inline]
|
[inline]
|
||||||
fn (m &map) key_to_index(pkey voidptr) (u32, u32) {
|
fn (m &map) key_to_index(pkey voidptr) (u32, u32) {
|
||||||
hash := m.hash_fn(pkey)
|
hash := m.hash_fn(pkey)
|
||||||
|
|
|
@ -1442,10 +1442,13 @@ pub fn (mut c Checker) call_method(mut call_expr ast.CallExpr) table.Type {
|
||||||
call_expr.return_type = table.int_type
|
call_expr.return_type = table.int_type
|
||||||
}
|
}
|
||||||
return call_expr.return_type
|
return call_expr.return_type
|
||||||
} else if left_type_sym.kind == .map && method_name in ['clone', 'keys'] {
|
} else if left_type_sym.kind == .map && method_name in ['clone', 'keys', 'move'] {
|
||||||
mut ret_type := table.void_type
|
mut ret_type := table.void_type
|
||||||
match method_name {
|
match method_name {
|
||||||
'clone' {
|
'clone', 'move' {
|
||||||
|
if method_name[0] == `m` {
|
||||||
|
c.fail_if_immutable(call_expr.left)
|
||||||
|
}
|
||||||
ret_type = left_type
|
ret_type = left_type
|
||||||
}
|
}
|
||||||
'keys' {
|
'keys' {
|
||||||
|
@ -2737,9 +2740,9 @@ pub fn (mut c Checker) assign_stmt(mut assign_stmt ast.AssignStmt) {
|
||||||
if left_sym.kind == .map && !c.inside_unsafe && assign_stmt.op in [.assign, .decl_assign]
|
if left_sym.kind == .map && !c.inside_unsafe && assign_stmt.op in [.assign, .decl_assign]
|
||||||
&& right_sym.kind == .map && (left is ast.Ident && !left.is_blank_ident())
|
&& right_sym.kind == .map && (left is ast.Ident && !left.is_blank_ident())
|
||||||
&& right is ast.Ident {
|
&& right is ast.Ident {
|
||||||
// Do not allow `a = b`, only `a = b.clone()`
|
// Do not allow `a = b`
|
||||||
c.error('use `map2 $assign_stmt.op.str() map1.clone()` instead of `map2 $assign_stmt.op.str() map1` (or use `unsafe`)',
|
c.error('cannot copy map: call `move` or `clone` method first (or use `unsafe`)',
|
||||||
assign_stmt.pos)
|
right.position())
|
||||||
}
|
}
|
||||||
left_is_ptr := left_type.is_ptr() || left_sym.is_pointer()
|
left_is_ptr := left_type.is_ptr() || left_sym.is_pointer()
|
||||||
if left_is_ptr && c.for_in_mut_val_name != left.str() && left.str() !in c.fn_mut_arg_names {
|
if left_is_ptr && c.for_in_mut_val_name != left.str() && left.str() !in c.fn_mut_arg_names {
|
||||||
|
|
|
@ -12,16 +12,17 @@ vlib/v/checker/tests/array_or_map_assign_err.vv:5:5: error: use `array2 = array1
|
||||||
| ^
|
| ^
|
||||||
6 |
|
6 |
|
||||||
7 | m1 := {'one': 1}
|
7 | m1 := {'one': 1}
|
||||||
vlib/v/checker/tests/array_or_map_assign_err.vv:8:5: error: use `map2 := map1.clone()` instead of `map2 := map1` (or use `unsafe`)
|
vlib/v/checker/tests/array_or_map_assign_err.vv:8:8: error: cannot copy map: call `move` or `clone` method first (or use `unsafe`)
|
||||||
6 |
|
6 |
|
||||||
7 | m1 := {'one': 1}
|
7 | m1 := {'one': 1}
|
||||||
8 | m2 := m1
|
8 | m2 := m1
|
||||||
| ~~
|
| ~~
|
||||||
9 | mut m3 := map[string]int{}
|
9 | mut m3 := map[string]int{}
|
||||||
10 | m3 = m1
|
10 | m3 = m1
|
||||||
vlib/v/checker/tests/array_or_map_assign_err.vv:10:5: error: use `map2 = map1.clone()` instead of `map2 = map1` (or use `unsafe`)
|
vlib/v/checker/tests/array_or_map_assign_err.vv:10:7: error: cannot copy map: call `move` or `clone` method first (or use `unsafe`)
|
||||||
8 | m2 := m1
|
8 | m2 := m1
|
||||||
9 | mut m3 := map[string]int{}
|
9 | mut m3 := map[string]int{}
|
||||||
10 | m3 = m1
|
10 | m3 = m1
|
||||||
| ^
|
| ~~
|
||||||
11 | }
|
11 |
|
||||||
|
12 | _ = a2
|
||||||
|
|
|
@ -8,4 +8,7 @@ fn main() {
|
||||||
m2 := m1
|
m2 := m1
|
||||||
mut m3 := map[string]int{}
|
mut m3 := map[string]int{}
|
||||||
m3 = m1
|
m3 = m1
|
||||||
|
|
||||||
|
_ = a2
|
||||||
|
_ = m2
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,27 @@
|
||||||
|
vlib/v/checker/tests/immutable_map.vv:3:2: error: `m` is immutable, declare it with `mut` to make it mutable
|
||||||
|
1 | fn main() {
|
||||||
|
2 | m := map[string]int
|
||||||
|
3 | m['test']++
|
||||||
|
| ^
|
||||||
|
4 | m['test']--
|
||||||
|
5 | _ = m.move()
|
||||||
|
vlib/v/checker/tests/immutable_map.vv:4:2: error: `m` is immutable, declare it with `mut` to make it mutable
|
||||||
|
2 | m := map[string]int
|
||||||
|
3 | m['test']++
|
||||||
|
4 | m['test']--
|
||||||
|
| ^
|
||||||
|
5 | _ = m.move()
|
||||||
|
6 | m.delete('s')
|
||||||
|
vlib/v/checker/tests/immutable_map.vv:5:6: error: `m` is immutable, declare it with `mut` to make it mutable
|
||||||
|
3 | m['test']++
|
||||||
|
4 | m['test']--
|
||||||
|
5 | _ = m.move()
|
||||||
|
| ^
|
||||||
|
6 | m.delete('s')
|
||||||
|
7 | }
|
||||||
|
vlib/v/checker/tests/immutable_map.vv:6:2: error: `m` is immutable, declare it with `mut` to make it mutable
|
||||||
|
4 | m['test']--
|
||||||
|
5 | _ = m.move()
|
||||||
|
6 | m.delete('s')
|
||||||
|
| ^
|
||||||
|
7 | }
|
|
@ -2,4 +2,6 @@ fn main() {
|
||||||
m := map[string]int
|
m := map[string]int
|
||||||
m['test']++
|
m['test']++
|
||||||
m['test']--
|
m['test']--
|
||||||
|
_ = m.move()
|
||||||
|
m.delete('s')
|
||||||
}
|
}
|
|
@ -1,13 +0,0 @@
|
||||||
vlib/v/checker/tests/immutable_map_postfix.vv:3:2: error: `m` is immutable, declare it with `mut` to make it mutable
|
|
||||||
1 | fn main() {
|
|
||||||
2 | m := map[string]int
|
|
||||||
3 | m['test']++
|
|
||||||
| ^
|
|
||||||
4 | m['test']--
|
|
||||||
5 | }
|
|
||||||
vlib/v/checker/tests/immutable_map_postfix.vv:4:2: error: `m` is immutable, declare it with `mut` to make it mutable
|
|
||||||
2 | m := map[string]int
|
|
||||||
3 | m['test']++
|
|
||||||
4 | m['test']--
|
|
||||||
| ^
|
|
||||||
5 | }
|
|
|
@ -479,7 +479,7 @@ fn (mut g Gen) method_call(node ast.CallExpr) {
|
||||||
g.gen_str_for_type(node.receiver_type)
|
g.gen_str_for_type(node.receiver_type)
|
||||||
}
|
}
|
||||||
mut has_cast := false
|
mut has_cast := false
|
||||||
if left_sym.kind == .map && node.name == 'clone' {
|
if left_sym.kind == .map && node.name in ['clone', 'move'] {
|
||||||
receiver_type_name = 'map'
|
receiver_type_name = 'map'
|
||||||
}
|
}
|
||||||
// TODO performance, detect `array` method differently
|
// TODO performance, detect `array` method differently
|
||||||
|
|
Loading…
Reference in New Issue