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.stmts(call_expr.or_block.stmts)
|
||||
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
|
||||
}
|
||||
|
||||
|
@ -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)
|
||||
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
|
||||
return f.return_type
|
||||
}
|
||||
|
@ -3877,7 +3885,9 @@ pub fn (mut c Checker) ident(mut ident ast.Ident) table.Type {
|
|||
ast.ConstField {
|
||||
mut typ := obj.typ
|
||||
if typ == 0 {
|
||||
c.inside_const = true
|
||||
typ = c.expr(obj.expr)
|
||||
c.inside_const = false
|
||||
if obj.expr is ast.CallExpr {
|
||||
if obj.expr.or_block.kind != .absent {
|
||||
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`
|
||||
9 | abc := 'print'
|
||||
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'
|
||||
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`
|
||||
15 | test.$s()
|
||||
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()
|
||||
}
|
||||
|
||||
fn xx_prop() ?string {
|
||||
s := ret(raise() ?)
|
||||
return s
|
||||
}
|
||||
|
||||
fn test_nested_propagation() {
|
||||
a := xx_prop() or { 'propagated' }
|
||||
assert a == 'propagated'
|
||||
}
|
||||
|
||||
struct St {
|
||||
mut:
|
||||
z f64
|
||||
|
@ -41,3 +51,19 @@ fn test_nested_or_method_call() {
|
|||
x.aa()
|
||||
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