checker: make optional arguments in func call an error (#9362)
parent
c8416f9a54
commit
f9bbc119aa
|
@ -1499,7 +1499,7 @@ pub fn (mut c Checker) call_method(mut call_expr ast.CallExpr) table.Type {
|
||||||
}
|
}
|
||||||
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.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 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',
|
||||||
|
@ -1634,7 +1634,7 @@ pub fn (mut c Checker) call_method(mut call_expr ast.CallExpr) table.Type {
|
||||||
call_expr.return_type = info.func.return_type
|
call_expr.return_type = info.func.return_type
|
||||||
mut earg_types := []table.Type{}
|
mut earg_types := []table.Type{}
|
||||||
for mut arg in call_expr.args {
|
for mut arg in call_expr.args {
|
||||||
targ := c.expr(arg.expr)
|
targ := c.check_expr_opt_call(arg.expr, c.expr(arg.expr))
|
||||||
arg.typ = targ
|
arg.typ = targ
|
||||||
earg_types << targ
|
earg_types << targ
|
||||||
}
|
}
|
||||||
|
@ -1732,7 +1732,7 @@ fn (mut c Checker) call_array_builtin_method(mut call_expr ast.CallExpr, left_ty
|
||||||
// map/filter are supposed to have 1 arg only
|
// map/filter are supposed to have 1 arg only
|
||||||
mut arg_type := left_type
|
mut arg_type := left_type
|
||||||
for arg in call_expr.args {
|
for arg in call_expr.args {
|
||||||
arg_type = c.expr(arg.expr)
|
arg_type = c.check_expr_opt_call(arg.expr, c.expr(arg.expr))
|
||||||
}
|
}
|
||||||
if method_name == 'map' {
|
if method_name == 'map' {
|
||||||
// check fn
|
// check fn
|
||||||
|
@ -2024,7 +2024,7 @@ pub fn (mut c Checker) call_fn(mut call_expr ast.CallExpr) table.Type {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
c.expected_type = arg.typ
|
c.expected_type = arg.typ
|
||||||
typ := c.expr(call_arg.expr)
|
typ := c.check_expr_opt_call(call_arg.expr, c.expr(call_arg.expr))
|
||||||
call_expr.args[i].typ = typ
|
call_expr.args[i].typ = typ
|
||||||
typ_sym := c.table.get_type_symbol(typ)
|
typ_sym := c.table.get_type_symbol(typ)
|
||||||
arg_typ_sym := c.table.get_type_symbol(arg.typ)
|
arg_typ_sym := c.table.get_type_symbol(arg.typ)
|
||||||
|
|
|
@ -1,20 +1,104 @@
|
||||||
vlib/v/checker/tests/optional_fn_err.vv:11:2: error: foo() returns an option, so it should have either an `or {}` block, or `?` at the end
|
vlib/v/checker/tests/optional_fn_err.vv:25:2: error: foo() returns an option, so it should have either an `or {}` block, or `?` at the end
|
||||||
9 | fn main() {
|
23 | fn main() {
|
||||||
10 | // Calling foo() without ? or an or block, should be an error.
|
24 | // Calling foo() without ? or an or block, should be an error.
|
||||||
11 | foo()
|
25 | foo()
|
||||||
| ~~~~~
|
| ~~~~~
|
||||||
12 |
|
26 |
|
||||||
13 | _ := bar()
|
27 | _ := bar(0)
|
||||||
vlib/v/checker/tests/optional_fn_err.vv:13:7: error: bar() returns an option, so it should have either an `or {}` block, or `?` at the end
|
vlib/v/checker/tests/optional_fn_err.vv:27:7: error: bar() returns an option, so it should have either an `or {}` block, or `?` at the end
|
||||||
11 | foo()
|
25 | foo()
|
||||||
12 |
|
26 |
|
||||||
13 | _ := bar()
|
27 | _ := bar(0)
|
||||||
| ~~~~~
|
| ~~~~~~
|
||||||
14 | _ := [bar()]
|
28 | _ := [bar(0)]
|
||||||
15 | }
|
29 |
|
||||||
vlib/v/checker/tests/optional_fn_err.vv:14:8: error: bar() returns an option, so it should have either an `or {}` block, or `?` at the end
|
vlib/v/checker/tests/optional_fn_err.vv:28:8: error: bar() returns an option, so it should have either an `or {}` block, or `?` at the end
|
||||||
12 |
|
26 |
|
||||||
13 | _ := bar()
|
27 | _ := bar(0)
|
||||||
14 | _ := [bar()]
|
28 | _ := [bar(0)]
|
||||||
| ~~~~~
|
| ~~~~~~
|
||||||
15 | }
|
29 |
|
||||||
|
30 | // Calling fn with optional argument
|
||||||
|
vlib/v/checker/tests/optional_fn_err.vv:31:16: error: bar() returns an option, so it should have either an `or {}` block, or `?` at the end
|
||||||
|
29 |
|
||||||
|
30 | // Calling fn with optional argument
|
||||||
|
31 | println(twice(bar(0)))
|
||||||
|
| ~~~~~~
|
||||||
|
32 | // method and fn field
|
||||||
|
33 | mut v := Data{fn (_ int) {}, 1}
|
||||||
|
vlib/v/checker/tests/optional_fn_err.vv:34:8: error: bar() returns an option, so it should have either an `or {}` block, or `?` at the end
|
||||||
|
32 | // method and fn field
|
||||||
|
33 | mut v := Data{fn (_ int) {}, 1}
|
||||||
|
34 | v.add(bar(0))
|
||||||
|
| ~~~~~~
|
||||||
|
35 | v.f(bar(0))
|
||||||
|
36 | // anon fn
|
||||||
|
vlib/v/checker/tests/optional_fn_err.vv:35:6: error: bar() returns an option, so it should have either an `or {}` block, or `?` at the end
|
||||||
|
33 | mut v := Data{fn (_ int) {}, 1}
|
||||||
|
34 | v.add(bar(0))
|
||||||
|
35 | v.f(bar(0))
|
||||||
|
| ~~~~~~
|
||||||
|
36 | // anon fn
|
||||||
|
37 | fn (_ int) {}(bar(0))
|
||||||
|
vlib/v/checker/tests/optional_fn_err.vv:37:16: error: bar() returns an option, so it should have either an `or {}` block, or `?` at the end
|
||||||
|
35 | v.f(bar(0))
|
||||||
|
36 | // anon fn
|
||||||
|
37 | fn (_ int) {}(bar(0))
|
||||||
|
| ~~~~~~
|
||||||
|
38 | // array builtin methods
|
||||||
|
39 | mut arr := [1, 2]
|
||||||
|
vlib/v/checker/tests/optional_fn_err.vv:40:16: error: bar() returns an option, so it should have either an `or {}` block, or `?` at the end
|
||||||
|
38 | // array builtin methods
|
||||||
|
39 | mut arr := [1, 2]
|
||||||
|
40 | arr.insert(0, bar(0))
|
||||||
|
| ~~~~~~
|
||||||
|
41 | arr.prepend(bar(0))
|
||||||
|
42 | arr.contains(bar(0))
|
||||||
|
vlib/v/checker/tests/optional_fn_err.vv:41:14: error: bar() returns an option, so it should have either an `or {}` block, or `?` at the end
|
||||||
|
39 | mut arr := [1, 2]
|
||||||
|
40 | arr.insert(0, bar(0))
|
||||||
|
41 | arr.prepend(bar(0))
|
||||||
|
| ~~~~~~
|
||||||
|
42 | arr.contains(bar(0))
|
||||||
|
43 | arr.index(bar(0))
|
||||||
|
vlib/v/checker/tests/optional_fn_err.vv:42:15: error: bar() returns an option, so it should have either an `or {}` block, or `?` at the end
|
||||||
|
40 | arr.insert(0, bar(0))
|
||||||
|
41 | arr.prepend(bar(0))
|
||||||
|
42 | arr.contains(bar(0))
|
||||||
|
| ~~~~~~
|
||||||
|
43 | arr.index(bar(0))
|
||||||
|
44 | println(arr.map(bar(0)))
|
||||||
|
vlib/v/checker/tests/optional_fn_err.vv:43:12: error: bar() returns an option, so it should have either an `or {}` block, or `?` at the end
|
||||||
|
41 | arr.prepend(bar(0))
|
||||||
|
42 | arr.contains(bar(0))
|
||||||
|
43 | arr.index(bar(0))
|
||||||
|
| ~~~~~~
|
||||||
|
44 | println(arr.map(bar(0)))
|
||||||
|
45 | println(arr.filter(bar(true)))
|
||||||
|
vlib/v/checker/tests/optional_fn_err.vv:44:18: error: bar() returns an option, so it should have either an `or {}` block, or `?` at the end
|
||||||
|
42 | arr.contains(bar(0))
|
||||||
|
43 | arr.index(bar(0))
|
||||||
|
44 | println(arr.map(bar(0)))
|
||||||
|
| ~~~~~~
|
||||||
|
45 | println(arr.filter(bar(true)))
|
||||||
|
46 | println(arr.any(bar(true)))
|
||||||
|
vlib/v/checker/tests/optional_fn_err.vv:45:21: error: bar() returns an option, so it should have either an `or {}` block, or `?` at the end
|
||||||
|
43 | arr.index(bar(0))
|
||||||
|
44 | println(arr.map(bar(0)))
|
||||||
|
45 | println(arr.filter(bar(true)))
|
||||||
|
| ~~~~~~~~~
|
||||||
|
46 | println(arr.any(bar(true)))
|
||||||
|
47 | println(arr.all(bar(true)))
|
||||||
|
vlib/v/checker/tests/optional_fn_err.vv:46:18: error: bar() returns an option, so it should have either an `or {}` block, or `?` at the end
|
||||||
|
44 | println(arr.map(bar(0)))
|
||||||
|
45 | println(arr.filter(bar(true)))
|
||||||
|
46 | println(arr.any(bar(true)))
|
||||||
|
| ~~~~~~~~~
|
||||||
|
47 | println(arr.all(bar(true)))
|
||||||
|
48 | }
|
||||||
|
vlib/v/checker/tests/optional_fn_err.vv:47:18: error: bar() returns an option, so it should have either an `or {}` block, or `?` at the end
|
||||||
|
45 | println(arr.filter(bar(true)))
|
||||||
|
46 | println(arr.any(bar(true)))
|
||||||
|
47 | println(arr.all(bar(true)))
|
||||||
|
| ~~~~~~~~~
|
||||||
|
48 | }
|
||||||
|
|
|
@ -2,14 +2,47 @@ fn foo() ? {
|
||||||
println('foo is called')
|
println('foo is called')
|
||||||
}
|
}
|
||||||
|
|
||||||
fn bar() ?int {
|
fn bar<T>(v T) ?T {
|
||||||
return none
|
return none
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct Data {
|
||||||
|
f fn (int)
|
||||||
|
mut:
|
||||||
|
value int
|
||||||
|
}
|
||||||
|
|
||||||
|
fn (mut v Data) add(n int) {
|
||||||
|
v.value += n
|
||||||
|
}
|
||||||
|
|
||||||
|
fn twice(n int) int {
|
||||||
|
return n * 2
|
||||||
|
}
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
// Calling foo() without ? or an or block, should be an error.
|
// Calling foo() without ? or an or block, should be an error.
|
||||||
foo()
|
foo()
|
||||||
|
|
||||||
_ := bar()
|
_ := bar(0)
|
||||||
_ := [bar()]
|
_ := [bar(0)]
|
||||||
|
|
||||||
|
// Calling fn with optional argument
|
||||||
|
println(twice(bar(0)))
|
||||||
|
// method and fn field
|
||||||
|
mut v := Data{fn (_ int) {}, 1}
|
||||||
|
v.add(bar(0))
|
||||||
|
v.f(bar(0))
|
||||||
|
// anon fn
|
||||||
|
fn (_ int) {}(bar(0))
|
||||||
|
// array builtin methods
|
||||||
|
mut arr := [1, 2]
|
||||||
|
arr.insert(0, bar(0))
|
||||||
|
arr.prepend(bar(0))
|
||||||
|
arr.contains(bar(0))
|
||||||
|
arr.index(bar(0))
|
||||||
|
println(arr.map(bar(0)))
|
||||||
|
println(arr.filter(bar(true)))
|
||||||
|
println(arr.any(bar(true)))
|
||||||
|
println(arr.all(bar(true)))
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue