checker: support nested propagation cases `f(g() ?)` (#8447)
parent
19784ab89b
commit
9c82eec529
|
@ -1211,6 +1211,14 @@ pub fn (mut c Checker) call_expr(mut call_expr ast.CallExpr) table.Type {
|
||||||
c.expected_or_type = call_expr.return_type.clear_flag(.optional)
|
c.expected_or_type = call_expr.return_type.clear_flag(.optional)
|
||||||
c.stmts(call_expr.or_block.stmts)
|
c.stmts(call_expr.or_block.stmts)
|
||||||
c.expected_or_type = table.void_type
|
c.expected_or_type = table.void_type
|
||||||
|
if call_expr.or_block.kind == .propagate && !c.cur_fn.return_type.has_flag(.optional)
|
||||||
|
&& !c.inside_const {
|
||||||
|
cur_names := c.cur_fn.name.split('.')
|
||||||
|
if cur_names[cur_names.len - 1] != 'main' {
|
||||||
|
c.error('to propagate the optional call, `$c.cur_fn.name` must return an optional',
|
||||||
|
call_expr.or_block.pos)
|
||||||
|
}
|
||||||
|
}
|
||||||
return typ
|
return typ
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3707,7 +3715,7 @@ fn (mut c Checker) comptime_call(mut node ast.ComptimeCall) table.Type {
|
||||||
c.error('could not find method `$method_name`', node.method_pos)
|
c.error('could not find method `$method_name`', node.method_pos)
|
||||||
return table.void_type
|
return table.void_type
|
||||||
}
|
}
|
||||||
println(f.name + ' ' + c.table.type_to_str(f.return_type))
|
// println(f.name + ' ' + c.table.type_to_str(f.return_type))
|
||||||
node.result_type = f.return_type
|
node.result_type = f.return_type
|
||||||
return f.return_type
|
return f.return_type
|
||||||
}
|
}
|
||||||
|
@ -3877,7 +3885,9 @@ pub fn (mut c Checker) ident(mut ident ast.Ident) table.Type {
|
||||||
ast.ConstField {
|
ast.ConstField {
|
||||||
mut typ := obj.typ
|
mut typ := obj.typ
|
||||||
if typ == 0 {
|
if typ == 0 {
|
||||||
|
c.inside_const = true
|
||||||
typ = c.expr(obj.expr)
|
typ = c.expr(obj.expr)
|
||||||
|
c.inside_const = false
|
||||||
if obj.expr is ast.CallExpr {
|
if obj.expr is ast.CallExpr {
|
||||||
if obj.expr.or_block.kind != .absent {
|
if obj.expr.or_block.kind != .absent {
|
||||||
typ = typ.clear_flag(.optional)
|
typ = typ.clear_flag(.optional)
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
print void
|
|
||||||
vlib/v/checker/tests/comptime_call_no_unused_var.vv:11:8: error: unknown identifier `w`
|
vlib/v/checker/tests/comptime_call_no_unused_var.vv:11:8: error: unknown identifier `w`
|
||||||
9 | abc := 'print'
|
9 | abc := 'print'
|
||||||
10 | test.$abc() // OK
|
10 | test.$abc() // OK
|
||||||
|
@ -20,7 +19,7 @@ vlib/v/checker/tests/comptime_call_no_unused_var.vv:15:8: error: todo: not a str
|
||||||
| ^
|
| ^
|
||||||
16 | s2 := 'x'
|
16 | s2 := 'x'
|
||||||
17 | test.$s2()
|
17 | test.$s2()
|
||||||
details: v.ast.InfixExpr
|
Details: v.ast.InfixExpr
|
||||||
vlib/v/checker/tests/comptime_call_no_unused_var.vv:17:8: error: could not find method `x`
|
vlib/v/checker/tests/comptime_call_no_unused_var.vv:17:8: error: could not find method `x`
|
||||||
15 | test.$s()
|
15 | test.$s()
|
||||||
16 | s2 := 'x'
|
16 | s2 := 'x'
|
||||||
|
|
|
@ -0,0 +1,14 @@
|
||||||
|
vlib/v/checker/tests/optional_propagate_nested.vv:10:19: error: to propagate the optional call, `xx_prop` must return an optional
|
||||||
|
8 |
|
||||||
|
9 | fn xx_prop() string {
|
||||||
|
10 | s := ret(raise() ?)
|
||||||
|
| ^
|
||||||
|
11 | return s
|
||||||
|
12 | }
|
||||||
|
vlib/v/checker/tests/optional_propagate_nested.vv:28:22: error: to propagate the optional call, `aa_propagate` must return an optional
|
||||||
|
26 |
|
||||||
|
27 | fn (mut s St) aa_propagate() {
|
||||||
|
28 | f := retf(s.raise() ?)
|
||||||
|
| ^
|
||||||
|
29 | s.z = 7.5
|
||||||
|
30 | println(f)
|
|
@ -0,0 +1,31 @@
|
||||||
|
fn ret(s string) string {
|
||||||
|
return s
|
||||||
|
}
|
||||||
|
|
||||||
|
fn raise() ?string {
|
||||||
|
return none
|
||||||
|
}
|
||||||
|
|
||||||
|
fn xx_prop() string {
|
||||||
|
s := ret(raise() ?)
|
||||||
|
return s
|
||||||
|
}
|
||||||
|
|
||||||
|
struct St {
|
||||||
|
mut:
|
||||||
|
z f64
|
||||||
|
}
|
||||||
|
|
||||||
|
fn (mut s St) raise() ?f64 {
|
||||||
|
return error('some error')
|
||||||
|
}
|
||||||
|
|
||||||
|
fn retf(f f64) f64 {
|
||||||
|
return f
|
||||||
|
}
|
||||||
|
|
||||||
|
fn (mut s St) aa_propagate() {
|
||||||
|
f := retf(s.raise() ?)
|
||||||
|
s.z = 7.5
|
||||||
|
println(f)
|
||||||
|
}
|
|
@ -15,6 +15,16 @@ fn test_nested_or() {
|
||||||
xx()
|
xx()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn xx_prop() ?string {
|
||||||
|
s := ret(raise() ?)
|
||||||
|
return s
|
||||||
|
}
|
||||||
|
|
||||||
|
fn test_nested_propagation() {
|
||||||
|
a := xx_prop() or { 'propagated' }
|
||||||
|
assert a == 'propagated'
|
||||||
|
}
|
||||||
|
|
||||||
struct St {
|
struct St {
|
||||||
mut:
|
mut:
|
||||||
z f64
|
z f64
|
||||||
|
@ -41,3 +51,19 @@ fn test_nested_or_method_call() {
|
||||||
x.aa()
|
x.aa()
|
||||||
assert x.z == 2.25
|
assert x.z == 2.25
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn (mut s St) aa_propagate() ? {
|
||||||
|
f := retf(s.raise() ?)
|
||||||
|
s.z = 7.5
|
||||||
|
println(f)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn test_nested_propagation_method() {
|
||||||
|
mut x := St{
|
||||||
|
z: 2.25
|
||||||
|
}
|
||||||
|
x.aa_propagate() or {
|
||||||
|
x.z = 13.0625
|
||||||
|
}
|
||||||
|
assert x.z == 13.0625
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue