mirror of
https://github.com/vlang/v.git
synced 2023-08-10 21:13:21 +03:00
ast, cgen: fix wrong name and cname, when array and fixed array elements have optional (fix #16099) (#16122)
This commit is contained in:
parent
2083e6b04c
commit
07310d850d
@ -884,21 +884,22 @@ pub fn (t &Table) known_type_idx(typ Type) bool {
|
|||||||
pub fn (t &Table) array_name(elem_type Type) string {
|
pub fn (t &Table) array_name(elem_type Type) string {
|
||||||
elem_type_sym := t.sym(elem_type)
|
elem_type_sym := t.sym(elem_type)
|
||||||
ptr := if elem_type.is_ptr() { '&'.repeat(elem_type.nr_muls()) } else { '' }
|
ptr := if elem_type.is_ptr() { '&'.repeat(elem_type.nr_muls()) } else { '' }
|
||||||
return '[]$ptr$elem_type_sym.name'
|
opt := if elem_type.has_flag(.optional) { '?' } else { '' }
|
||||||
|
res := if elem_type.has_flag(.result) { '!' } else { '' }
|
||||||
|
return '[]$opt$res$ptr$elem_type_sym.name'
|
||||||
}
|
}
|
||||||
|
|
||||||
[inline]
|
[inline]
|
||||||
pub fn (t &Table) array_cname(elem_type Type) string {
|
pub fn (t &Table) array_cname(elem_type Type) string {
|
||||||
elem_type_sym := t.sym(elem_type)
|
elem_type_sym := t.sym(elem_type)
|
||||||
mut res := ''
|
suffix := if elem_type.is_ptr() { '_ptr'.repeat(elem_type.nr_muls()) } else { '' }
|
||||||
if elem_type.is_ptr() {
|
opt := if elem_type.has_flag(.optional) { '_option_' } else { '' }
|
||||||
res = '_ptr'.repeat(elem_type.nr_muls())
|
res := if elem_type.has_flag(.result) { '_result_' } else { '' }
|
||||||
}
|
|
||||||
if elem_type_sym.cname.contains('<') {
|
if elem_type_sym.cname.contains('<') {
|
||||||
type_name := elem_type_sym.cname.replace_each(['<', '_T_', ', ', '_', '>', ''])
|
type_name := elem_type_sym.cname.replace_each(['<', '_T_', ', ', '_', '>', ''])
|
||||||
return 'Array_$type_name' + res
|
return 'Array_$opt$res$type_name$suffix'
|
||||||
} else {
|
} else {
|
||||||
return 'Array_$elem_type_sym.cname' + res
|
return 'Array_$opt$res$elem_type_sym.cname$suffix'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -908,22 +909,28 @@ pub fn (t &Table) array_cname(elem_type Type) string {
|
|||||||
pub fn (t &Table) array_fixed_name(elem_type Type, size int, size_expr Expr) string {
|
pub fn (t &Table) array_fixed_name(elem_type Type, size int, size_expr Expr) string {
|
||||||
elem_type_sym := t.sym(elem_type)
|
elem_type_sym := t.sym(elem_type)
|
||||||
ptr := if elem_type.is_ptr() { '&'.repeat(elem_type.nr_muls()) } else { '' }
|
ptr := if elem_type.is_ptr() { '&'.repeat(elem_type.nr_muls()) } else { '' }
|
||||||
|
opt := if elem_type.has_flag(.optional) { '?' } else { '' }
|
||||||
|
res := if elem_type.has_flag(.result) { '!' } else { '' }
|
||||||
size_str := if size_expr is EmptyExpr || size != 987654321 {
|
size_str := if size_expr is EmptyExpr || size != 987654321 {
|
||||||
size.str()
|
size.str()
|
||||||
} else {
|
} else {
|
||||||
size_expr.str()
|
size_expr.str()
|
||||||
}
|
}
|
||||||
return '[$size_str]$ptr$elem_type_sym.name'
|
return '[$size_str]$opt$res$ptr$elem_type_sym.name'
|
||||||
}
|
}
|
||||||
|
|
||||||
[inline]
|
[inline]
|
||||||
pub fn (t &Table) array_fixed_cname(elem_type Type, size int) string {
|
pub fn (t &Table) array_fixed_cname(elem_type Type, size int) string {
|
||||||
elem_type_sym := t.sym(elem_type)
|
elem_type_sym := t.sym(elem_type)
|
||||||
mut res := ''
|
suffix := if elem_type.is_ptr() { '_ptr$elem_type.nr_muls()' } else { '' }
|
||||||
if elem_type.is_ptr() {
|
opt := if elem_type.has_flag(.optional) { '_option_' } else { '' }
|
||||||
res = '_ptr$elem_type.nr_muls()'
|
res := if elem_type.has_flag(.result) { '_result_' } else { '' }
|
||||||
|
if elem_type_sym.cname.contains('<') {
|
||||||
|
type_name := elem_type_sym.cname.replace_each(['<', '_T_', ', ', '_', '>', ''])
|
||||||
|
return 'Array_fixed_$opt$res$type_name${suffix}_$size'
|
||||||
|
} else {
|
||||||
|
return 'Array_fixed_$opt$res$elem_type_sym.cname${suffix}_$size'
|
||||||
}
|
}
|
||||||
return 'Array_fixed_$elem_type_sym.cname${res}_$size'
|
|
||||||
}
|
}
|
||||||
|
|
||||||
[inline]
|
[inline]
|
||||||
@ -1012,7 +1019,7 @@ pub fn (t &Table) thread_cname(return_type Type) string {
|
|||||||
pub fn (t &Table) map_name(key_type Type, value_type Type) string {
|
pub fn (t &Table) map_name(key_type Type, value_type Type) string {
|
||||||
key_type_sym := t.sym(key_type)
|
key_type_sym := t.sym(key_type)
|
||||||
value_type_sym := t.sym(value_type)
|
value_type_sym := t.sym(value_type)
|
||||||
ptr := if value_type.is_ptr() { '&' } else { '' }
|
ptr := if value_type.is_ptr() { '&'.repeat(value_type.nr_muls()) } else { '' }
|
||||||
opt := if value_type.has_flag(.optional) { '?' } else { '' }
|
opt := if value_type.has_flag(.optional) { '?' } else { '' }
|
||||||
res := if value_type.has_flag(.result) { '!' } else { '' }
|
res := if value_type.has_flag(.result) { '!' } else { '' }
|
||||||
return 'map[$key_type_sym.name]$opt$res$ptr$value_type_sym.name'
|
return 'map[$key_type_sym.name]$opt$res$ptr$value_type_sym.name'
|
||||||
@ -1022,10 +1029,15 @@ pub fn (t &Table) map_name(key_type Type, value_type Type) string {
|
|||||||
pub fn (t &Table) map_cname(key_type Type, value_type Type) string {
|
pub fn (t &Table) map_cname(key_type Type, value_type Type) string {
|
||||||
key_type_sym := t.sym(key_type)
|
key_type_sym := t.sym(key_type)
|
||||||
value_type_sym := t.sym(value_type)
|
value_type_sym := t.sym(value_type)
|
||||||
suffix := if value_type.is_ptr() { '_ptr' } else { '' }
|
suffix := if value_type.is_ptr() { '_ptr'.repeat(value_type.nr_muls()) } else { '' }
|
||||||
opt := if value_type.has_flag(.optional) { '_option_' } else { '' }
|
opt := if value_type.has_flag(.optional) { '_option_' } else { '' }
|
||||||
res := if value_type.has_flag(.result) { '_result_' } else { '' }
|
res := if value_type.has_flag(.result) { '_result_' } else { '' }
|
||||||
return 'Map_${key_type_sym.cname}_$opt$res$value_type_sym.cname$suffix'
|
if value_type_sym.cname.contains('<') {
|
||||||
|
type_name := value_type_sym.cname.replace_each(['<', '_T_', ', ', '_', '>', ''])
|
||||||
|
return 'Map_${key_type_sym.cname}_$opt$res$type_name$suffix'
|
||||||
|
} else {
|
||||||
|
return 'Map_${key_type_sym.cname}_$opt$res$value_type_sym.cname$suffix'
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn (mut t Table) find_or_register_chan(elem_type Type, is_mut bool) int {
|
pub fn (mut t Table) find_or_register_chan(elem_type Type, is_mut bool) int {
|
||||||
|
@ -72,7 +72,9 @@ mut:
|
|||||||
embedded_data strings.Builder // data to embed in the executable/binary
|
embedded_data strings.Builder // data to embed in the executable/binary
|
||||||
shared_types strings.Builder // shared/lock types
|
shared_types strings.Builder // shared/lock types
|
||||||
shared_functions strings.Builder // shared constructors
|
shared_functions strings.Builder // shared constructors
|
||||||
options strings.Builder // `option_xxxx` types
|
out_options_forward strings.Builder // forward `option_xxxx` types
|
||||||
|
out_options strings.Builder // `option_xxxx` types
|
||||||
|
out_results_forward strings.Builder // forward`result_xxxx` types
|
||||||
out_results strings.Builder // `result_xxxx` types
|
out_results strings.Builder // `result_xxxx` types
|
||||||
json_forward_decls strings.Builder // json type forward decls
|
json_forward_decls strings.Builder // json type forward decls
|
||||||
sql_buf strings.Builder // for writing exprs to args via `sqlite3_bind_int()` etc
|
sql_buf strings.Builder // for writing exprs to args via `sqlite3_bind_int()` etc
|
||||||
@ -99,9 +101,12 @@ mut:
|
|||||||
is_json_fn bool // inside json.encode()
|
is_json_fn bool // inside json.encode()
|
||||||
is_js_call bool // for handling a special type arg #1 `json.decode(User, ...)`
|
is_js_call bool // for handling a special type arg #1 `json.decode(User, ...)`
|
||||||
is_fn_index_call bool
|
is_fn_index_call bool
|
||||||
is_cc_msvc bool // g.pref.ccompiler == 'msvc'
|
is_cc_msvc bool // g.pref.ccompiler == 'msvc'
|
||||||
vlines_path string // set to the proper path for generating #line directives
|
vlines_path string // set to the proper path for generating #line directives
|
||||||
|
optionals_pos_forward int // insertion point to forward
|
||||||
|
options_forward []string // to forward
|
||||||
optionals map[string]string // to avoid duplicates
|
optionals map[string]string // to avoid duplicates
|
||||||
|
results_forward []string // to forward
|
||||||
results map[string]string // to avoid duplicates
|
results map[string]string // to avoid duplicates
|
||||||
done_optionals shared []string // to avoid duplicates
|
done_optionals shared []string // to avoid duplicates
|
||||||
chan_pop_optionals map[string]string // types for `x := <-ch or {...}`
|
chan_pop_optionals map[string]string // types for `x := <-ch or {...}`
|
||||||
@ -270,7 +275,9 @@ pub fn gen(files []&ast.File, table &ast.Table, pref &pref.Preferences) (string,
|
|||||||
dump_funcs: strings.new_builder(100)
|
dump_funcs: strings.new_builder(100)
|
||||||
pcs_declarations: strings.new_builder(100)
|
pcs_declarations: strings.new_builder(100)
|
||||||
embedded_data: strings.new_builder(1000)
|
embedded_data: strings.new_builder(1000)
|
||||||
options: strings.new_builder(100)
|
out_options_forward: strings.new_builder(100)
|
||||||
|
out_options: strings.new_builder(100)
|
||||||
|
out_results_forward: strings.new_builder(100)
|
||||||
out_results: strings.new_builder(100)
|
out_results: strings.new_builder(100)
|
||||||
shared_types: strings.new_builder(100)
|
shared_types: strings.new_builder(100)
|
||||||
shared_functions: strings.new_builder(100)
|
shared_functions: strings.new_builder(100)
|
||||||
@ -456,6 +463,22 @@ pub fn gen(files []&ast.File, table &ast.Table, pref &pref.Preferences) (string,
|
|||||||
g.write_init_function()
|
g.write_init_function()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// insert for optionals forward
|
||||||
|
if g.out_options_forward.len > 0 || g.out_results_forward.len > 0 {
|
||||||
|
tail := g.type_definitions.cut_to(g.optionals_pos_forward)
|
||||||
|
if g.out_options_forward.len > 0 {
|
||||||
|
g.type_definitions.writeln('// #start V forward option_xxx definitions:')
|
||||||
|
g.type_definitions.writeln(g.out_options_forward.str())
|
||||||
|
g.type_definitions.writeln('// #end V forward option_xxx definitions\n')
|
||||||
|
}
|
||||||
|
if g.out_results_forward.len > 0 {
|
||||||
|
g.type_definitions.writeln('// #start V forward result_xxx definitions:')
|
||||||
|
g.type_definitions.writeln(g.out_results_forward.str())
|
||||||
|
g.type_definitions.writeln('// #end V forward result_xxx definitions\n')
|
||||||
|
}
|
||||||
|
g.type_definitions.writeln(tail)
|
||||||
|
}
|
||||||
|
|
||||||
g.finish()
|
g.finish()
|
||||||
|
|
||||||
mut b := strings.new_builder(640000)
|
mut b := strings.new_builder(640000)
|
||||||
@ -488,7 +511,7 @@ pub fn gen(files []&ast.File, table &ast.Table, pref &pref.Preferences) (string,
|
|||||||
b.writeln('\n// V shared types:')
|
b.writeln('\n// V shared types:')
|
||||||
b.write_string(g.shared_types.str())
|
b.write_string(g.shared_types.str())
|
||||||
b.writeln('\n// V Option_xxx definitions:')
|
b.writeln('\n// V Option_xxx definitions:')
|
||||||
b.write_string(g.options.str())
|
b.write_string(g.out_options.str())
|
||||||
b.writeln('\n// V result_xxx definitions:')
|
b.writeln('\n// V result_xxx definitions:')
|
||||||
b.write_string(g.out_results.str())
|
b.write_string(g.out_results.str())
|
||||||
b.writeln('\n// V json forward decls:')
|
b.writeln('\n// V json forward decls:')
|
||||||
@ -591,7 +614,9 @@ fn cgen_process_one_file_cb(p &pool.PoolProcessor, idx int, wid int) &Gen {
|
|||||||
pcs_declarations: strings.new_builder(100)
|
pcs_declarations: strings.new_builder(100)
|
||||||
hotcode_definitions: strings.new_builder(100)
|
hotcode_definitions: strings.new_builder(100)
|
||||||
embedded_data: strings.new_builder(1000)
|
embedded_data: strings.new_builder(1000)
|
||||||
options: strings.new_builder(100)
|
out_options_forward: strings.new_builder(100)
|
||||||
|
out_options: strings.new_builder(100)
|
||||||
|
out_results_forward: strings.new_builder(100)
|
||||||
out_results: strings.new_builder(100)
|
out_results: strings.new_builder(100)
|
||||||
shared_types: strings.new_builder(100)
|
shared_types: strings.new_builder(100)
|
||||||
shared_functions: strings.new_builder(100)
|
shared_functions: strings.new_builder(100)
|
||||||
@ -615,6 +640,8 @@ fn cgen_process_one_file_cb(p &pool.PoolProcessor, idx int, wid int) &Gen {
|
|||||||
array_sort_fn: global_g.array_sort_fn
|
array_sort_fn: global_g.array_sort_fn
|
||||||
waiter_fns: global_g.waiter_fns
|
waiter_fns: global_g.waiter_fns
|
||||||
threaded_fns: global_g.threaded_fns
|
threaded_fns: global_g.threaded_fns
|
||||||
|
options_forward: global_g.options_forward
|
||||||
|
results_forward: global_g.results_forward
|
||||||
done_optionals: global_g.done_optionals
|
done_optionals: global_g.done_optionals
|
||||||
is_autofree: global_g.pref.autofree
|
is_autofree: global_g.pref.autofree
|
||||||
referenced_fns: global_g.referenced_fns
|
referenced_fns: global_g.referenced_fns
|
||||||
@ -650,7 +677,9 @@ pub fn (mut g Gen) free_builders() {
|
|||||||
g.shared_functions.free()
|
g.shared_functions.free()
|
||||||
g.channel_definitions.free()
|
g.channel_definitions.free()
|
||||||
g.thread_definitions.free()
|
g.thread_definitions.free()
|
||||||
g.options.free()
|
g.out_options_forward.free()
|
||||||
|
g.out_options.free()
|
||||||
|
g.out_results_forward.free()
|
||||||
g.out_results.free()
|
g.out_results.free()
|
||||||
g.json_forward_decls.free()
|
g.json_forward_decls.free()
|
||||||
g.enum_typedefs.free()
|
g.enum_typedefs.free()
|
||||||
@ -734,6 +763,7 @@ pub fn (mut g Gen) init() {
|
|||||||
g.cheaders.writeln('#include <spawn.h>')
|
g.cheaders.writeln('#include <spawn.h>')
|
||||||
}
|
}
|
||||||
g.write_builtin_types()
|
g.write_builtin_types()
|
||||||
|
g.optionals_pos_forward = g.type_definitions.len
|
||||||
g.write_typedef_types()
|
g.write_typedef_types()
|
||||||
g.write_typeof_functions()
|
g.write_typeof_functions()
|
||||||
g.write_sorted_types()
|
g.write_sorted_types()
|
||||||
@ -1086,7 +1116,11 @@ fn (mut g Gen) write_optionals() {
|
|||||||
}
|
}
|
||||||
done << base
|
done << base
|
||||||
g.typedefs.writeln('typedef struct $styp $styp;')
|
g.typedefs.writeln('typedef struct $styp $styp;')
|
||||||
g.options.write_string(g.optional_type_text(styp, base) + ';\n\n')
|
if base in g.options_forward {
|
||||||
|
g.out_options_forward.write_string(g.optional_type_text(styp, base) + ';\n\n')
|
||||||
|
} else {
|
||||||
|
g.out_options.write_string(g.optional_type_text(styp, base) + ';\n\n')
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1098,7 +1132,11 @@ fn (mut g Gen) write_results() {
|
|||||||
}
|
}
|
||||||
done << base
|
done << base
|
||||||
g.typedefs.writeln('typedef struct $styp $styp;')
|
g.typedefs.writeln('typedef struct $styp $styp;')
|
||||||
g.out_results.write_string(g.result_type_text(styp, base) + ';\n\n')
|
if base in g.results_forward {
|
||||||
|
g.out_results_forward.write_string(g.result_type_text(styp, base) + ';\n\n')
|
||||||
|
} else {
|
||||||
|
g.out_results.write_string(g.result_type_text(styp, base) + ';\n\n')
|
||||||
|
}
|
||||||
}
|
}
|
||||||
for k, _ in g.table.anon_struct_names {
|
for k, _ in g.table.anon_struct_names {
|
||||||
ck := c_name(k)
|
ck := c_name(k)
|
||||||
@ -1314,6 +1352,12 @@ pub fn (mut g Gen) write_typedef_types() {
|
|||||||
g.type_definitions.writeln(def_str)
|
g.type_definitions.writeln(def_str)
|
||||||
} else {
|
} else {
|
||||||
g.type_definitions.writeln('typedef $fixed $styp [$len];')
|
g.type_definitions.writeln('typedef $fixed $styp [$len];')
|
||||||
|
base := g.typ(info.elem_type.clear_flag(.optional).clear_flag(.result))
|
||||||
|
if info.elem_type.has_flag(.optional) && base !in g.options_forward {
|
||||||
|
g.options_forward << base
|
||||||
|
} else if info.elem_type.has_flag(.result) && base !in g.results_forward {
|
||||||
|
g.results_forward << base
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -2272,7 +2316,8 @@ fn (mut g Gen) expr_with_cast(expr ast.Expr, got_type_raw ast.Type, expected_typ
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
if got_sym.info !is ast.Interface && exp_sym.info is ast.Interface
|
if got_sym.info !is ast.Interface && exp_sym.info is ast.Interface
|
||||||
&& got_type.idx() != expected_type.idx() && !expected_type.has_flag(.optional) {
|
&& got_type.idx() != expected_type.idx() && !expected_type.has_flag(.optional)
|
||||||
|
&& !expected_type.has_flag(.result) {
|
||||||
if expr is ast.StructInit && !got_type.is_ptr() {
|
if expr is ast.StructInit && !got_type.is_ptr() {
|
||||||
g.inside_cast_in_heap++
|
g.inside_cast_in_heap++
|
||||||
got_styp := g.cc_type(got_type.ref(), true)
|
got_styp := g.cc_type(got_type.ref(), true)
|
||||||
@ -2362,7 +2407,7 @@ fn (mut g Gen) expr_with_cast(expr ast.Expr, got_type_raw ast.Type, expected_typ
|
|||||||
// Generic dereferencing logic
|
// Generic dereferencing logic
|
||||||
neither_void := ast.voidptr_type !in [got_type, expected_type]
|
neither_void := ast.voidptr_type !in [got_type, expected_type]
|
||||||
if expected_type.has_flag(.shared_f) && !got_type_raw.has_flag(.shared_f)
|
if expected_type.has_flag(.shared_f) && !got_type_raw.has_flag(.shared_f)
|
||||||
&& !expected_type.has_flag(.optional) {
|
&& !expected_type.has_flag(.optional) && !expected_type.has_flag(.result) {
|
||||||
shared_styp := exp_styp[0..exp_styp.len - 1] // `shared` implies ptr, so eat one `*`
|
shared_styp := exp_styp[0..exp_styp.len - 1] // `shared` implies ptr, so eat one `*`
|
||||||
if got_type_raw.is_ptr() {
|
if got_type_raw.is_ptr() {
|
||||||
g.error('cannot convert reference to `shared`', expr.pos())
|
g.error('cannot convert reference to `shared`', expr.pos())
|
||||||
@ -2393,8 +2438,8 @@ fn (mut g Gen) expr_with_cast(expr ast.Expr, got_type_raw ast.Type, expected_typ
|
|||||||
got_deref_type := got_type.deref()
|
got_deref_type := got_type.deref()
|
||||||
deref_sym := g.table.sym(got_deref_type)
|
deref_sym := g.table.sym(got_deref_type)
|
||||||
deref_will_match := expected_type in [got_type, got_deref_type, deref_sym.parent_idx]
|
deref_will_match := expected_type in [got_type, got_deref_type, deref_sym.parent_idx]
|
||||||
got_is_opt := got_type.has_flag(.optional)
|
got_is_opt_or_res := got_type.has_flag(.optional) || got_type.has_flag(.result)
|
||||||
if deref_will_match || got_is_opt || expr.is_auto_deref_var() {
|
if deref_will_match || got_is_opt_or_res || expr.is_auto_deref_var() {
|
||||||
g.write('*')
|
g.write('*')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -3452,8 +3497,9 @@ fn (mut g Gen) selector_expr(node ast.SelectorExpr) {
|
|||||||
}
|
}
|
||||||
sym := g.table.sym(g.unwrap_generic(node.expr_type))
|
sym := g.table.sym(g.unwrap_generic(node.expr_type))
|
||||||
// if node expr is a root ident and an optional
|
// if node expr is a root ident and an optional
|
||||||
mut is_optional := node.expr is ast.Ident && node.expr_type.has_flag(.optional)
|
mut is_opt_or_res := node.expr is ast.Ident
|
||||||
if is_optional {
|
&& (node.expr_type.has_flag(.optional) || node.expr_type.has_flag(.result))
|
||||||
|
if is_opt_or_res {
|
||||||
opt_base_typ := g.base_type(node.expr_type)
|
opt_base_typ := g.base_type(node.expr_type)
|
||||||
g.writeln('(*($opt_base_typ*)')
|
g.writeln('(*($opt_base_typ*)')
|
||||||
}
|
}
|
||||||
@ -3584,7 +3630,7 @@ fn (mut g Gen) selector_expr(node ast.SelectorExpr) {
|
|||||||
} else {
|
} else {
|
||||||
g.expr(node.expr)
|
g.expr(node.expr)
|
||||||
}
|
}
|
||||||
if is_optional {
|
if is_opt_or_res {
|
||||||
g.write('.data)')
|
g.write('.data)')
|
||||||
}
|
}
|
||||||
// struct embedding
|
// struct embedding
|
||||||
|
44
vlib/v/tests/array_elements_with_optional_test.v
Normal file
44
vlib/v/tests/array_elements_with_optional_test.v
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
struct Foo1 {
|
||||||
|
arr1 [5]?int
|
||||||
|
arr2 [5]int
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_has_optional_fixed() ?int {
|
||||||
|
foo := Foo1{}
|
||||||
|
return foo.arr1[0]
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_no_optional_fixed() int {
|
||||||
|
foo := Foo1{}
|
||||||
|
return foo.arr2[0]
|
||||||
|
}
|
||||||
|
|
||||||
|
fn test_optional_fixed() ? {
|
||||||
|
x := get_has_optional_fixed()?
|
||||||
|
assert x == 0
|
||||||
|
assert get_no_optional_fixed() == 0
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Foo2 {
|
||||||
|
mut:
|
||||||
|
arr1 []?int
|
||||||
|
arr2 []int
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_has_optional() ?int {
|
||||||
|
mut foo := Foo2{}
|
||||||
|
foo.arr1 << 0
|
||||||
|
return foo.arr1[0]
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_no_optional() int {
|
||||||
|
mut foo := Foo2{}
|
||||||
|
foo.arr2 << 0
|
||||||
|
return foo.arr2[0]
|
||||||
|
}
|
||||||
|
|
||||||
|
fn test_optional_non_fixed() ? {
|
||||||
|
x := get_has_optional()?
|
||||||
|
assert x == 0
|
||||||
|
assert get_no_optional() == 0
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user