checker: fix infinite recursion on generic interface cast

pull/13004/head
Delyan Angelov 2021-12-30 19:28:42 +02:00
parent df8384b62e
commit ae036b6146
No known key found for this signature in database
GPG Key ID: 66886C0F12D595ED
3 changed files with 26 additions and 0 deletions

View File

@ -1613,6 +1613,9 @@ fn (mut c Checker) fail_if_immutable(expr ast.Expr) (string, token.Position) {
} }
fn (mut c Checker) type_implements(typ ast.Type, interface_type ast.Type, pos token.Position) bool { fn (mut c Checker) type_implements(typ ast.Type, interface_type ast.Type, pos token.Position) bool {
if typ == interface_type {
return true
}
$if debug_interface_type_implements ? { $if debug_interface_type_implements ? {
eprintln('> type_implements typ: $typ.debug() (`${c.table.type_to_str(typ)}`) | inter_typ: $interface_type.debug() (`${c.table.type_to_str(interface_type)}`)') eprintln('> type_implements typ: $typ.debug() (`${c.table.type_to_str(typ)}`) | inter_typ: $interface_type.debug() (`${c.table.type_to_str(interface_type)}`)')
} }
@ -1642,6 +1645,10 @@ fn (mut c Checker) type_implements(typ ast.Type, interface_type ast.Type, pos to
} }
} }
if inter_sym.info.is_generic { if inter_sym.info.is_generic {
if inferred_type == interface_type {
// terminate early, since otherwise we get an infinite recursion/segfault:
return false
}
return c.type_implements(typ, inferred_type, pos) return c.type_implements(typ, inferred_type, pos)
} }
} }

View File

@ -0,0 +1,11 @@
vlib/v/checker/tests/interface_generic_err.vv:7:9: error: generic struct init must specify type parameter, e.g. Foo<int>
5 |
6 | // no segfault without generic
7 | what := What{}
| ~~~~~~
8 | why := Why(what)
vlib/v/checker/tests/interface_generic_err.vv:8:8: error: could not infer generic type `T` in interface
6 | // no segfault without generic
7 | what := What{}
8 | why := Why(what)
| ~~~~~~~~~

View File

@ -0,0 +1,8 @@
struct What<T> {}
// with or without generic
interface Why<T> {}
// no segfault without generic
what := What{}
why := Why(what)