checker: check argument for `chan.try_push/pop()` (#9798)
parent
a45da620e6
commit
8ab0d42b5f
|
@ -2904,7 +2904,7 @@ println(l)
|
||||||
println(c)
|
println(c)
|
||||||
mut b := Abc{}
|
mut b := Abc{}
|
||||||
ch2 := chan Abc{}
|
ch2 := chan Abc{}
|
||||||
res2 := ch2.try_pop(b) // try to perform `b = <-ch2`
|
res2 := ch2.try_pop(mut b) // try to perform `b = <-ch2`
|
||||||
```
|
```
|
||||||
|
|
||||||
The `try_push/pop()` methods will return immediately with one of the results
|
The `try_push/pop()` methods will return immediately with one of the results
|
||||||
|
|
|
@ -18,7 +18,7 @@ fn do_rec(ch chan int, resch chan i64, n int) {
|
||||||
mut sum := i64(0)
|
mut sum := i64(0)
|
||||||
for _ in 0 .. n {
|
for _ in 0 .. n {
|
||||||
mut r := 0
|
mut r := 0
|
||||||
for ch.try_pop(r) != .success {
|
for ch.try_pop(mut r) != .success {
|
||||||
}
|
}
|
||||||
sum += r
|
sum += r
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,7 +7,7 @@ fn test_channel_try_buffered() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
mut obj := int(0)
|
mut obj := int(0)
|
||||||
for ch.try_pop(obj) == .success {
|
for ch.try_pop(mut obj) == .success {
|
||||||
println(obj)
|
println(obj)
|
||||||
}
|
}
|
||||||
assert obj == 6
|
assert obj == 6
|
||||||
|
|
|
@ -8,6 +8,6 @@ fn test_channel_try_unbuffered() {
|
||||||
panic('push on non-ready channel not detected')
|
panic('push on non-ready channel not detected')
|
||||||
}
|
}
|
||||||
mut obj := -17
|
mut obj := -17
|
||||||
for ch.try_pop(obj) == .success {}
|
for ch.try_pop(mut obj) == .success {}
|
||||||
assert obj == -17
|
assert obj == -17
|
||||||
}
|
}
|
||||||
|
|
|
@ -1612,22 +1612,44 @@ pub fn (mut c Checker) method_call(mut call_expr ast.CallExpr) ast.Type {
|
||||||
} else {
|
} else {
|
||||||
call_expr.return_type = method.return_type
|
call_expr.return_type = method.return_type
|
||||||
}
|
}
|
||||||
|
mut exp_arg_typ := ast.Type(0) // type of 1st arg for special builtin methods
|
||||||
|
mut param_is_mut := false
|
||||||
|
mut no_type_promotion := false
|
||||||
|
if left_type_sym.kind == .chan {
|
||||||
|
elem_typ := (left_type_sym.info as ast.Chan).elem_type
|
||||||
|
if method_name == 'try_push' {
|
||||||
|
exp_arg_typ = elem_typ.to_ptr()
|
||||||
|
} else if method_name == 'try_pop' {
|
||||||
|
exp_arg_typ = elem_typ
|
||||||
|
param_is_mut = true
|
||||||
|
no_type_promotion = true
|
||||||
|
}
|
||||||
|
}
|
||||||
// if method_name == 'clone' {
|
// if method_name == 'clone' {
|
||||||
// println('CLONE nr args=$method.args.len')
|
// println('CLONE nr args=$method.args.len')
|
||||||
// }
|
// }
|
||||||
// call_expr.args << method.args[0].typ
|
// call_expr.args << method.args[0].typ
|
||||||
// call_expr.exp_arg_types << method.args[0].typ
|
// call_expr.exp_arg_types << method.args[0].typ
|
||||||
for i, arg in call_expr.args {
|
for i, arg in call_expr.args {
|
||||||
exp_arg_typ := if method.is_variadic && i >= method.params.len - 1 {
|
if i > 0 || exp_arg_typ == ast.Type(0) {
|
||||||
method.params[method.params.len - 1].typ
|
exp_arg_typ = if method.is_variadic && i >= method.params.len - 1 {
|
||||||
} else {
|
method.params[method.params.len - 1].typ
|
||||||
method.params[i + 1].typ
|
} else {
|
||||||
|
method.params[i + 1].typ
|
||||||
|
}
|
||||||
|
param_is_mut = false
|
||||||
|
no_type_promotion = false
|
||||||
}
|
}
|
||||||
exp_arg_sym := c.table.get_type_symbol(exp_arg_typ)
|
exp_arg_sym := c.table.get_type_symbol(exp_arg_typ)
|
||||||
c.expected_type = exp_arg_typ
|
c.expected_type = exp_arg_typ
|
||||||
got_arg_typ := c.check_expr_opt_call(arg.expr, c.expr(arg.expr))
|
got_arg_typ := c.check_expr_opt_call(arg.expr, c.expr(arg.expr))
|
||||||
call_expr.args[i].typ = got_arg_typ
|
call_expr.args[i].typ = got_arg_typ
|
||||||
|
if no_type_promotion {
|
||||||
|
if got_arg_typ != exp_arg_typ {
|
||||||
|
c.error('cannot use `${c.table.get_type_symbol(got_arg_typ).name}` as argument for `$method.name` (`$exp_arg_sym.name` expected)',
|
||||||
|
arg.pos)
|
||||||
|
}
|
||||||
|
}
|
||||||
if method.is_variadic && got_arg_typ.has_flag(.variadic) && call_expr.args.len - 1 > i {
|
if method.is_variadic && got_arg_typ.has_flag(.variadic) && call_expr.args.len - 1 > i {
|
||||||
c.error('when forwarding a variadic variable, it must be the final argument',
|
c.error('when forwarding a variadic variable, it must be the final argument',
|
||||||
arg.pos)
|
arg.pos)
|
||||||
|
@ -1656,6 +1678,7 @@ pub fn (mut c Checker) method_call(mut call_expr ast.CallExpr) ast.Type {
|
||||||
} else {
|
} else {
|
||||||
method.params[i + 1]
|
method.params[i + 1]
|
||||||
}
|
}
|
||||||
|
param_is_mut = param_is_mut || param.is_mut
|
||||||
param_share := param.typ.share()
|
param_share := param.typ.share()
|
||||||
if param_share == .shared_t && (c.locked_names.len > 0 || c.rlocked_names.len > 0) {
|
if param_share == .shared_t && (c.locked_names.len > 0 || c.rlocked_names.len > 0) {
|
||||||
c.error('method with `shared` arguments cannot be called inside `lock`/`rlock` block',
|
c.error('method with `shared` arguments cannot be called inside `lock`/`rlock` block',
|
||||||
|
@ -1663,12 +1686,12 @@ pub fn (mut c Checker) method_call(mut call_expr ast.CallExpr) ast.Type {
|
||||||
}
|
}
|
||||||
if arg.is_mut {
|
if arg.is_mut {
|
||||||
to_lock, pos := c.fail_if_immutable(arg.expr)
|
to_lock, pos := c.fail_if_immutable(arg.expr)
|
||||||
if !param.is_mut {
|
if !param_is_mut {
|
||||||
tok := arg.share.str()
|
tok := arg.share.str()
|
||||||
c.error('`$call_expr.name` parameter `$param.name` is not `$tok`, `$tok` is not needed`',
|
c.error('`$call_expr.name` parameter `$param.name` is not `$tok`, `$tok` is not needed`',
|
||||||
arg.expr.position())
|
arg.expr.position())
|
||||||
} else {
|
} else {
|
||||||
if param.typ.share() != arg.share {
|
if param_share != arg.share {
|
||||||
c.error('wrong shared type', arg.expr.position())
|
c.error('wrong shared type', arg.expr.position())
|
||||||
}
|
}
|
||||||
if to_lock != '' && param_share != .shared_t {
|
if to_lock != '' && param_share != .shared_t {
|
||||||
|
@ -1677,7 +1700,7 @@ pub fn (mut c Checker) method_call(mut call_expr ast.CallExpr) ast.Type {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if param.is_mut {
|
if param_is_mut {
|
||||||
tok := arg.share.str()
|
tok := arg.share.str()
|
||||||
c.error('`$call_expr.name` parameter `$param.name` is `$tok`, you need to provide `$tok` e.g. `$tok arg${
|
c.error('`$call_expr.name` parameter `$param.name` is `$tok`, you need to provide `$tok` e.g. `$tok arg${
|
||||||
i + 1}`', arg.expr.position())
|
i + 1}`', arg.expr.position())
|
||||||
|
|
|
@ -0,0 +1,28 @@
|
||||||
|
vlib/v/checker/tests/chan_args.vv:4:19: error: cannot use `int` as `&f64` in argument 1 to `chan f64.try_push`
|
||||||
|
2 | ch := chan f64{cap: 5}
|
||||||
|
3 | a := 2
|
||||||
|
4 | _ := ch.try_push(a)
|
||||||
|
| ^
|
||||||
|
5 | _ := ch.try_push(2.5)
|
||||||
|
6 | b := 2.5
|
||||||
|
vlib/v/checker/tests/chan_args.vv:5:19: error: cannot use `float literal` as `&f64` in argument 1 to `chan f64.try_push`
|
||||||
|
3 | a := 2
|
||||||
|
4 | _ := ch.try_push(a)
|
||||||
|
5 | _ := ch.try_push(2.5)
|
||||||
|
| ~~~
|
||||||
|
6 | b := 2.5
|
||||||
|
7 | _ := ch.try_pop(b)
|
||||||
|
vlib/v/checker/tests/chan_args.vv:7:18: error: `try_pop` parameter `obj` is `mut`, you need to provide `mut` e.g. `mut arg1`
|
||||||
|
5 | _ := ch.try_push(2.5)
|
||||||
|
6 | b := 2.5
|
||||||
|
7 | _ := ch.try_pop(b)
|
||||||
|
| ^
|
||||||
|
8 | // this should work:
|
||||||
|
9 | _ := ch.try_push(b)
|
||||||
|
vlib/v/checker/tests/chan_args.vv:11:22: error: cannot use `int` as argument for `try_pop` (`f64` expected)
|
||||||
|
9 | _ := ch.try_push(b)
|
||||||
|
10 | mut c := 7
|
||||||
|
11 | _ := ch.try_pop(mut c)
|
||||||
|
| ^
|
||||||
|
12 | mut x := 12.5
|
||||||
|
13 | // this should work:
|
|
@ -0,0 +1,15 @@
|
||||||
|
fn main() {
|
||||||
|
ch := chan f64{cap: 5}
|
||||||
|
a := 2
|
||||||
|
_ := ch.try_push(a)
|
||||||
|
_ := ch.try_push(2.5)
|
||||||
|
b := 2.5
|
||||||
|
_ := ch.try_pop(b)
|
||||||
|
// this should work:
|
||||||
|
_ := ch.try_push(b)
|
||||||
|
mut c := 7
|
||||||
|
_ := ch.try_pop(mut c)
|
||||||
|
mut x := 12.5
|
||||||
|
// this should work:
|
||||||
|
_ := ch.try_pop(mut x)
|
||||||
|
}
|
Loading…
Reference in New Issue