diff --git a/vlib/v/ast/types.v b/vlib/v/ast/types.v index 9c0ef4e9ac..410a009606 100644 --- a/vlib/v/ast/types.v +++ b/vlib/v/ast/types.v @@ -411,8 +411,18 @@ pub const ( error_type = new_type(error_type_idx) charptr_types = [charptr_type, new_type(char_type_idx).set_nr_muls(1)] byteptr_types = [byteptr_type, new_type(byte_type_idx).set_nr_muls(1)] + voidptr_types = [voidptr_type, new_type(voidptr_type_idx).set_nr_muls(1)] + cptr_types = merge_types(voidptr_types, byteptr_types, charptr_types) ) +pub fn merge_types(params ...[]Type) []Type { + mut res := []Type{} + for types in params { + res << types + } + return res +} + pub const ( builtin_type_names = ['void', 'voidptr', 'charptr', 'byteptr', 'i8', 'i16', 'int', 'i64', 'u16', 'u32', 'u64', 'int_literal', 'f32', 'f64', 'float_literal', 'string', 'ustring', 'char', diff --git a/vlib/v/gen/c/auto_str_methods.v b/vlib/v/gen/c/auto_str_methods.v index dbe6630d42..941a1ca4c5 100644 --- a/vlib/v/gen/c/auto_str_methods.v +++ b/vlib/v/gen/c/auto_str_methods.v @@ -728,12 +728,12 @@ fn (g &Gen) type_to_fmt1(typ ast.Type) StrIntpType { if typ == ast.char_type_idx { return .si_c } - if typ == ast.voidptr_type_idx || typ in ast.byteptr_types { + if typ in ast.voidptr_types || typ in ast.byteptr_types { return .si_p } if typ in ast.charptr_types { - return .si_s // return '%C\\000' // a C string + return .si_s } sym := g.table.get_type_symbol(typ) if typ.is_ptr() && (typ.is_int_valptr() || typ.is_float_valptr()) { @@ -831,10 +831,10 @@ fn (mut g Gen) gen_str_for_struct(info ast.Struct, styp string, str_fn_name stri } mut func := struct_auto_str_func1(sym, field.typ, field_styp_fn_name, field.name) - - // manage reference types can be "nil" - if field.typ.is_ptr() && !(field.typ in ast.charptr_types - || field.typ in ast.byteptr_types || field.typ == ast.voidptr_type_idx) { + if field.typ in ast.cptr_types { + func = '(voidptr) it.$field.name' + } else if field.typ.is_ptr() { + // reference types can be "nil" fn_builder.write_string('isnil(it.${c_name(field.name)})') fn_builder.write_string(' ? _SLIT("nil") : ') // struct, floats and ints have a special case through the _str function diff --git a/vlib/v/tests/interface_edge_cases/empty_interface_1_test.v b/vlib/v/tests/interface_edge_cases/empty_interface_1_test.v new file mode 100644 index 0000000000..160393c0f9 --- /dev/null +++ b/vlib/v/tests/interface_edge_cases/empty_interface_1_test.v @@ -0,0 +1,16 @@ +interface IEmpty {} + +struct Abc { + x string +} + +fn test_empty_interface_string_interpolation() { + a := IEmpty(u64(1)) + b := IEmpty(f32(1)) + c := IEmpty(Abc{'abc'}) + assert '$a' == 'IEmpty(1)' + assert '$b' == 'IEmpty(1.)' + assert '$c'.starts_with('IEmpty(Abc{') + assert '$c'.contains("x: 'abc'") + assert '$c'.ends_with('})') +} diff --git a/vlib/v/tests/interface_edge_cases/empty_interface_println_test.v b/vlib/v/tests/interface_edge_cases/empty_interface_println_test.v new file mode 100644 index 0000000000..d8acc559d5 --- /dev/null +++ b/vlib/v/tests/interface_edge_cases/empty_interface_println_test.v @@ -0,0 +1,11 @@ +interface IEmpty { +} + +struct Abc { + abc int +} + +fn test_an_empty_interface_can_be_printed() { + println(IEmpty(Abc{123})) + assert true +} diff --git a/vlib/v/tests/structs_with_voidptr_fields_can_be_printed_test.v b/vlib/v/tests/structs_with_voidptr_fields_can_be_printed_test.v new file mode 100644 index 0000000000..6c44ae65b4 --- /dev/null +++ b/vlib/v/tests/structs_with_voidptr_fields_can_be_printed_test.v @@ -0,0 +1,13 @@ +struct Abc { +mut: + vptr voidptr + vptrptr &voidptr = 0 + bptr &byte = 0 + cptr &char = c'abcdef' +} + +fn test_structs_can_be_printed() { + a := Abc{} + println(a) + assert true +}