v: unwrap an option value automatically, inside if o != none { (#20275)

This commit is contained in:
Felipe Pena 2023-12-27 16:22:44 -03:00 committed by GitHub
parent 34858c3265
commit b944927f09
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 90 additions and 5 deletions

View File

@ -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 {

View File

@ -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(')')

View 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
}
}