diff --git a/vlib/v/checker/check_types.v b/vlib/v/checker/check_types.v index 72157515a4..688384ac4e 100644 --- a/vlib/v/checker/check_types.v +++ b/vlib/v/checker/check_types.v @@ -314,7 +314,7 @@ pub fn (c &Checker) get_default_fmt(ftyp table.Type, typ table.Type) byte { } else if typ.is_pointer() { return `p` } else { - mut sym := c.table.get_type_symbol(ftyp) + mut sym := c.table.get_type_symbol(c.unwrap_generic(ftyp)) if sym.kind == .alias { // string aliases should be printable info := sym.info as table.Alias diff --git a/vlib/v/gen/auto_str_methods.v b/vlib/v/gen/auto_str_methods.v index 96150dbf02..9bf68fd97c 100644 --- a/vlib/v/gen/auto_str_methods.v +++ b/vlib/v/gen/auto_str_methods.v @@ -8,7 +8,7 @@ import v.util // already generated styp, reuse it fn (mut g Gen) gen_str_for_type_with_styp(typ table.Type, styp string) string { - mut sym := g.table.get_type_symbol(typ) + mut sym := g.table.get_type_symbol(g.unwrap_generic(typ)) mut str_fn_name := styp_to_str_fn_name(styp) if sym.info is table.Alias { sym = g.table.get_type_symbol((sym.info as table.Alias).parent_type) diff --git a/vlib/v/gen/str.v b/vlib/v/gen/str.v index c65cf77281..5fd954402a 100644 --- a/vlib/v/gen/str.v +++ b/vlib/v/gen/str.v @@ -336,30 +336,31 @@ fn (mut g Gen) string_inter_literal(node ast.StringInterLiteral) { if node.precisions[i] != 987698 { fmt = '${fmt}.${node.precisions[i]}' } + typ := g.unwrap_generic(node.expr_types[i]) if fspec == `s` { if node.fwidths[i] == 0 { g.write('.*s') } else { g.write('*.*s') } - } else if node.expr_types[i].is_float() { + } else if typ.is_float() { g.write('$fmt${fspec:c}') - } else if node.expr_types[i].is_pointer() { + } else if typ.is_pointer() { if fspec == `p` { g.write('${fmt}p') } else { g.write('$fmt"PRI${fspec:c}PTR"') } - } else if node.expr_types[i].is_int() { + } else if typ.is_int() { if fspec == `c` { g.write('${fmt}c') } else { g.write('$fmt"PRI${fspec:c}') - if node.expr_types[i] in [table.i8_type, table.byte_type] { + if typ in [table.i8_type, table.byte_type] { g.write('8') - } else if node.expr_types[i] in [table.i16_type, table.u16_type] { + } else if typ in [table.i16_type, table.u16_type] { g.write('16') - } else if node.expr_types[i] in [table.i64_type, table.u64_type] { + } else if typ in [table.i64_type, table.u64_type] { g.write('64') } else { g.write('32') @@ -378,7 +379,8 @@ fn (mut g Gen) string_inter_literal(node ast.StringInterLiteral) { g.write('", $num_string_parts, ') // Build args for i, expr in node.exprs { - if node.expr_types[i] == table.string_type { + typ := g.unwrap_generic(node.expr_types[i]) + if typ == table.string_type { if g.inside_vweb_tmpl { g.write('vweb__filter(') g.expr(expr) @@ -386,18 +388,17 @@ fn (mut g Gen) string_inter_literal(node ast.StringInterLiteral) { } else { g.expr(expr) } - } else if node.expr_types[i] == table.bool_type { + } else if typ == table.bool_type { g.expr(expr) g.write(' ? _SLIT("true") : _SLIT("false")') - } else if node.expr_types[i].is_number() || node.expr_types[i].is_pointer() || - node.fmts[i] == `d` { - if node.expr_types[i].is_signed() && node.fmts[i] in [`x`, `X`, `o`] { + } else if typ.is_number() || typ.is_pointer() || node.fmts[i] == `d` { + if typ.is_signed() && node.fmts[i] in [`x`, `X`, `o`] { // convert to unsigned first befors C's integer propagation strikes - if node.expr_types[i] == table.i8_type { + if typ == table.i8_type { g.write('(byte)(') - } else if node.expr_types[i] == table.i16_type { + } else if typ == table.i16_type { g.write('(u16)(') - } else if node.expr_types[i] == table.int_type { + } else if typ == table.int_type { g.write('(u32)(') } else { g.write('(u64)(') @@ -408,7 +409,7 @@ fn (mut g Gen) string_inter_literal(node ast.StringInterLiteral) { g.expr(expr) } } else if node.fmts[i] == `s` { - g.gen_expr_to_string(expr, node.expr_types[i]) + g.gen_expr_to_string(expr, typ) } else { g.expr(expr) } diff --git a/vlib/v/tests/str_gen_test.v b/vlib/v/tests/str_gen_test.v index 65e681eccf..7254c2a8ee 100644 --- a/vlib/v/tests/str_gen_test.v +++ b/vlib/v/tests/str_gen_test.v @@ -218,3 +218,16 @@ fn test_map_with_struct() { assert a.str() == 'MapWithStruct{\n foo: {\'test\': TestStruct{\n x: 0\n }}\n}' assert '$a' == 'MapWithStruct{\n foo: {\'test\': TestStruct{\n x: 0\n }}\n}' } + +struct ForGeneric {} +fn generic_fn_interpolation(p T) string { + return '$p' +} +fn generic_fn_str(p T) string { + return p.str() +} +fn test_generic_auto_str() { + s := ForGeneric{} + assert generic_fn_interpolation(s) == 'ForGeneric{}' + assert generic_fn_str(s) == 'ForGeneric{}' +}