checker: check types with $for/$if introspection (#8984)
parent
1a8ff9d7dd
commit
4ad95cfeaf
|
@ -3109,11 +3109,10 @@ fn (mut c Checker) stmt(node ast.Stmt) {
|
||||||
c.branch_stmt(node)
|
c.branch_stmt(node)
|
||||||
}
|
}
|
||||||
ast.CompFor {
|
ast.CompFor {
|
||||||
if node.typ > table.void_type {
|
typ := c.unwrap_generic(node.typ)
|
||||||
sym := c.table.get_type_symbol(node.typ)
|
sym := c.table.get_type_symbol(typ)
|
||||||
if sym.kind == .placeholder {
|
if sym.kind == .placeholder || typ.has_flag(.generic) {
|
||||||
c.error('unknown type `$sym.name`', node.typ_pos)
|
c.error('unknown type `$sym.name`', node.typ_pos)
|
||||||
}
|
|
||||||
}
|
}
|
||||||
c.stmts(node.stmts)
|
c.stmts(node.stmts)
|
||||||
}
|
}
|
||||||
|
@ -4806,7 +4805,11 @@ pub fn (mut c Checker) if_expr(mut node ast.IfExpr) table.Type {
|
||||||
if branch.cond is ast.InfixExpr {
|
if branch.cond is ast.InfixExpr {
|
||||||
if branch.cond.op == .key_is {
|
if branch.cond.op == .key_is {
|
||||||
left := branch.cond.left
|
left := branch.cond.left
|
||||||
got_type := (branch.cond.right as ast.Type).typ
|
got_type := c.unwrap_generic((branch.cond.right as ast.Type).typ)
|
||||||
|
sym := c.table.get_type_symbol(got_type)
|
||||||
|
if sym.kind == .placeholder || got_type.has_flag(.generic) {
|
||||||
|
c.error('unknown type `$sym.name`', branch.cond.right.position())
|
||||||
|
}
|
||||||
if left is ast.SelectorExpr {
|
if left is ast.SelectorExpr {
|
||||||
comptime_field_name = left.expr.str()
|
comptime_field_name = left.expr.str()
|
||||||
c.comptime_fields_type[comptime_field_name] = got_type
|
c.comptime_fields_type[comptime_field_name] = got_type
|
||||||
|
|
|
@ -12,7 +12,7 @@ vlib/v/checker/tests/comptime_field_selector_not_name_err.vv:12:12: error: unkno
|
||||||
| ~~
|
| ~~
|
||||||
13 | }
|
13 | }
|
||||||
14 | }
|
14 | }
|
||||||
vlib/v/checker/tests/comptime_field_selector_not_name_err.vv:15:10: error: compile time field access can only be used when iterating over `T.fields`
|
vlib/v/checker/tests/comptime_field_selector_not_name_err.vv:15:10: error: undefined ident: `f`
|
||||||
13 | }
|
13 | }
|
||||||
14 | }
|
14 | }
|
||||||
15 | _ = t.$(f.name)
|
15 | _ = t.$(f.name)
|
||||||
|
|
|
@ -3,10 +3,53 @@ vlib/v/checker/tests/comptime_for.vv:2:12: error: unknown type `Huh`
|
||||||
2 | $for m in Huh.methods {}
|
2 | $for m in Huh.methods {}
|
||||||
| ~~~
|
| ~~~
|
||||||
3 | $for f in Huh.fields {}
|
3 | $for f in Huh.fields {}
|
||||||
4 | }
|
4 | $for f in T.fields {
|
||||||
vlib/v/checker/tests/comptime_for.vv:3:12: error: unknown type `Huh`
|
vlib/v/checker/tests/comptime_for.vv:3:12: error: unknown type `Huh`
|
||||||
1 | fn unknown() {
|
1 | fn unknown() {
|
||||||
2 | $for m in Huh.methods {}
|
2 | $for m in Huh.methods {}
|
||||||
3 | $for f in Huh.fields {}
|
3 | $for f in Huh.fields {}
|
||||||
| ~~~
|
| ~~~
|
||||||
4 | }
|
4 | $for f in T.fields {
|
||||||
|
5 | $if f.typ is Huh {}
|
||||||
|
vlib/v/checker/tests/comptime_for.vv:4:12: error: unknown type `T`
|
||||||
|
2 | $for m in Huh.methods {}
|
||||||
|
3 | $for f in Huh.fields {}
|
||||||
|
4 | $for f in T.fields {
|
||||||
|
| ^
|
||||||
|
5 | $if f.typ is Huh {}
|
||||||
|
6 | $if f.typ is T {}
|
||||||
|
vlib/v/checker/tests/comptime_for.vv:5:16: error: unknown type `Huh`
|
||||||
|
3 | $for f in Huh.fields {}
|
||||||
|
4 | $for f in T.fields {
|
||||||
|
5 | $if f.typ is Huh {}
|
||||||
|
| ~~~
|
||||||
|
6 | $if f.typ is T {}
|
||||||
|
7 | }
|
||||||
|
vlib/v/checker/tests/comptime_for.vv:6:16: error: unknown type `T`
|
||||||
|
4 | $for f in T.fields {
|
||||||
|
5 | $if f.typ is Huh {}
|
||||||
|
6 | $if f.typ is T {}
|
||||||
|
| ^
|
||||||
|
7 | }
|
||||||
|
8 | _ = m
|
||||||
|
vlib/v/checker/tests/comptime_for.vv:8:6: error: undefined ident: `m`
|
||||||
|
6 | $if f.typ is T {}
|
||||||
|
7 | }
|
||||||
|
8 | _ = m
|
||||||
|
| ^
|
||||||
|
9 | }
|
||||||
|
10 |
|
||||||
|
vlib/v/checker/tests/comptime_for.vv:14:16: error: unknown type `U`
|
||||||
|
12 | $for f in T.fields {
|
||||||
|
13 | $if f.typ is T {}
|
||||||
|
14 | $if f.typ is U {}
|
||||||
|
| ^
|
||||||
|
15 | }
|
||||||
|
16 | _ = f
|
||||||
|
vlib/v/checker/tests/comptime_for.vv:16:6: error: undefined ident: `f`
|
||||||
|
14 | $if f.typ is U {}
|
||||||
|
15 | }
|
||||||
|
16 | _ = f
|
||||||
|
| ^
|
||||||
|
17 | }
|
||||||
|
18 |
|
||||||
|
|
|
@ -1,4 +1,23 @@
|
||||||
fn unknown() {
|
fn unknown() {
|
||||||
$for m in Huh.methods {}
|
$for m in Huh.methods {}
|
||||||
$for f in Huh.fields {}
|
$for f in Huh.fields {}
|
||||||
|
$for f in T.fields {
|
||||||
|
$if f.typ is Huh {}
|
||||||
|
$if f.typ is T {}
|
||||||
|
}
|
||||||
|
_ = m
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn gf<T>() {
|
||||||
|
$for f in T.fields {
|
||||||
|
$if f.typ is T {}
|
||||||
|
$if f.typ is U {}
|
||||||
|
}
|
||||||
|
_ = f
|
||||||
|
}
|
||||||
|
|
||||||
|
struct S1 {
|
||||||
|
i int
|
||||||
|
}
|
||||||
|
|
||||||
|
gf<S1>()
|
||||||
|
|
|
@ -227,6 +227,7 @@ fn (mut p Parser) comp_for() ast.CompFor {
|
||||||
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
|
||||||
|
p.open_scope()
|
||||||
if for_val == 'methods' {
|
if for_val == 'methods' {
|
||||||
p.scope.register(ast.Var{
|
p.scope.register(ast.Var{
|
||||||
name: val_var
|
name: val_var
|
||||||
|
@ -247,6 +248,7 @@ fn (mut p Parser) comp_for() ast.CompFor {
|
||||||
}
|
}
|
||||||
spos := p.tok.position()
|
spos := p.tok.position()
|
||||||
stmts := p.parse_block()
|
stmts := p.parse_block()
|
||||||
|
p.close_scope()
|
||||||
return ast.CompFor{
|
return ast.CompFor{
|
||||||
val_var: val_var
|
val_var: val_var
|
||||||
stmts: stmts
|
stmts: stmts
|
||||||
|
|
Loading…
Reference in New Issue