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 {
|
if to_sym.language != .c {
|
||||||
c.ensure_type_exists(to_type, node.pos) or {}
|
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() {
|
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)',
|
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 {
|
if is_auto_heap {
|
||||||
g.write('(*(${styp}*)${name}->data)')
|
g.write('(*(${styp}*)${name}->data)')
|
||||||
} else {
|
} 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
|
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 := ''
|
mut cast_label := ''
|
||||||
// `ast.string_type` is done for MSVC's bug
|
// `ast.string_type` is done for MSVC's bug
|
||||||
if sym.kind != .alias
|
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})'
|
cast_label = '(${styp})'
|
||||||
}
|
}
|
||||||
if node.typ.has_flag(.option) && node.expr is ast.None {
|
if node.typ.has_flag(.option) && node.expr is ast.None {
|
||||||
g.gen_option_error(node.typ, node.expr)
|
g.gen_option_error(node.typ, node.expr)
|
||||||
} else if node.typ.has_flag(.option) {
|
} else if node.typ.has_flag(.option) {
|
||||||
if sym.kind == .alias && node.expr_type.has_flag(.option) {
|
if sym.kind == .alias {
|
||||||
g.expr_opt_with_cast(node.expr, expr_type, node.typ)
|
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 {
|
} else {
|
||||||
g.expr_with_opt(node.expr, expr_type, node.typ)
|
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 {
|
} else {
|
||||||
g.write('(${cast_label}(')
|
g.write('(${cast_label}(')
|
||||||
if sym.kind == .alias && g.table.final_sym(node.typ).kind == .string {
|
if sym.kind == .alias && g.table.final_sym(node.typ).kind == .string {
|
||||||
|
|
Loading…
Reference in New Issue
Block a user