checker: detect unknown type to iterate with $for (#8971)
parent
3a082621c9
commit
59d4d0ef1d
|
@ -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
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
|
@ -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 | }
|
|
@ -0,0 +1,4 @@
|
||||||
|
fn unknown() {
|
||||||
|
$for m in Huh.methods {}
|
||||||
|
$for f in Huh.fields {}
|
||||||
|
}
|
|
@ -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())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue