checker: detect unknown type to iterate with $for (#8971)

pull/8980/head
Nick Treleaven 2021-02-26 06:28:19 +00:00 committed by GitHub
parent 3a082621c9
commit 59d4d0ef1d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 31 additions and 2 deletions

View File

@ -723,6 +723,7 @@ pub:
stmts []Stmt stmts []Stmt
kind CompForKind kind CompForKind
pos token.Position pos token.Position
typ_pos token.Position
pub mut: pub mut:
// expr Expr // expr Expr
typ table.Type typ table.Type

View File

@ -3109,7 +3109,12 @@ fn (mut c Checker) stmt(node ast.Stmt) {
c.branch_stmt(node) c.branch_stmt(node)
} }
ast.CompFor { ast.CompFor {
// node.typ = c.expr(node.expr) if node.typ > table.void_type {
sym := c.table.get_type_symbol(node.typ)
if sym.kind == .placeholder {
c.error('unknown type `$sym.name`', node.typ_pos)
}
}
c.stmts(node.stmts) c.stmts(node.stmts)
} }
ast.ConstDecl { ast.ConstDecl {

View File

@ -0,0 +1,12 @@
vlib/v/checker/tests/comptime_for.vv:2:12: error: unknown type `Huh`
1 | fn unknown() {
2 | $for m in Huh.methods {}
| ~~~
3 | $for f in Huh.fields {}
4 | }
vlib/v/checker/tests/comptime_for.vv:3:12: error: unknown type `Huh`
1 | fn unknown() {
2 | $for m in Huh.methods {}
3 | $for f in Huh.fields {}
| ~~~
4 | }

View File

@ -0,0 +1,4 @@
fn unknown() {
$for m in Huh.methods {}
$for f in Huh.fields {}
}

View File

@ -217,10 +217,13 @@ fn (mut p Parser) comp_for() ast.CompFor {
// $for field in App(fields) { // $for field in App(fields) {
p.next() p.next()
p.check(.key_for) p.check(.key_for)
var_pos := p.tok.position()
val_var := p.check_name() val_var := p.check_name()
p.check(.key_in) p.check(.key_in)
mut typ_pos := p.tok.position()
lang := p.parse_language() lang := p.parse_language()
typ := p.parse_any_type(lang, false, false) typ := p.parse_any_type(lang, false, false)
typ_pos = typ_pos.extend(p.prev_tok.position())
p.check(.dot) p.check(.dot)
for_val := p.check_name() for_val := p.check_name()
mut kind := ast.CompForKind.methods mut kind := ast.CompForKind.methods
@ -228,15 +231,18 @@ fn (mut p Parser) comp_for() ast.CompFor {
p.scope.register(ast.Var{ p.scope.register(ast.Var{
name: val_var name: val_var
typ: p.table.find_type_idx('FunctionData') typ: p.table.find_type_idx('FunctionData')
pos: var_pos
}) })
} else if for_val == 'fields' { } else if for_val == 'fields' {
p.scope.register(ast.Var{ p.scope.register(ast.Var{
name: val_var name: val_var
typ: p.table.find_type_idx('FieldData') typ: p.table.find_type_idx('FieldData')
pos: var_pos
}) })
kind = .fields kind = .fields
} else { } else {
p.error('unknown kind `$for_val`, available are: `methods` or `fields`') p.error_with_pos('unknown kind `$for_val`, available are: `methods` or `fields`',
p.prev_tok.position())
return ast.CompFor{} return ast.CompFor{}
} }
spos := p.tok.position() spos := p.tok.position()
@ -246,6 +252,7 @@ fn (mut p Parser) comp_for() ast.CompFor {
stmts: stmts stmts: stmts
kind: kind kind: kind
typ: typ typ: typ
typ_pos: typ_pos
pos: spos.extend(p.tok.position()) pos: spos.extend(p.tok.position())
} }
} }