Skip to content

Commit

Permalink
ast, parser, checker: check struct implements non interface type
Browse files Browse the repository at this point in the history
  • Loading branch information
yuyi98 committed Sep 14, 2024
1 parent 26ab7d4 commit 8e915f2
Show file tree
Hide file tree
Showing 5 changed files with 39 additions and 20 deletions.
5 changes: 3 additions & 2 deletions vlib/v/ast/ast.v
Original file line number Diff line number Diff line change
Expand Up @@ -417,8 +417,9 @@ pub:
end_comments []Comment
embeds []Embed

is_implements bool
implements_types []Type
is_implements bool
implements_types []Type
implements_types_pos token.Pos
pub mut:
fields []StructField
}
Expand Down
4 changes: 4 additions & 0 deletions vlib/v/checker/struct.v
Original file line number Diff line number Diff line change
Expand Up @@ -334,6 +334,10 @@ 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 {
t_sym := c.table.sym(t)
if t_sym.kind != .interface_ {
c.error('`${t_sym.name}` is not an interface type', node.implements_types_pos)
}
c.type_implements(struct_type, t, node.pos)
}
}
Expand Down
5 changes: 5 additions & 0 deletions vlib/v/checker/tests/struct_implements_non_interface_err.out
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
vlib/v/checker/tests/struct_implements_non_interface_err.vv:1:26: error: `Abcde` is not an interface type
1 | struct Walker implements Abcde {
| ~~~~~
2 | aaa string
3 | }
5 changes: 5 additions & 0 deletions vlib/v/checker/tests/struct_implements_non_interface_err.vv
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
struct Walker implements Abcde {
aaa string
}

fn main() {}
40 changes: 22 additions & 18 deletions vlib/v/parser/struct.v
Original file line number Diff line number Diff line change
Expand Up @@ -97,16 +97,19 @@ fn (mut p Parser) struct_decl(is_anon bool) ast.StructDecl {
mut implements_types := []ast.Type{cap: 3} // ast.void_type
mut last_line := p.prev_tok.pos().line_nr + 1
mut end_comments := []ast.Comment{}
mut implements_types_pos := token.Pos{}
if !no_body {
if p.tok.kind == .key_implements {
is_implements = true
start_implements_pos := p.peek_tok.pos()
for {
p.next()
implements_types << p.parse_type()
if p.tok.kind != .comma {
break
}
}
implements_types_pos = start_implements_pos.extend(p.prev_tok.pos())
}
p.check(.lcbr)
pre_comments << p.eat_comments()
Expand Down Expand Up @@ -383,24 +386,25 @@ fn (mut p Parser) struct_decl(is_anon bool) ast.StructDecl {
}
p.expr_mod = ''
return ast.StructDecl{
name: name
is_pub: is_pub
fields: ast_fields
pos: start_pos.extend_with_last_line(name_pos, last_line)
mut_pos: mut_pos
pub_pos: pub_pos
pub_mut_pos: pub_mut_pos
global_pos: global_pos
module_pos: module_pos
language: language
is_union: is_union
attrs: if is_anon { []ast.Attr{} } else { attrs } // anon structs can't have attributes
pre_comments: pre_comments
end_comments: end_comments
generic_types: generic_types
embeds: embeds
is_implements: is_implements
implements_types: implements_types
name: name
is_pub: is_pub
fields: ast_fields
pos: start_pos.extend_with_last_line(name_pos, last_line)
mut_pos: mut_pos
pub_pos: pub_pos
pub_mut_pos: pub_mut_pos
global_pos: global_pos
module_pos: module_pos
language: language
is_union: is_union
attrs: if is_anon { []ast.Attr{} } else { attrs } // anon structs can't have attributes
pre_comments: pre_comments
end_comments: end_comments
generic_types: generic_types
embeds: embeds
is_implements: is_implements
implements_types: implements_types
implements_types_pos: implements_types_pos
}
}

Expand Down

0 comments on commit 8e915f2

Please sign in to comment.