mirror of
https://github.com/vlang/v.git
synced 2025-09-13 22:42:26 +03:00
This commit is contained in:
parent
4eb087a347
commit
5fcfc27e50
10 changed files with 129 additions and 6 deletions
|
@ -626,6 +626,8 @@ fn (t Tree) struct_decl(node ast.StructDecl) &Node {
|
|||
obj.add_terse('attrs', t.array_node_attr(node.attrs))
|
||||
obj.add('end_comments', t.array_node_comment(node.end_comments))
|
||||
obj.add_terse('embeds', t.array_node_embed(node.embeds))
|
||||
obj.add('is_implements', t.bool_node(node.is_implements))
|
||||
obj.add_terse('implements_types', t.array_node_type_expr(node.implements_types))
|
||||
return obj
|
||||
}
|
||||
|
||||
|
|
|
@ -418,7 +418,7 @@ pub:
|
|||
embeds []Embed
|
||||
|
||||
is_implements bool
|
||||
implements_types []Type
|
||||
implements_types []TypeNode
|
||||
pub mut:
|
||||
fields []StructField
|
||||
}
|
||||
|
|
|
@ -952,6 +952,11 @@ pub fn (t &Struct) is_empty_struct() bool {
|
|||
return t.fields.len == 0 && t.embeds.len == 0
|
||||
}
|
||||
|
||||
@[inline]
|
||||
pub fn (t &Struct) is_unresolved_generic() bool {
|
||||
return t.generic_types.len > 0 && t.concrete_types.len == 0
|
||||
}
|
||||
|
||||
pub fn (t &TypeSymbol) is_array_fixed() bool {
|
||||
if t.info is ArrayFixed {
|
||||
return true
|
||||
|
|
|
@ -334,7 +334,24 @@ fn (mut c Checker) struct_decl(mut node ast.StructDecl) {
|
|||
// cgen error if I use `println(sym)` without handling the option with `or{}`
|
||||
struct_type := c.table.find_type_idx(node.name) // or { panic(err) }
|
||||
for t in node.implements_types {
|
||||
c.type_implements(struct_type, t, node.pos)
|
||||
t_sym := c.table.sym(t.typ)
|
||||
if t_sym.info is ast.Interface {
|
||||
if t_sym.info.is_generic {
|
||||
itype_name := c.table.type_to_str(t.typ)
|
||||
if !itype_name.contains('[') {
|
||||
c.error('missing generic type on ${t_sym.name}', t.pos)
|
||||
}
|
||||
if itype_name.contains('<') {
|
||||
struct_generic_letters := node.generic_types.map(c.table.type_to_str(it))
|
||||
unknown_letters := itype_name.all_after('<').all_before('>').split(',').filter(it !in struct_generic_letters)
|
||||
if unknown_letters.len > 0 {
|
||||
c.error('unknown generic type ${unknown_letters.first()}',
|
||||
t.pos)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
c.type_implements(struct_type, t.typ, node.pos)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
21
vlib/v/checker/tests/implements_generic_err.out
Normal file
21
vlib/v/checker/tests/implements_generic_err.out
Normal file
|
@ -0,0 +1,21 @@
|
|||
vlib/v/checker/tests/implements_generic_err.vv:12:31: error: missing generic type on IB
|
||||
10 | }
|
||||
11 |
|
||||
12 | struct Foo1[T] implements IA, IB {
|
||||
| ~~
|
||||
13 | a int
|
||||
14 | b T
|
||||
vlib/v/checker/tests/implements_generic_err.vv:17:31: error: unknown generic type Y
|
||||
15 | }
|
||||
16 |
|
||||
17 | struct Foo2[T] implements IA, IB[Y] {
|
||||
| ~~
|
||||
18 | a int
|
||||
19 | b T
|
||||
vlib/v/checker/tests/implements_generic_err.vv:22:31: error: unknown generic type Y
|
||||
20 | }
|
||||
21 |
|
||||
22 | struct Foo3[T] implements IA, IB[T,Y] {
|
||||
| ~~
|
||||
23 | a int
|
||||
24 | b T
|
37
vlib/v/checker/tests/implements_generic_err.vv
Normal file
37
vlib/v/checker/tests/implements_generic_err.vv
Normal file
|
@ -0,0 +1,37 @@
|
|||
interface IA {
|
||||
a int
|
||||
fa()
|
||||
}
|
||||
|
||||
interface IB[T] {
|
||||
a int
|
||||
b T
|
||||
fa()
|
||||
}
|
||||
|
||||
struct Foo1[T] implements IA, IB {
|
||||
a int
|
||||
b T
|
||||
}
|
||||
|
||||
struct Foo2[T] implements IA, IB[Y] {
|
||||
a int
|
||||
b T
|
||||
}
|
||||
|
||||
struct Foo3[T] implements IA, IB[T,Y] {
|
||||
a int
|
||||
b T
|
||||
}
|
||||
|
||||
fn (foo Foo1[T]) fa() {
|
||||
println(foo.b)
|
||||
}
|
||||
|
||||
fn (foo Foo2[T]) fa() {
|
||||
println(foo.b)
|
||||
}
|
||||
|
||||
fn (foo Foo3[T]) fa() {
|
||||
println(foo.b)
|
||||
}
|
|
@ -34,11 +34,11 @@ pub fn (mut f Fmt) struct_decl(node ast.StructDecl, is_anon bool) {
|
|||
if node.is_implements {
|
||||
f.write(' implements ')
|
||||
for i, t in node.implements_types {
|
||||
f.write(f.table.type_to_str_using_aliases(t, f.mod2alias))
|
||||
f.write(f.table.type_to_str_using_aliases(t.typ, f.mod2alias))
|
||||
if i < node.implements_types.len - 1 {
|
||||
f.write(', ')
|
||||
}
|
||||
f.mark_types_import_as_used(t)
|
||||
f.mark_types_import_as_used(t.typ)
|
||||
}
|
||||
}
|
||||
// Calculate the alignments first
|
||||
|
|
|
@ -1055,6 +1055,9 @@ pub fn (mut g Gen) write_typeof_functions() {
|
|||
g.writeln('static char * v_typeof_interface_${sym.cname}(int sidx) { /* ${sym.name} */ ')
|
||||
for t in inter_info.types {
|
||||
sub_sym := g.table.sym(ast.mktyp(t))
|
||||
if sub_sym.info is ast.Struct && sub_sym.info.is_unresolved_generic() {
|
||||
continue
|
||||
}
|
||||
g.writeln('\tif (sidx == _${sym.cname}_${sub_sym.cname}_index) return "${util.strip_main_name(sub_sym.name)}";')
|
||||
}
|
||||
g.writeln('\treturn "unknown ${util.strip_main_name(sym.name)}";')
|
||||
|
@ -1063,6 +1066,9 @@ pub fn (mut g Gen) write_typeof_functions() {
|
|||
g.writeln('static int v_typeof_interface_idx_${sym.cname}(int sidx) { /* ${sym.name} */ ')
|
||||
for t in inter_info.types {
|
||||
sub_sym := g.table.sym(ast.mktyp(t))
|
||||
if sub_sym.info is ast.Struct && sub_sym.info.is_unresolved_generic() {
|
||||
continue
|
||||
}
|
||||
g.writeln('\tif (sidx == _${sym.cname}_${sub_sym.cname}_index) return ${int(t.set_nr_muls(0))};')
|
||||
}
|
||||
g.writeln('\treturn ${int(ityp)};')
|
||||
|
@ -7688,6 +7694,10 @@ fn (mut g Gen) interface_table() string {
|
|||
iinidx_minimum_base := 1000 // Note: NOT 0, to avoid map entries set to 0 later, so `if already_generated_mwrappers[name] > 0 {` works.
|
||||
mut current_iinidx := iinidx_minimum_base
|
||||
for st in inter_info.types {
|
||||
st_sym_info := g.table.sym(st)
|
||||
if st_sym_info.info is ast.Struct && st_sym_info.info.is_unresolved_generic() {
|
||||
continue
|
||||
}
|
||||
st_sym := g.table.sym(ast.mktyp(st))
|
||||
// cctype is the Cleaned Concrete Type name, *without ptr*,
|
||||
// i.e. cctype is always just Cat, not Cat_ptr:
|
||||
|
|
|
@ -94,7 +94,7 @@ fn (mut p Parser) struct_decl(is_anon bool) ast.StructDecl {
|
|||
mut is_field_pub := false
|
||||
mut is_field_global := false
|
||||
mut is_implements := false
|
||||
mut implements_types := []ast.Type{cap: 3} // ast.void_type
|
||||
mut implements_types := []ast.TypeNode{cap: 3} // ast.void_type
|
||||
mut last_line := p.prev_tok.pos().line_nr + 1
|
||||
mut end_comments := []ast.Comment{}
|
||||
if !no_body {
|
||||
|
@ -102,7 +102,11 @@ fn (mut p Parser) struct_decl(is_anon bool) ast.StructDecl {
|
|||
is_implements = true
|
||||
for {
|
||||
p.next()
|
||||
implements_types << p.parse_type()
|
||||
type_pos := p.tok.pos()
|
||||
implements_types << ast.TypeNode{
|
||||
typ: p.parse_type()
|
||||
pos: type_pos
|
||||
}
|
||||
if p.tok.kind != .comma {
|
||||
break
|
||||
}
|
||||
|
|
27
vlib/v/tests/interfaces/interface_generic_test.v
Normal file
27
vlib/v/tests/interfaces/interface_generic_test.v
Normal file
|
@ -0,0 +1,27 @@
|
|||
interface IA {
|
||||
a int
|
||||
fa()
|
||||
}
|
||||
|
||||
interface IB[T] {
|
||||
a int
|
||||
b T
|
||||
fa()
|
||||
}
|
||||
|
||||
struct Foo[T] implements IA, IB[T] {
|
||||
a int
|
||||
b T
|
||||
}
|
||||
|
||||
fn (foo Foo[T]) fa() {
|
||||
println(foo.b)
|
||||
}
|
||||
|
||||
fn test_main() {
|
||||
foo := Foo[u8]{
|
||||
b: 16
|
||||
}
|
||||
foo.fa()
|
||||
assert true
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue