checker: fix generic type ignores implemented interface (#9124)

pull/9128/head
Gal Pasternak 2021-03-05 06:59:18 +02:00 committed by GitHub
parent cce006b129
commit 208cabc994
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 41 additions and 5 deletions

View File

@ -2030,10 +2030,11 @@ fn (mut c Checker) type_implements(typ table.Type, inter_typ table.Type, pos tok
$if debug_interface_type_implements ? { $if debug_interface_type_implements ? {
eprintln('> type_implements typ: $typ.debug() | inter_typ: $inter_typ.debug()') eprintln('> type_implements typ: $typ.debug() | inter_typ: $inter_typ.debug()')
} }
typ_sym := c.table.get_type_symbol(typ) utyp := c.unwrap_generic(typ)
typ_sym := c.table.get_type_symbol(utyp)
mut inter_sym := c.table.get_type_symbol(inter_typ) mut inter_sym := c.table.get_type_symbol(inter_typ)
styp := c.table.type_to_str(typ) styp := c.table.type_to_str(utyp)
same_base_type := typ.idx() == inter_typ.idx() same_base_type := utyp.idx() == inter_typ.idx()
if typ_sym.kind == .interface_ && inter_sym.kind == .interface_ && !same_base_type { if typ_sym.kind == .interface_ && inter_sym.kind == .interface_ && !same_base_type {
c.error('cannot implement interface `$inter_sym.name` with a different interface `$styp`', c.error('cannot implement interface `$inter_sym.name` with a different interface `$styp`',
pos) pos)
@ -2077,8 +2078,8 @@ fn (mut c Checker) type_implements(typ table.Type, inter_typ table.Type, pos tok
c.error("`$styp` doesn't implement field `$ifield.name` of interface `$inter_sym.name`", c.error("`$styp` doesn't implement field `$ifield.name` of interface `$inter_sym.name`",
pos) pos)
} }
if typ !in inter_sym.info.types && typ_sym.kind != .interface_ { if utyp !in inter_sym.info.types && typ_sym.kind != .interface_ {
inter_sym.info.types << typ inter_sym.info.types << utyp
} }
} }
return true return true

View File

@ -0,0 +1,35 @@
// The series of i?_test.v files, do test different edge cases for
// interface table generation. The differences may seem very minor
// (placement of the interface declaration, whether or not there are
// helper methods, etc), but PLEASE do NOT be tempted to merge them in
// a single _test.v file. Debugging interface code generation issues
// is *much easier* when the _test.v files are very short and focused.
struct Point {
x i8
y i8
}
fn (p Point) draw() string {
return 'Point($p.x,$p.y)'
}
fn to_string(d Drawer) {
println(d.draw())
}
interface Drawer {
draw() string
}
fn to_string_generic<T>(t T) {
to_string(t)
}
fn test_to_string_generic_can_be_called() {
p := Point{
x: 2
y: 3
}
to_string_generic(p)
assert true
}