cgen: fix error of the interface str method (fix #12538) (#12620)

pull/12626/head
yuyi 2021-11-30 21:03:44 +08:00 committed by GitHub
parent 7d9028db56
commit d1b0ce9e0c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 44 additions and 1 deletions

View File

@ -7367,7 +7367,7 @@ static inline $interface_name I_${cctype}_to_Interface_${interface_name}($cctype
// .speak = Cat_speak_Interface_Animal_method_wrapper // .speak = Cat_speak_Interface_Animal_method_wrapper
method_call += iwpostfix method_call += iwpostfix
} }
if g.pref.build_mode != .build_module { if g.pref.build_mode != .build_module && st != ast.voidptr_type {
methods_struct.writeln('\t\t._method_${c_name(method.name)} = (void*) $method_call,') methods_struct.writeln('\t\t._method_${c_name(method.name)} = (void*) $method_call,')
} }
} }

View File

@ -1141,6 +1141,19 @@ fn (mut g Gen) fn_call(node ast.CallExpr) {
} }
if typ != ast.string_type { if typ != ast.string_type {
expr := node.args[0].expr expr := node.args[0].expr
typ_sym := g.table.get_type_symbol(typ)
if typ_sym.kind == .interface_ && (typ_sym.info as ast.Interface).defines_method('str') {
g.write('${c_name(print_method)}(')
rec_type_name := util.no_dots(g.cc_type(typ, false))
g.write('${c_name(rec_type_name)}_name_table[')
g.expr(expr)
dot := if typ.is_ptr() { '->' } else { '.' }
g.write('${dot}_typ]._method_str(')
g.expr(expr)
g.write('${dot}_object')
g.writeln('));')
return
}
if g.is_autofree && !typ.has_flag(.optional) { if g.is_autofree && !typ.has_flag(.optional) {
// Create a temporary variable so that the value can be freed // Create a temporary variable so that the value can be freed
tmp := g.new_tmp_var() tmp := g.new_tmp_var()

View File

@ -125,6 +125,7 @@ fn (mut g Gen) str_val(node ast.StringInterLiteral, i int) {
expr := node.exprs[i] expr := node.exprs[i]
typ := g.unwrap_generic(node.expr_types[i]) typ := g.unwrap_generic(node.expr_types[i])
typ_sym := g.table.get_type_symbol(typ)
if typ == ast.string_type { if typ == ast.string_type {
if g.inside_vweb_tmpl { if g.inside_vweb_tmpl {
g.write('vweb__filter(') g.write('vweb__filter(')
@ -139,6 +140,15 @@ fn (mut g Gen) str_val(node ast.StringInterLiteral, i int) {
} }
g.expr(expr) g.expr(expr)
} }
} else if typ_sym.kind == .interface_ && (typ_sym.info as ast.Interface).defines_method('str') {
rec_type_name := util.no_dots(g.cc_type(typ, false))
g.write('${c_name(rec_type_name)}_name_table[')
g.expr(expr)
dot := if typ.is_ptr() { '->' } else { '.' }
g.write('${dot}_typ]._method_str(')
g.expr(expr)
g.write('${dot}_object')
g.write(')')
} else if node.fmts[i] == `s` || typ.has_flag(.variadic) { } else if node.fmts[i] == `s` || typ.has_flag(.variadic) {
mut exp_typ := typ mut exp_typ := typ
if expr is ast.Ident && g.comptime_var_type_map.len > 0 { if expr is ast.Ident && g.comptime_var_type_map.len > 0 {

View File

@ -0,0 +1,20 @@
interface Str {
str() string
}
struct St {}
fn (s St) str() string {
return 's'
}
fn printer(s Str) string {
println(s)
return '$s'
}
fn test_interface_str_method() {
s := St{}
ret := printer(s)
assert ret == 's'
}