mirror of
https://github.com/vlang/v.git
synced 2025-09-17 11:26:17 -04:00
v: unwrap an option value automatically, inside if o != none {
(#20275)
This commit is contained in:
parent
34858c3265
commit
b944927f09
@ -515,6 +515,9 @@ fn (mut c Checker) smartcast_if_conds(mut node ast.Expr, mut scope ast.Scope) {
|
||||
if node.op == .and {
|
||||
c.smartcast_if_conds(mut node.left, mut scope)
|
||||
c.smartcast_if_conds(mut node.right, mut scope)
|
||||
} else if node.left is ast.Ident && node.op == .ne && node.right is ast.None {
|
||||
c.smartcast(mut node.left, node.left_type, node.left_type.clear_flag(.option), mut
|
||||
scope)
|
||||
} else if node.op == .key_is {
|
||||
right_expr := node.right
|
||||
right_type := match right_expr {
|
||||
|
@ -4495,19 +4495,27 @@ fn (mut g Gen) ident(node ast.Ident) {
|
||||
if node.obj.smartcasts.len > 0 {
|
||||
obj_sym := g.table.sym(node.obj.typ)
|
||||
if !prevent_sum_type_unwrapping_once {
|
||||
for _ in node.obj.smartcasts {
|
||||
for _, typ in node.obj.smartcasts {
|
||||
is_option_unwrap := is_option && typ == node.obj.typ.clear_flag(.option)
|
||||
g.write('(')
|
||||
if obj_sym.kind == .sum_type && !is_auto_heap {
|
||||
g.write('*')
|
||||
if is_option {
|
||||
if !is_option_unwrap {
|
||||
g.write('*(')
|
||||
}
|
||||
styp := g.base_type(node.obj.typ)
|
||||
g.write('(*(${styp}*)')
|
||||
g.write('*(${styp}*)')
|
||||
} else {
|
||||
g.write('*')
|
||||
}
|
||||
} else if g.inside_interface_deref && g.table.is_interface_var(node.obj) {
|
||||
g.write('*')
|
||||
} else if is_option {
|
||||
g.write('*(${g.base_type(node.obj.typ)}*)')
|
||||
}
|
||||
}
|
||||
for i, typ in node.obj.smartcasts {
|
||||
is_option_unwrap := is_option && typ == node.obj.typ.clear_flag(.option)
|
||||
cast_sym := g.table.sym(g.unwrap_generic(typ))
|
||||
if obj_sym.kind == .interface_ && cast_sym.kind == .interface_ {
|
||||
ptr := '*'.repeat(node.obj.typ.nr_muls())
|
||||
@ -4529,9 +4537,14 @@ fn (mut g Gen) ident(node ast.Ident) {
|
||||
g.write('${dot}_${sym.cname}')
|
||||
} else {
|
||||
if is_option {
|
||||
g.write('.data)')
|
||||
g.write('.data')
|
||||
if !is_option_unwrap {
|
||||
g.write(')')
|
||||
}
|
||||
}
|
||||
if !is_option_unwrap && obj_sym.kind in [.sum_type, .interface_] {
|
||||
g.write('${dot}_${cast_sym.cname}')
|
||||
}
|
||||
g.write('${dot}_${cast_sym.cname}')
|
||||
}
|
||||
}
|
||||
g.write(')')
|
||||
|
69
vlib/v/tests/option_cast_test.v
Normal file
69
vlib/v/tests/option_cast_test.v
Normal file
@ -0,0 +1,69 @@
|
||||
struct Test {
|
||||
a int
|
||||
}
|
||||
|
||||
type MySum = f64 | int
|
||||
|
||||
type MyAlias = Test
|
||||
|
||||
fn test_int() {
|
||||
a := ?int(1)
|
||||
if a != none {
|
||||
assert dump(a) == 1
|
||||
assert true
|
||||
} else {
|
||||
assert false
|
||||
}
|
||||
}
|
||||
|
||||
fn test_struct() {
|
||||
b := ?Test{
|
||||
a: 1
|
||||
}
|
||||
if b != none {
|
||||
assert dump(b) == Test{
|
||||
a: 1
|
||||
}
|
||||
assert true
|
||||
} else {
|
||||
assert false
|
||||
}
|
||||
}
|
||||
|
||||
fn test_string() {
|
||||
c := ?string('foo')
|
||||
if c != none {
|
||||
assert dump(c) == 'foo'
|
||||
assert true
|
||||
} else {
|
||||
assert false
|
||||
}
|
||||
}
|
||||
|
||||
fn test_sum_type() {
|
||||
d := ?MySum(1.2)
|
||||
assert d != none
|
||||
|
||||
if d != none {
|
||||
assert dump(d) == MySum(1.2)
|
||||
assert true
|
||||
} else {
|
||||
assert false
|
||||
}
|
||||
}
|
||||
|
||||
fn test_alias() {
|
||||
d := ?MyAlias(Test{
|
||||
a: 1
|
||||
})
|
||||
assert d != none
|
||||
|
||||
if d != none {
|
||||
assert dump(d) == Test{
|
||||
a: 1
|
||||
}
|
||||
assert true
|
||||
} else {
|
||||
assert false
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user