mirror of
https://github.com/vlang/v.git
synced 2023-08-10 21:13:21 +03:00
map: add move
method (#8660)
This commit is contained in:
parent
65f2420516
commit
84a16d8684
@ -207,7 +207,7 @@ pub struct map {
|
||||
mut:
|
||||
// Highest even index in the hashtable
|
||||
even_index u32
|
||||
// Number of cached hashbits left for rehasing
|
||||
// Number of cached hashbits left for rehashing
|
||||
cached_hashbits byte
|
||||
// Used for right-shifting out used hashbits
|
||||
shift byte
|
||||
@ -346,6 +346,14 @@ fn new_map_init_2(hash_fn MapHashFn, key_eq_fn MapEqFn, clone_fn MapCloneFn, fre
|
||||
return out
|
||||
}
|
||||
|
||||
pub fn (mut m map) move() map {
|
||||
r := *m
|
||||
unsafe {
|
||||
C.memset(m, 0, sizeof(map))
|
||||
}
|
||||
return r
|
||||
}
|
||||
|
||||
[inline]
|
||||
fn (m &map) key_to_index(pkey voidptr) (u32, u32) {
|
||||
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
|
||||
}
|
||||
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
|
||||
match method_name {
|
||||
'clone' {
|
||||
'clone', 'move' {
|
||||
if method_name[0] == `m` {
|
||||
c.fail_if_immutable(call_expr.left)
|
||||
}
|
||||
ret_type = left_type
|
||||
}
|
||||
'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]
|
||||
&& right_sym.kind == .map && (left is ast.Ident && !left.is_blank_ident())
|
||||
&& right is ast.Ident {
|
||||
// Do not allow `a = b`, only `a = b.clone()`
|
||||
c.error('use `map2 $assign_stmt.op.str() map1.clone()` instead of `map2 $assign_stmt.op.str() map1` (or use `unsafe`)',
|
||||
assign_stmt.pos)
|
||||
// Do not allow `a = b`
|
||||
c.error('cannot copy map: call `move` or `clone` method first (or use `unsafe`)',
|
||||
right.position())
|
||||
}
|
||||
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 {
|
||||
|
@ -10,18 +10,19 @@ vlib/v/checker/tests/array_or_map_assign_err.vv:5:5: error: use `array2 = array1
|
||||
4 | mut a3 := []int{}
|
||||
5 | a3 = a1
|
||||
| ^
|
||||
6 |
|
||||
6 |
|
||||
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`)
|
||||
6 |
|
||||
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 |
|
||||
7 | m1 := {'one': 1}
|
||||
8 | m2 := m1
|
||||
| ~~
|
||||
| ~~
|
||||
9 | mut m3 := map[string]int{}
|
||||
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
|
||||
9 | mut m3 := map[string]int{}
|
||||
10 | m3 = m1
|
||||
| ^
|
||||
11 | }
|
||||
| ~~
|
||||
11 |
|
||||
12 | _ = a2
|
||||
|
@ -8,4 +8,7 @@ fn main() {
|
||||
m2 := m1
|
||||
mut m3 := map[string]int{}
|
||||
m3 = m1
|
||||
|
||||
_ = a2
|
||||
_ = m2
|
||||
}
|
||||
|
27
vlib/v/checker/tests/immutable_map.out
Normal file
27
vlib/v/checker/tests/immutable_map.out
Normal file
@ -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['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)
|
||||
}
|
||||
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'
|
||||
}
|
||||
// TODO performance, detect `array` method differently
|
||||
|
Loading…
Reference in New Issue
Block a user