Skip to content

Commit c657384

Browse files
authored
cgen: fix alias to option handling (#18490)
1 parent a7f00e7 commit c657384

File tree

4 files changed

+116
-4
lines changed

4 files changed

+116
-4
lines changed

vlib/v/checker/checker.v

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2861,6 +2861,12 @@ fn (mut c Checker) cast_expr(mut node ast.CastExpr) ast.Type {
28612861

28622862
if to_sym.language != .c {
28632863
c.ensure_type_exists(to_type, node.pos) or {}
2864+
2865+
if to_sym.kind == .alias && (to_sym.info as ast.Alias).parent_type.has_flag(.option)
2866+
&& !to_type.has_flag(.option) {
2867+
c.error('alias to Option type requires to be used as Option type (?${to_sym.name}(...))',
2868+
node.pos)
2869+
}
28642870
}
28652871
if from_sym.kind == .u8 && from_type.is_ptr() && to_sym.kind == .string && !to_type.is_ptr() {
28662872
c.error('to convert a C string buffer pointer to a V string, use x.vstring() instead of string(x)',
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
vlib/v/checker/tests/alias_to_option_err.vv:11:7: error: alias to Option type requires to be used as Option type (?TestInt(...))
2+
9 |
3+
10 | fn main() {
4+
11 | f := TestInt(1)
5+
| ~~~~~~~~~~
6+
12 | dump(f)
7+
13 | println(f)
8+
vlib/v/checker/tests/alias_to_option_err.vv:15:7: error: alias to Option type requires to be used as Option type (?TestString(...))
9+
13 | println(f)
10+
14 |
11+
15 | g := TestString('foo')
12+
| ~~~~~~~~~~~~~~~~~
13+
16 | dump(g)
14+
17 | println(g)
15+
vlib/v/checker/tests/alias_to_option_err.vv:19:7: error: alias to Option type requires to be used as Option type (?TestString(...))
16+
17 | println(g)
17+
18 |
18+
19 | h := TestString(none)
19+
| ~~~~~~~~~~~~~~~~
20+
20 | dump(h)
21+
21 |
22+
vlib/v/checker/tests/alias_to_option_err.vv:22:7: error: alias to Option type requires to be used as Option type (?TestF64(...))
23+
20 | dump(h)
24+
21 |
25+
22 | i := TestF64(none)
26+
| ~~~~~~~~~~~~~
27+
23 | dump(i)
28+
24 |
29+
vlib/v/checker/tests/alias_to_option_err.vv:25:7: error: alias to Option type requires to be used as Option type (?TestStruct(...))
30+
23 | dump(i)
31+
24 |
32+
25 | l := TestStruct(none)
33+
| ~~~~~~~~~~~~~~~~
34+
26 | dump(l)
35+
27 |
36+
vlib/v/checker/tests/alias_to_option_err.vv:28:7: error: alias to Option type requires to be used as Option type (?TestStruct(...))
37+
26 | dump(l)
38+
27 |
39+
28 | k := TestStruct(Struct{})
40+
| ~~~~~~~~~~~~~~~~~~~~
41+
29 | dump(k)
42+
30 | }
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
type TestInt = ?int
2+
type TestString = ?string
3+
type TestF64 = ?f64
4+
5+
struct Struct {
6+
}
7+
8+
type TestStruct = ?Struct
9+
10+
fn main() {
11+
f := TestInt(1)
12+
dump(f)
13+
println(f)
14+
15+
g := TestString('foo')
16+
dump(g)
17+
println(g)
18+
19+
h := TestString(none)
20+
dump(h)
21+
22+
i := TestF64(none)
23+
dump(i)
24+
25+
l := TestStruct(none)
26+
dump(l)
27+
28+
k := TestStruct(Struct{})
29+
dump(k)
30+
}

vlib/v/gen/c/cgen.v

Lines changed: 38 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4245,7 +4245,20 @@ fn (mut g Gen) ident(node ast.Ident) {
42454245
if is_auto_heap {
42464246
g.write('(*(${styp}*)${name}->data)')
42474247
} else {
4248-
g.write('(*(${styp}*)${name}.data)')
4248+
type_sym := g.table.sym(node.info.typ)
4249+
if type_sym.kind == .alias {
4250+
// Alias to Option type
4251+
parent_typ := (type_sym.info as ast.Alias).parent_type
4252+
if parent_typ.has_flag(.option) {
4253+
g.write('*((${g.base_type(parent_typ)}*)')
4254+
}
4255+
g.write('(*(${styp}*)${name}.data)')
4256+
if parent_typ.has_flag(.option) {
4257+
g.write('.data)')
4258+
}
4259+
} else {
4260+
g.write('(*(${styp}*)${name}.data)')
4261+
}
42494262
}
42504263
}
42514264
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) {
43984411
mut cast_label := ''
43994412
// `ast.string_type` is done for MSVC's bug
44004413
if sym.kind != .alias
4401-
|| (sym.info as ast.Alias).parent_type !in [expr_type, ast.string_type] {
4414+
|| (!(sym.info as ast.Alias).parent_type.has_flag(.option)
4415+
&& (sym.info as ast.Alias).parent_type !in [expr_type, ast.string_type]) {
44024416
cast_label = '(${styp})'
44034417
}
44044418
if node.typ.has_flag(.option) && node.expr is ast.None {
44054419
g.gen_option_error(node.typ, node.expr)
44064420
} else if node.typ.has_flag(.option) {
4407-
if sym.kind == .alias && node.expr_type.has_flag(.option) {
4408-
g.expr_opt_with_cast(node.expr, expr_type, node.typ)
4421+
if sym.kind == .alias {
4422+
if (sym.info as ast.Alias).parent_type.has_flag(.option) {
4423+
cur_stmt := g.go_before_stmt(0)
4424+
g.empty_line = true
4425+
parent_type := (sym.info as ast.Alias).parent_type
4426+
tmp_var := g.new_tmp_var()
4427+
tmp_var2 := g.new_tmp_var()
4428+
g.writeln('${styp} ${tmp_var};')
4429+
g.writeln('${g.typ(parent_type)} ${tmp_var2};')
4430+
g.write('_option_ok(&(${g.base_type(parent_type)}[]) { ')
4431+
g.expr(node.expr)
4432+
g.writeln(' }, (${c.option_name}*)(&${tmp_var2}), sizeof(${g.base_type(parent_type)}));')
4433+
g.writeln('_option_ok(&(${g.typ(parent_type)}[]) { ${tmp_var2} }, (${c.option_name}*)&${tmp_var}, sizeof(${g.typ(parent_type)}));')
4434+
g.write(cur_stmt)
4435+
g.write(tmp_var)
4436+
} else if node.expr_type.has_flag(.option) {
4437+
g.expr_opt_with_cast(node.expr, expr_type, node.typ)
4438+
} else {
4439+
g.expr_with_opt(node.expr, expr_type, node.typ)
4440+
}
44094441
} else {
44104442
g.expr_with_opt(node.expr, expr_type, node.typ)
44114443
}
4444+
} else if sym.kind == .alias && (sym.info as ast.Alias).parent_type.has_flag(.option) {
4445+
g.expr_with_opt(node.expr, expr_type, (sym.info as ast.Alias).parent_type)
44124446
} else {
44134447
g.write('(${cast_label}(')
44144448
if sym.kind == .alias && g.table.final_sym(node.typ).kind == .string {

0 commit comments

Comments
 (0)