checker: check that type exists in TypeDecl

pull/4601/head
Enzo Baldisserri 2020-04-26 06:40:54 +02:00 committed by GitHub
parent 541b058e90
commit 0b3412cdb5
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 90 additions and 21 deletions

View File

@ -155,6 +155,40 @@ fn (mut c Checker) check_file_in_main(file ast.File) bool {
return has_main_fn
}
pub fn (mut c Checker) type_decl(node ast.TypeDecl) {
match node {
ast.AliasTypeDecl {
typ_sym := c.table.get_type_symbol(it.parent_type)
if typ_sym.kind == .placeholder {
c.error("type `$typ_sym.name` doesn't exist", it.pos)
}
}
ast.FnTypeDecl {
typ_sym := c.table.get_type_symbol(it.typ)
fn_typ_info := typ_sym.info as table.FnType
fn_info := fn_typ_info.func
ret_sym := c.table.get_type_symbol(fn_info.return_type)
if ret_sym.kind == .placeholder {
c.error("type `$ret_sym.name` doesn't exist", it.pos)
}
for arg in fn_info.args {
arg_sym := c.table.get_type_symbol(arg.typ)
if arg_sym.kind == .placeholder {
c.error("type `$arg_sym.name` doesn't exist", it.pos)
}
}
}
ast.SumTypeDecl {
for typ in it.sub_types {
typ_sym := c.table.get_type_symbol(typ)
if typ_sym.kind == .placeholder {
c.error("type `$typ_sym.name` doesn't exist", it.pos)
}
}
}
}
}
pub fn (mut c Checker) struct_decl(decl ast.StructDecl) {
splitted_full_name := decl.name.split('.')
is_builtin := splitted_full_name[0] == 'builtin'
@ -1088,6 +1122,7 @@ fn (mut c Checker) stmt(node ast.Stmt) {
it.pos)
}
}
// ast.Attr {}
ast.AssignStmt {
c.assign_stmt(mut it)
}
@ -1099,7 +1134,6 @@ fn (mut c Checker) stmt(node ast.Stmt) {
c.error('$it.tok.lit statement not within a loop', it.tok.position())
}
}
// ast.Attr {}
ast.CompIf {
// c.expr(it.cond)
c.stmts(it.stmts)
@ -1170,17 +1204,6 @@ fn (mut c Checker) stmt(node ast.Stmt) {
}
c.returns = false
}
ast.ForStmt {
c.in_for_count++
typ := c.expr(it.cond)
if !it.is_inf && typ.idx() != table.bool_type_idx {
c.error('non-bool used as for condition', it.pos)
}
// TODO: update loop var type
// how does this work currenly?
c.stmts(it.stmts)
c.in_for_count--
}
ast.ForCStmt {
c.in_for_count++
c.stmt(it.init)
@ -1230,8 +1253,20 @@ fn (mut c Checker) stmt(node ast.Stmt) {
c.stmts(it.stmts)
c.in_for_count--
}
ast.ForStmt {
c.in_for_count++
typ := c.expr(it.cond)
if !it.is_inf && typ.idx() != table.bool_type_idx {
c.error('non-bool used as for condition', it.pos)
}
// TODO: update loop var type
// how does this work currenly?
c.stmts(it.stmts)
c.in_for_count--
}
// ast.GlobalDecl {}
ast.GoStmt {
if !is_call_expr(it.call_expr) {
if !(it.call_expr is ast.CallExpr) {
c.error('expression in `go` must be a function call', it.call_expr.position())
}
c.expr(it.call_expr)
@ -1242,7 +1277,6 @@ fn (mut c Checker) stmt(node ast.Stmt) {
c.mod = it.name
c.is_builtin_mod = it.name == 'builtin'
}
// ast.GlobalDecl {}
ast.Return {
c.returns = true
c.return_stmt(mut it)
@ -1250,6 +1284,9 @@ fn (mut c Checker) stmt(node ast.Stmt) {
ast.StructDecl {
c.struct_decl(it)
}
ast.TypeDecl {
c.type_decl(it)
}
ast.UnsafeStmt {
c.stmts(it.stmts)
}
@ -1260,13 +1297,6 @@ fn (mut c Checker) stmt(node ast.Stmt) {
}
}
fn is_call_expr(expr ast.Expr) bool {
return match expr {
ast.CallExpr { true }
else { false }
}
}
fn (mut c Checker) stmts(stmts []ast.Stmt) {
c.expected_type = table.void_type
for stmt in stmts {

View File

@ -0,0 +1,5 @@
vlib/v/checker/tests/inout/alias_type_exists.v:1:1: error: type `Bird` doesn't exist
1| type Pigeon = Bird
~~~~~~~~~~~
2|
3| fn main() {

View File

@ -0,0 +1,5 @@
type Pigeon = Bird
fn main() {
}

View File

@ -0,0 +1,12 @@
vlib/v/checker/tests/inout/fn_type_exists.v:1:1: error: type `Pants` doesn't exist
1| type PantsCreator = fn (a Shirt) Pants
~~~~~~~~~~~~~~~~~
2|
3| type PantsConsumer = fn (p Pants)
vlib/v/checker/tests/inout/fn_type_exists.v:3:1: error: type `Pants` doesn't exist
1| type PantsCreator = fn (a Shirt) Pants
2|
3| type PantsConsumer = fn (p Pants)
~~~~~~~~~~~~~~~~~~
4|
5| fn main() {

View File

@ -0,0 +1,7 @@
type PantsCreator = fn (a Shirt) Pants
type PantsConsumer = fn (p Pants)
fn main() {
}

View File

@ -0,0 +1,5 @@
vlib/v/checker/tests/inout/sum_type_exists.v:1:1: error: type `Nope` doesn't exist
1| type Miscellaneous = Nope | Inexistant | int
~~~~~~~~~~~~~~~~~~
2|
3| fn main() {

View File

@ -0,0 +1,5 @@
type Miscellaneous = Nope | Inexistant | int
fn main() {
}