cgen: interface fix + add more interface tests (#7776)
parent
d5b510df80
commit
82162b8ff8
|
@ -4196,6 +4196,10 @@ fn (mut g Gen) return_statement(node ast.Return) {
|
||||||
if !g.fn_decl.return_type.is_ptr() && node.types[0].is_ptr() {
|
if !g.fn_decl.return_type.is_ptr() && node.types[0].is_ptr() {
|
||||||
// Automatic Dereference for optional
|
// Automatic Dereference for optional
|
||||||
g.write('*')
|
g.write('*')
|
||||||
|
// Fixes returning a mutable receiver with interface as return type
|
||||||
|
if node.exprs[0] is ast.Ident && !g.is_amp {
|
||||||
|
g.write('&')
|
||||||
|
}
|
||||||
}
|
}
|
||||||
for i, expr in node.exprs {
|
for i, expr in node.exprs {
|
||||||
g.expr(expr)
|
g.expr(expr)
|
||||||
|
|
|
@ -788,7 +788,9 @@ fn (mut g Gen) call_args(node ast.CallExpr) {
|
||||||
exp_sym := g.table.get_type_symbol(expected_types[i])
|
exp_sym := g.table.get_type_symbol(expected_types[i])
|
||||||
// exp_styp := g.typ(expected_types[arg_no]) // g.table.get_type_symbol(expected_types[arg_no])
|
// exp_styp := g.typ(expected_types[arg_no]) // g.table.get_type_symbol(expected_types[arg_no])
|
||||||
// styp := g.typ(arg.typ) // g.table.get_type_symbol(arg.typ)
|
// styp := g.typ(arg.typ) // g.table.get_type_symbol(arg.typ)
|
||||||
if exp_sym.kind == .interface_ {
|
// NB: the second check avoids casting the interface into itself
|
||||||
|
// aka avoid 'I__Speaker_to_Interface_Speaker' thing for example
|
||||||
|
if exp_sym.kind == .interface_ && expected_types[i] != arg.typ {
|
||||||
g.interface_call(arg.typ, expected_types[i])
|
g.interface_call(arg.typ, expected_types[i])
|
||||||
is_interface = true
|
is_interface = true
|
||||||
}
|
}
|
||||||
|
|
|
@ -188,6 +188,52 @@ fn test_register() {
|
||||||
interface Speaker2 {
|
interface Speaker2 {
|
||||||
name() string
|
name() string
|
||||||
speak()
|
speak()
|
||||||
|
return_speaker() Speaker2
|
||||||
|
return_speaker2() ?Speaker2
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Boss {
|
||||||
|
mut:
|
||||||
|
name string
|
||||||
|
}
|
||||||
|
|
||||||
|
fn (b Boss) name() string {
|
||||||
|
return b.name
|
||||||
|
}
|
||||||
|
|
||||||
|
fn (b Boss) speak() {
|
||||||
|
println("i'm $b.name")
|
||||||
|
}
|
||||||
|
|
||||||
|
fn (b &Boss) return_speaker() Speaker2 {
|
||||||
|
return b
|
||||||
|
}
|
||||||
|
|
||||||
|
fn (mut b Boss) return_speaker2() ?Speaker2 {
|
||||||
|
if b.name == 'richard' {
|
||||||
|
return none
|
||||||
|
}
|
||||||
|
b.name = 'boss'
|
||||||
|
return b
|
||||||
|
}
|
||||||
|
|
||||||
|
fn return_speaker2(sp Speaker2) Speaker2 {
|
||||||
|
s := sp.return_speaker()
|
||||||
|
s2 := sp.return_speaker2() or {
|
||||||
|
return sp
|
||||||
|
}
|
||||||
|
s.speak()
|
||||||
|
s2.speak()
|
||||||
|
return s2
|
||||||
|
}
|
||||||
|
|
||||||
|
fn test_interface_returning_interface() {
|
||||||
|
mut b := Boss{'bob'}
|
||||||
|
assert b.name == 'bob'
|
||||||
|
s2 := return_speaker2(b)
|
||||||
|
if s2 is Boss {
|
||||||
|
assert s2.name == 'boss'
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct Foo {
|
struct Foo {
|
||||||
|
|
Loading…
Reference in New Issue