mirror of
https://github.com/vlang/v.git
synced 2025-09-17 03:17:25 -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 {
|
if node.op == .and {
|
||||||
c.smartcast_if_conds(mut node.left, mut scope)
|
c.smartcast_if_conds(mut node.left, mut scope)
|
||||||
c.smartcast_if_conds(mut node.right, 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 {
|
} else if node.op == .key_is {
|
||||||
right_expr := node.right
|
right_expr := node.right
|
||||||
right_type := match right_expr {
|
right_type := match right_expr {
|
||||||
|
@ -4495,19 +4495,27 @@ fn (mut g Gen) ident(node ast.Ident) {
|
|||||||
if node.obj.smartcasts.len > 0 {
|
if node.obj.smartcasts.len > 0 {
|
||||||
obj_sym := g.table.sym(node.obj.typ)
|
obj_sym := g.table.sym(node.obj.typ)
|
||||||
if !prevent_sum_type_unwrapping_once {
|
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('(')
|
g.write('(')
|
||||||
if obj_sym.kind == .sum_type && !is_auto_heap {
|
if obj_sym.kind == .sum_type && !is_auto_heap {
|
||||||
g.write('*')
|
|
||||||
if is_option {
|
if is_option {
|
||||||
|
if !is_option_unwrap {
|
||||||
|
g.write('*(')
|
||||||
|
}
|
||||||
styp := g.base_type(node.obj.typ)
|
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) {
|
} else if g.inside_interface_deref && g.table.is_interface_var(node.obj) {
|
||||||
g.write('*')
|
g.write('*')
|
||||||
|
} else if is_option {
|
||||||
|
g.write('*(${g.base_type(node.obj.typ)}*)')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for i, typ in node.obj.smartcasts {
|
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))
|
cast_sym := g.table.sym(g.unwrap_generic(typ))
|
||||||
if obj_sym.kind == .interface_ && cast_sym.kind == .interface_ {
|
if obj_sym.kind == .interface_ && cast_sym.kind == .interface_ {
|
||||||
ptr := '*'.repeat(node.obj.typ.nr_muls())
|
ptr := '*'.repeat(node.obj.typ.nr_muls())
|
||||||
@ -4529,9 +4537,14 @@ fn (mut g Gen) ident(node ast.Ident) {
|
|||||||
g.write('${dot}_${sym.cname}')
|
g.write('${dot}_${sym.cname}')
|
||||||
} else {
|
} else {
|
||||||
if is_option {
|
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(')')
|
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