diff --git a/vlib/v/checker/checker.v b/vlib/v/checker/checker.v index ddbe16b238..cc898c24d4 100644 --- a/vlib/v/checker/checker.v +++ b/vlib/v/checker/checker.v @@ -1232,6 +1232,10 @@ pub fn (mut c Checker) return_stmt(mut return_stmt ast.Return) { if is_generic { exp_typ_sym = c.table.get_type_symbol(c.cur_generic_type) } + if exp_typ_sym.kind == .interface_ { + c.type_implements(got_typ, exp_type, return_stmt.pos) + continue + } c.error('cannot use `$got_typ_sym.name` as type `$exp_typ_sym.name` in return argument', pos) } diff --git a/vlib/v/gen/cgen.v b/vlib/v/gen/cgen.v index d4a4560be0..0359046699 100644 --- a/vlib/v/gen/cgen.v +++ b/vlib/v/gen/cgen.v @@ -2300,7 +2300,7 @@ fn (mut g Gen) return_statement(node ast.Return) { if fn_return_is_optional && !node.types[0].flag_is(.optional) && return_sym.name != 'Option' { styp := g.base_type(g.fn_decl.return_type) - g.write('/*:)$return_sym.name*/opt_ok(&($styp[]) { ') + g.write('/*$return_sym.name*/opt_ok(&($styp[]) { ') if !g.fn_decl.return_type.is_ptr() && node.types[0].is_ptr() { // Automatic Dereference for optional g.write('*') @@ -2314,7 +2314,13 @@ fn (mut g Gen) return_statement(node ast.Return) { g.writeln(' }, sizeof($styp));') return } + if sym.kind == .interface_ { + g.interface_call(node.types[0], g.fn_decl.return_type) + } g.expr_with_cast(node.exprs[0], node.types[0], g.fn_decl.return_type) + if sym.kind == .interface_ { + g.write(')') + } } g.writeln(';') } diff --git a/vlib/v/tests/interface_test.v b/vlib/v/tests/interface_test.v index 33712ed1fc..f6da952007 100644 --- a/vlib/v/tests/interface_test.v +++ b/vlib/v/tests/interface_test.v @@ -238,3 +238,8 @@ fn foo2(a Animal) int { return 0 } } + +fn new_animal() Animal { + dog := Dog{} + return dog +}