cgen: interface fix + add more interface tests (#7776)

pull/7871/head
Ned Palacios 2021-01-05 03:54:13 +08:00 committed by GitHub
parent d5b510df80
commit 82162b8ff8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 53 additions and 1 deletions

View File

@ -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() {
// Automatic Dereference for optional
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 {
g.expr(expr)

View File

@ -788,7 +788,9 @@ fn (mut g Gen) call_args(node ast.CallExpr) {
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])
// 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])
is_interface = true
}

View File

@ -188,6 +188,52 @@ fn test_register() {
interface Speaker2 {
name() string
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 {