mirror of
https://github.com/vlang/v.git
synced 2025-09-09 15:27:05 -04:00
cgen: fix interface generic smartcast (#20609)
This commit is contained in:
parent
672fe9b8eb
commit
2874e7cac0
@ -4649,7 +4649,7 @@ fn (mut g Gen) ident(node ast.Ident) {
|
|||||||
g.write('(*(')
|
g.write('(*(')
|
||||||
}
|
}
|
||||||
if node.obj.smartcasts.len > 0 {
|
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 {
|
if !prevent_sum_type_unwrapping_once {
|
||||||
for _, typ in node.obj.smartcasts {
|
for _, typ in node.obj.smartcasts {
|
||||||
is_option_unwrap := is_option && typ == node.obj.typ.clear_flag(.option)
|
is_option_unwrap := is_option && typ == node.obj.typ.clear_flag(.option)
|
||||||
@ -4665,7 +4665,9 @@ fn (mut g Gen) ident(node ast.Ident) {
|
|||||||
g.write('*')
|
g.write('*')
|
||||||
}
|
}
|
||||||
} else if (g.inside_interface_deref && g.table.is_interface_var(node.obj))
|
} 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('*')
|
g.write('*')
|
||||||
} else if is_option {
|
} else if is_option {
|
||||||
g.write('*(${g.base_type(node.obj.typ)}*)')
|
g.write('*(${g.base_type(node.obj.typ)}*)')
|
||||||
|
46
vlib/v/tests/generic_smartcast_test.v
Normal file
46
vlib/v/tests/generic_smartcast_test.v
Normal file
@ -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
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user