mirror of
https://github.com/vlang/v.git
synced 2025-09-18 11:56:57 -04:00
checker: fix checking of expression as mut receiver, when calling methods of arrays/maps (#20410)
This commit is contained in:
parent
a321ef694b
commit
3d8425dafd
@ -2066,10 +2066,7 @@ fn (mut c Checker) method_call(mut node ast.CallExpr) ast.Type {
|
||||
node.pos)
|
||||
}
|
||||
if method.params[0].is_mut {
|
||||
to_lock, pos := c.fail_if_immutable(mut node.left)
|
||||
if !node.left.is_lvalue() {
|
||||
c.error('cannot pass expression as `mut`', node.left.pos())
|
||||
}
|
||||
to_lock, pos := c.check_for_mut_receiver(mut node.left)
|
||||
// node.is_mut = true
|
||||
if to_lock != '' && rec_share != .shared_t {
|
||||
c.error('${to_lock} is `shared` and must be `lock`ed to be passed as `mut`',
|
||||
@ -2684,7 +2681,7 @@ fn (mut c Checker) map_builtin_method_call(mut node ast.CallExpr, left_type_ ast
|
||||
c.error('`.${method_name}()` does not have any arguments', node.args[0].pos)
|
||||
}
|
||||
if method_name[0] == `m` {
|
||||
c.fail_if_immutable(mut node.left)
|
||||
c.check_for_mut_receiver(mut node.left)
|
||||
}
|
||||
if node.left.is_auto_deref_var() || left_type.has_flag(.shared_f) {
|
||||
ret_type = node.left_type.deref()
|
||||
@ -2712,7 +2709,7 @@ fn (mut c Checker) map_builtin_method_call(mut node ast.CallExpr, left_type_ ast
|
||||
}
|
||||
}
|
||||
'delete' {
|
||||
c.fail_if_immutable(mut node.left)
|
||||
c.check_for_mut_receiver(mut node.left)
|
||||
if node.args.len != 1 {
|
||||
c.error('expected 1 argument, but got ${node.args.len}', node.pos)
|
||||
}
|
||||
@ -2789,7 +2786,7 @@ fn (mut c Checker) array_builtin_method_call(mut node ast.CallExpr, left_type as
|
||||
c.error('the `sort()` method can be called only on mutable receivers, but `${node.left}` is a call expression',
|
||||
node.pos)
|
||||
}
|
||||
c.fail_if_immutable(mut node.left)
|
||||
c.check_for_mut_receiver(mut node.left)
|
||||
}
|
||||
// position of `a` and `b` doesn't matter, they're the same
|
||||
scope_register_a_b(mut node.scope, node.pos, elem_typ)
|
||||
@ -2943,13 +2940,13 @@ fn (mut c Checker) array_builtin_method_call(mut node ast.CallExpr, left_type as
|
||||
}
|
||||
node.return_type = array_info.elem_type
|
||||
if method_name == 'pop' {
|
||||
c.fail_if_immutable(mut node.left)
|
||||
c.check_for_mut_receiver(mut node.left)
|
||||
node.receiver_type = node.left_type.ref()
|
||||
} else {
|
||||
node.receiver_type = node.left_type
|
||||
}
|
||||
} else if method_name == 'delete' {
|
||||
c.fail_if_immutable(mut node.left)
|
||||
c.check_for_mut_receiver(mut node.left)
|
||||
unwrapped_left_sym := c.table.sym(unwrapped_left_type)
|
||||
if method := c.table.find_method(unwrapped_left_sym, method_name) {
|
||||
node.receiver_type = method.receiver_type
|
||||
@ -2959,6 +2956,14 @@ fn (mut c Checker) array_builtin_method_call(mut node ast.CallExpr, left_type as
|
||||
return node.return_type
|
||||
}
|
||||
|
||||
fn (mut c Checker) check_for_mut_receiver(mut expr ast.Expr) (string, token.Pos) {
|
||||
to_lock, pos := c.fail_if_immutable(mut expr)
|
||||
if !expr.is_lvalue() {
|
||||
c.error('cannot pass expression as `mut`', expr.pos())
|
||||
}
|
||||
return to_lock, pos
|
||||
}
|
||||
|
||||
fn scope_register_it(mut s ast.Scope, pos token.Pos, typ ast.Type) {
|
||||
scope_register_var_name(mut s, pos, typ, 'it')
|
||||
}
|
||||
|
@ -4,3 +4,9 @@ vlib/v/checker/tests/fn_return_array_sort_err.vv:6:14: error: the `sort()` metho
|
||||
6 | ret_array().sort()
|
||||
| ~~~~~~
|
||||
7 | }
|
||||
vlib/v/checker/tests/fn_return_array_sort_err.vv:6:2: error: cannot pass expression as `mut`
|
||||
4 |
|
||||
5 | fn main() {
|
||||
6 | ret_array().sort()
|
||||
| ~~~~~~~~~~~
|
||||
7 | }
|
||||
|
@ -1,5 +1,20 @@
|
||||
vlib/v/checker/tests/mut_receiver_lit.vv:10:1: error: cannot pass expression as `mut`
|
||||
8 | }
|
||||
9 |
|
||||
10 | Box{}.set(0)
|
||||
| ~~~~~
|
||||
vlib/v/checker/tests/mut_receiver_lit.vv:12:2: error: cannot pass expression as `mut`
|
||||
10 |
|
||||
11 | fn non_mut_receiver() {
|
||||
12 | Box{}.set(0)
|
||||
| ~~~~~
|
||||
13 | }
|
||||
14 |
|
||||
vlib/v/checker/tests/mut_receiver_lit.vv:18:11: error: cannot pass expression as `mut`
|
||||
16 | fn array_chained_method_calls() {
|
||||
17 | path := 'hello/file.txt'
|
||||
18 | _ = path.split('.').pop()
|
||||
| ~~~~~~~~~~
|
||||
19 | }
|
||||
20 |
|
||||
vlib/v/checker/tests/mut_receiver_lit.vv:24:4: error: cannot pass expression as `mut`
|
||||
22 | fn map_chained_method_calls() {
|
||||
23 | mut m := map[int]int{}
|
||||
24 | m.clone().delete(0)
|
||||
| ~~~~~~~
|
||||
25 | }
|
||||
|
@ -1,3 +1,4 @@
|
||||
// error in non-mut as receover
|
||||
struct Box {
|
||||
mut:
|
||||
value int
|
||||
@ -7,4 +8,18 @@ fn (mut box Box) set(value int) {
|
||||
box.value = value
|
||||
}
|
||||
|
||||
Box{}.set(0)
|
||||
fn non_mut_receiver() {
|
||||
Box{}.set(0)
|
||||
}
|
||||
|
||||
// error in array chained method calls
|
||||
fn array_chained_method_calls() {
|
||||
path := 'hello/file.txt'
|
||||
_ = path.split('.').pop()
|
||||
}
|
||||
|
||||
// error in map chained method calls
|
||||
fn map_chained_method_calls() {
|
||||
mut m := map[int]int{}
|
||||
m.clone().delete(0)
|
||||
}
|
||||
|
@ -2,6 +2,6 @@
|
||||
// Phenomenon: cgen brackets are asymmetric in chained method calls.
|
||||
fn test_main() {
|
||||
mut path := 'hello/file.txt'
|
||||
extension := path.split('.').pop()
|
||||
extension := path.split('.').last()
|
||||
assert extension == 'txt'
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user