diff --git a/vlib/v/gen/c/auto_str_methods.v b/vlib/v/gen/c/auto_str_methods.v index 080796f674..3dfd83ceda 100644 --- a/vlib/v/gen/c/auto_str_methods.v +++ b/vlib/v/gen/c/auto_str_methods.v @@ -627,7 +627,7 @@ fn (mut g Gen) gen_str_for_array(info ast.Array, styp string, str_fn_name string if sym.kind == .function { g.auto_str_funcs.writeln('\t\tstring x = ${elem_str_fn_name}();') } else { - if sym.kind == .array_fixed { + if !typ.has_flag(.option) && sym.kind == .array_fixed { g.auto_str_funcs.writeln('\t\t${field_styp} it;') g.auto_str_funcs.writeln('\t\tmemcpy(*(${field_styp}*)it, (byte*)array_get(a, i), sizeof(${field_styp}));') } else { diff --git a/vlib/v/gen/c/for.v b/vlib/v/gen/c/for.v index b0a18f981f..bb40caa591 100644 --- a/vlib/v/gen/c/for.v +++ b/vlib/v/gen/c/for.v @@ -253,12 +253,13 @@ fn (mut g Gen) for_in_stmt(node_ ast.ForInStmt) { tcc_bug := c_name(node.val_var) g.write_fn_ptr_decl(&val_sym.info, tcc_bug) g.writeln(' = ((voidptr*)${cond_var}${op_field}data)[${i}];') - } else if val_sym.kind == .array_fixed && !node.val_is_mut { + } else if !node.val_type.has_flag(.option) && val_sym.kind == .array_fixed + && !node.val_is_mut { right := '((${styp}*)${cond_var}${op_field}data)[${i}]' g.writeln('\t${styp} ${c_name(node.val_var)};') g.writeln('\tmemcpy(*(${styp}*)${c_name(node.val_var)}, (byte*)${right}, sizeof(${styp}));') } else { - needs_memcpy := !node.val_type.is_ptr() + needs_memcpy := !node.val_type.is_ptr() && !node.val_type.has_flag(.option) && g.table.final_sym(node.val_type).kind == .array_fixed // If val is mutable (pointer behind the scenes), we need to generate // `int* val = ((int*)arr.data) + i;` @@ -311,6 +312,7 @@ fn (mut g Gen) for_in_stmt(node_ ast.ForInStmt) { if node.val_var != '_' { val_sym := g.table.sym(node.val_type) is_fixed_array := val_sym.kind == .array_fixed && !node.val_is_mut + && !node.val_type.has_flag(.option) if val_sym.info is ast.FnType { g.write('\t') tcc_bug := c_name(node.val_var) diff --git a/vlib/v/gen/c/if.v b/vlib/v/gen/c/if.v index 706037ab15..b2463b8212 100644 --- a/vlib/v/gen/c/if.v +++ b/vlib/v/gen/c/if.v @@ -371,6 +371,9 @@ fn (mut g Gen) if_expr(node ast.IfExpr) { left_var_name := c_name(branch.cond.vars[0].name) if is_auto_heap { g.writeln('\t${base_type}* ${left_var_name} = HEAP(${base_type}, *(${base_type}*)${var_name}.data);') + } else if base_type.starts_with('Array_fixed') { + g.writeln('\t${base_type} ${left_var_name} = {0};') + g.writeln('memcpy(${left_var_name}, (${base_type}*)${var_name}.data, sizeof(${base_type}));') } else { dot_or_ptr := if !branch.cond.expr_type.has_flag(.option_mut_param_t) { '.' diff --git a/vlib/v/gen/c/infix.v b/vlib/v/gen/c/infix.v index 2605c6cf28..c28e711576 100644 --- a/vlib/v/gen/c/infix.v +++ b/vlib/v/gen/c/infix.v @@ -991,10 +991,11 @@ fn (mut g Gen) infix_expr_left_shift_op(node ast.InfixExpr) { tmp_var := g.new_tmp_var() array_info := left.unaliased_sym.info as ast.Array noscan := g.check_noscan(array_info.elem_type) + elem_is_option := array_info.elem_type.has_flag(.option) if (right.unaliased_sym.kind == .array || (right.unaliased_sym.kind == .struct && right.unaliased_sym.name == 'array')) && left.sym.nr_dims() == right.sym.nr_dims() && array_info.elem_type != right.typ - && !(right.sym.kind == .alias + && !elem_is_option && !(right.sym.kind == .alias && g.table.sumtype_has_variant(array_info.elem_type, node.right_type, false)) { // push an array => PUSH_MANY, but not if pushing an array to 2d array (`[][]int << []int`) g.write('_PUSH_MANY${noscan}(') @@ -1028,7 +1029,8 @@ fn (mut g Gen) infix_expr_left_shift_op(node ast.InfixExpr) { // push a single element elem_type_str := g.styp(array_info.elem_type) elem_sym := g.table.final_sym(array_info.elem_type) - elem_is_array_var := elem_sym.kind in [.array, .array_fixed] && node.right is ast.Ident + elem_is_array_var := !elem_is_option && elem_sym.kind in [.array, .array_fixed] + && node.right is ast.Ident g.write('array_push${noscan}((array*)') mut needs_addr := false if !left.typ.is_ptr() diff --git a/vlib/v/tests/builtin_arrays/array_of_option_array_test.v b/vlib/v/tests/builtin_arrays/array_of_option_array_test.v new file mode 100644 index 0000000000..d569eadf99 --- /dev/null +++ b/vlib/v/tests/builtin_arrays/array_of_option_array_test.v @@ -0,0 +1,30 @@ +fn test_array_of_option_array() { + mut arr := []?[]int{} + + arr1 := []int{} + arr << arr1 + + arr2 := [1, 2, 3] + arr << arr2 + + arr << none + + println(arr) + + for i, item in arr { + if arr_item := item { + if i == 0 { + assert arr_item == [] + } else if i == 1 { + assert arr_item == [1, 2, 3] + } + } else { + assert item == none + } + } + + assert arr.len == 3 + assert '${arr[0]}' == 'Option([])' + assert '${arr[1]}' == 'Option([1, 2, 3])' + assert '${arr[2]}' == 'Option(none)' +} diff --git a/vlib/v/tests/builtin_arrays/array_of_option_fixed_array_test.v b/vlib/v/tests/builtin_arrays/array_of_option_fixed_array_test.v new file mode 100644 index 0000000000..37daf8e59f --- /dev/null +++ b/vlib/v/tests/builtin_arrays/array_of_option_fixed_array_test.v @@ -0,0 +1,32 @@ +module builtin_arrays + +fn test_array_of_option_fixed_array() { + mut arr := []?[3]u8{} + + fixed_arr1 := [3]u8{} + arr << fixed_arr1 + + fixed_arr2 := [u8(1), 2, 3]! + arr << fixed_arr2 + + arr << none + + println(arr) + + for i, item in arr { + if arr1 := item { + if i == 0 { + assert arr1 == [3]u8{} + } else if i == 1 { + assert arr1 == [u8(1), 2, 3]! + } + } else { + assert item == none + } + } + + assert arr.len == 3 + assert '${arr[0]}' == 'Option([0, 0, 0])' + assert '${arr[1]}' == 'Option([1, 2, 3])' + assert '${arr[2]}' == 'Option(none)' +}