Skip to content

Commit

Permalink
cgen: fix interface generic smartcast (#20609)
Browse files Browse the repository at this point in the history
  • Loading branch information
felipensp committed Jan 23, 2024
1 parent 672fe9b commit 2874e7c
Show file tree
Hide file tree
Showing 2 changed files with 50 additions and 2 deletions.
6 changes: 4 additions & 2 deletions vlib/v/gen/c/cgen.v
Expand Up @@ -4649,7 +4649,7 @@ fn (mut g Gen) ident(node ast.Ident) {
g.write('(*(')
}
if node.obj.smartcasts.len > 0 {
obj_sym := g.table.sym(node.obj.typ)
obj_sym := g.table.sym(g.unwrap_generic(node.obj.typ))
if !prevent_sum_type_unwrapping_once {
for _, typ in node.obj.smartcasts {
is_option_unwrap := is_option && typ == node.obj.typ.clear_flag(.option)
Expand All @@ -4665,7 +4665,9 @@ fn (mut g Gen) ident(node ast.Ident) {
g.write('*')
}
} else if (g.inside_interface_deref && g.table.is_interface_var(node.obj))
|| node.obj.ct_type_var == .smartcast {
|| node.obj.ct_type_var == .smartcast
|| (obj_sym.kind == .interface_
&& g.table.type_kind(node.obj.typ) == .any) {
g.write('*')
} else if is_option {
g.write('*(${g.base_type(node.obj.typ)}*)')
Expand Down
46 changes: 46 additions & 0 deletions vlib/v/tests/generic_smartcast_test.v
@@ -0,0 +1,46 @@
fn cast_interface[T, U](u U) T {
$if U is $interface {
if u is T {
return u
} else {
panic('expected t to be ${typeof[T]().name}, got ${typeof[U]().name}')
}
} $else {
$compile_error('not an interface')
}
}

interface Foo {
f()
}

struct Bar {}

fn (bar Bar) f() {}

struct Baz {}

fn (baz Baz) f() {}

fn (_ Bar) g() int {
return 0
}

fn (_ Baz) g() int {
return 1
}

fn f(foo Foo) int {
if foo is Bar {
return cast_interface[Bar, Foo](foo).g()
}
if foo is Baz {
return cast_interface[Baz, Foo](foo).g()
}
return -1
}

fn test_main() {
assert f(Bar{}) == 0
assert f(Baz{}) == 1
}

0 comments on commit 2874e7c

Please sign in to comment.