mirror of
https://github.com/vlang/v.git
synced 2023-08-10 21:13:21 +03:00
cgen: fix alias to option handling (#18490)
This commit is contained in:
parent
a7f00e7594
commit
c657384f72
@ -2861,6 +2861,12 @@ fn (mut c Checker) cast_expr(mut node ast.CastExpr) ast.Type {
|
||||
|
||||
if to_sym.language != .c {
|
||||
c.ensure_type_exists(to_type, node.pos) or {}
|
||||
|
||||
if to_sym.kind == .alias && (to_sym.info as ast.Alias).parent_type.has_flag(.option)
|
||||
&& !to_type.has_flag(.option) {
|
||||
c.error('alias to Option type requires to be used as Option type (?${to_sym.name}(...))',
|
||||
node.pos)
|
||||
}
|
||||
}
|
||||
if from_sym.kind == .u8 && from_type.is_ptr() && to_sym.kind == .string && !to_type.is_ptr() {
|
||||
c.error('to convert a C string buffer pointer to a V string, use x.vstring() instead of string(x)',
|
||||
|
42
vlib/v/checker/tests/alias_to_option_err.out
Normal file
42
vlib/v/checker/tests/alias_to_option_err.out
Normal file
@ -0,0 +1,42 @@
|
||||
vlib/v/checker/tests/alias_to_option_err.vv:11:7: error: alias to Option type requires to be used as Option type (?TestInt(...))
|
||||
9 |
|
||||
10 | fn main() {
|
||||
11 | f := TestInt(1)
|
||||
| ~~~~~~~~~~
|
||||
12 | dump(f)
|
||||
13 | println(f)
|
||||
vlib/v/checker/tests/alias_to_option_err.vv:15:7: error: alias to Option type requires to be used as Option type (?TestString(...))
|
||||
13 | println(f)
|
||||
14 |
|
||||
15 | g := TestString('foo')
|
||||
| ~~~~~~~~~~~~~~~~~
|
||||
16 | dump(g)
|
||||
17 | println(g)
|
||||
vlib/v/checker/tests/alias_to_option_err.vv:19:7: error: alias to Option type requires to be used as Option type (?TestString(...))
|
||||
17 | println(g)
|
||||
18 |
|
||||
19 | h := TestString(none)
|
||||
| ~~~~~~~~~~~~~~~~
|
||||
20 | dump(h)
|
||||
21 |
|
||||
vlib/v/checker/tests/alias_to_option_err.vv:22:7: error: alias to Option type requires to be used as Option type (?TestF64(...))
|
||||
20 | dump(h)
|
||||
21 |
|
||||
22 | i := TestF64(none)
|
||||
| ~~~~~~~~~~~~~
|
||||
23 | dump(i)
|
||||
24 |
|
||||
vlib/v/checker/tests/alias_to_option_err.vv:25:7: error: alias to Option type requires to be used as Option type (?TestStruct(...))
|
||||
23 | dump(i)
|
||||
24 |
|
||||
25 | l := TestStruct(none)
|
||||
| ~~~~~~~~~~~~~~~~
|
||||
26 | dump(l)
|
||||
27 |
|
||||
vlib/v/checker/tests/alias_to_option_err.vv:28:7: error: alias to Option type requires to be used as Option type (?TestStruct(...))
|
||||
26 | dump(l)
|
||||
27 |
|
||||
28 | k := TestStruct(Struct{})
|
||||
| ~~~~~~~~~~~~~~~~~~~~
|
||||
29 | dump(k)
|
||||
30 | }
|
30
vlib/v/checker/tests/alias_to_option_err.vv
Normal file
30
vlib/v/checker/tests/alias_to_option_err.vv
Normal file
@ -0,0 +1,30 @@
|
||||
type TestInt = ?int
|
||||
type TestString = ?string
|
||||
type TestF64 = ?f64
|
||||
|
||||
struct Struct {
|
||||
}
|
||||
|
||||
type TestStruct = ?Struct
|
||||
|
||||
fn main() {
|
||||
f := TestInt(1)
|
||||
dump(f)
|
||||
println(f)
|
||||
|
||||
g := TestString('foo')
|
||||
dump(g)
|
||||
println(g)
|
||||
|
||||
h := TestString(none)
|
||||
dump(h)
|
||||
|
||||
i := TestF64(none)
|
||||
dump(i)
|
||||
|
||||
l := TestStruct(none)
|
||||
dump(l)
|
||||
|
||||
k := TestStruct(Struct{})
|
||||
dump(k)
|
||||
}
|
@ -4245,7 +4245,20 @@ fn (mut g Gen) ident(node ast.Ident) {
|
||||
if is_auto_heap {
|
||||
g.write('(*(${styp}*)${name}->data)')
|
||||
} else {
|
||||
g.write('(*(${styp}*)${name}.data)')
|
||||
type_sym := g.table.sym(node.info.typ)
|
||||
if type_sym.kind == .alias {
|
||||
// Alias to Option type
|
||||
parent_typ := (type_sym.info as ast.Alias).parent_type
|
||||
if parent_typ.has_flag(.option) {
|
||||
g.write('*((${g.base_type(parent_typ)}*)')
|
||||
}
|
||||
g.write('(*(${styp}*)${name}.data)')
|
||||
if parent_typ.has_flag(.option) {
|
||||
g.write('.data)')
|
||||
}
|
||||
} else {
|
||||
g.write('(*(${styp}*)${name}.data)')
|
||||
}
|
||||
}
|
||||
}
|
||||
if node.or_expr.kind != .absent && !(g.inside_opt_or_res && g.inside_assign
|
||||
@ -4398,17 +4411,38 @@ fn (mut g Gen) cast_expr(node ast.CastExpr) {
|
||||
mut cast_label := ''
|
||||
// `ast.string_type` is done for MSVC's bug
|
||||
if sym.kind != .alias
|
||||
|| (sym.info as ast.Alias).parent_type !in [expr_type, ast.string_type] {
|
||||
|| (!(sym.info as ast.Alias).parent_type.has_flag(.option)
|
||||
&& (sym.info as ast.Alias).parent_type !in [expr_type, ast.string_type]) {
|
||||
cast_label = '(${styp})'
|
||||
}
|
||||
if node.typ.has_flag(.option) && node.expr is ast.None {
|
||||
g.gen_option_error(node.typ, node.expr)
|
||||
} else if node.typ.has_flag(.option) {
|
||||
if sym.kind == .alias && node.expr_type.has_flag(.option) {
|
||||
g.expr_opt_with_cast(node.expr, expr_type, node.typ)
|
||||
if sym.kind == .alias {
|
||||
if (sym.info as ast.Alias).parent_type.has_flag(.option) {
|
||||
cur_stmt := g.go_before_stmt(0)
|
||||
g.empty_line = true
|
||||
parent_type := (sym.info as ast.Alias).parent_type
|
||||
tmp_var := g.new_tmp_var()
|
||||
tmp_var2 := g.new_tmp_var()
|
||||
g.writeln('${styp} ${tmp_var};')
|
||||
g.writeln('${g.typ(parent_type)} ${tmp_var2};')
|
||||
g.write('_option_ok(&(${g.base_type(parent_type)}[]) { ')
|
||||
g.expr(node.expr)
|
||||
g.writeln(' }, (${c.option_name}*)(&${tmp_var2}), sizeof(${g.base_type(parent_type)}));')
|
||||
g.writeln('_option_ok(&(${g.typ(parent_type)}[]) { ${tmp_var2} }, (${c.option_name}*)&${tmp_var}, sizeof(${g.typ(parent_type)}));')
|
||||
g.write(cur_stmt)
|
||||
g.write(tmp_var)
|
||||
} else if node.expr_type.has_flag(.option) {
|
||||
g.expr_opt_with_cast(node.expr, expr_type, node.typ)
|
||||
} else {
|
||||
g.expr_with_opt(node.expr, expr_type, node.typ)
|
||||
}
|
||||
} else {
|
||||
g.expr_with_opt(node.expr, expr_type, node.typ)
|
||||
}
|
||||
} else if sym.kind == .alias && (sym.info as ast.Alias).parent_type.has_flag(.option) {
|
||||
g.expr_with_opt(node.expr, expr_type, (sym.info as ast.Alias).parent_type)
|
||||
} else {
|
||||
g.write('(${cast_label}(')
|
||||
if sym.kind == .alias && g.table.final_sym(node.typ).kind == .string {
|
||||
|
Loading…
Reference in New Issue
Block a user