mirror of
https://github.com/vlang/v.git
synced 2023-08-10 21:13:21 +03:00
checker: disallow struct{...val.$(field.name)}
(#16852)
This commit is contained in:
parent
2e54a8cb0e
commit
09766c44b6
@ -459,6 +459,7 @@ pub mut:
|
||||
typ Type // the type of this struct
|
||||
update_expr Expr // `a` in `...a`
|
||||
update_expr_type Type
|
||||
update_expr_pos token.Pos
|
||||
update_expr_comments []Comment
|
||||
is_update_embed bool
|
||||
has_update_expr bool // has `...a`
|
||||
|
@ -334,8 +334,9 @@ fn (mut c Checker) struct_init(mut node ast.StructInit) ast.Type {
|
||||
}
|
||||
}
|
||||
// allow init structs from generic if they're private except the type is from builtin module
|
||||
if !type_sym.is_pub && type_sym.kind != .placeholder && type_sym.language != .c
|
||||
&& (type_sym.mod != c.mod && !(node.typ.has_flag(.generic) && type_sym.mod != 'builtin')) {
|
||||
if !node.has_update_expr && !type_sym.is_pub && type_sym.kind != .placeholder
|
||||
&& type_sym.language != .c && (type_sym.mod != c.mod && !(node.typ.has_flag(.generic)
|
||||
&& type_sym.mod != 'builtin')) {
|
||||
c.error('type `${type_sym.name}` is private', node.pos)
|
||||
}
|
||||
if type_sym.kind == .struct_ {
|
||||
@ -591,6 +592,9 @@ fn (mut c Checker) struct_init(mut node ast.StructInit) ast.Type {
|
||||
if node.has_update_expr {
|
||||
update_type := c.expr(node.update_expr)
|
||||
node.update_expr_type = update_type
|
||||
if node.update_expr is ast.ComptimeSelector {
|
||||
c.error('cannot use struct update syntax in compile time expressions', node.update_expr_pos)
|
||||
}
|
||||
if c.table.final_sym(update_type).kind != .struct_ {
|
||||
s := c.table.type_to_str(update_type)
|
||||
c.error('expected struct, found `${s}`', node.update_expr.pos())
|
||||
|
7
vlib/v/checker/tests/struct_update_comptime_err.out
Normal file
7
vlib/v/checker/tests/struct_update_comptime_err.out
Normal file
@ -0,0 +1,7 @@
|
||||
vlib/v/checker/tests/struct_update_comptime_err.vv:18:4: error: cannot use struct update syntax in compile time expressions
|
||||
16 | $for field in U.fields {
|
||||
17 | _ = struct {
|
||||
18 | ...val.$(field.name)
|
||||
| ~~~
|
||||
19 | }
|
||||
20 | }
|
32
vlib/v/checker/tests/struct_update_comptime_err.vv
Normal file
32
vlib/v/checker/tests/struct_update_comptime_err.vv
Normal file
@ -0,0 +1,32 @@
|
||||
struct Aa {
|
||||
sub Bb
|
||||
}
|
||||
|
||||
struct AaWithAliasType {
|
||||
sub Bb
|
||||
}
|
||||
|
||||
type AliasType = Bb
|
||||
|
||||
struct Bb {
|
||||
a int
|
||||
}
|
||||
|
||||
fn encode_struct[U](val U) {
|
||||
$for field in U.fields {
|
||||
_ = struct {
|
||||
...val.$(field.name)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
aa := Aa{}
|
||||
bb := Bb{}
|
||||
aa_with_alias_type := AaWithAliasType{}
|
||||
|
||||
encode_struct(aa)
|
||||
encode_struct(aa_with_alias_type)
|
||||
|
||||
encode_struct(bb)
|
||||
}
|
@ -408,6 +408,7 @@ fn (mut p Parser) struct_init(typ_str string, kind ast.StructInitKind) ast.Struc
|
||||
mut update_expr := ast.empty_expr
|
||||
mut update_expr_comments := []ast.Comment{}
|
||||
mut has_update_expr := false
|
||||
mut update_expr_pos := token.Pos{}
|
||||
for p.tok.kind !in [.rcbr, .rpar, .eof] {
|
||||
mut field_name := ''
|
||||
mut expr := ast.empty_expr
|
||||
@ -424,6 +425,7 @@ fn (mut p Parser) struct_init(typ_str string, kind ast.StructInitKind) ast.Struc
|
||||
comments = p.eat_comments(same_line: true)
|
||||
} else if is_update_expr {
|
||||
// struct updating syntax; f2 := Foo{ ...f, name: 'f2' }
|
||||
update_expr_pos = p.tok.pos()
|
||||
p.check(.ellipsis)
|
||||
update_expr = p.expr(0)
|
||||
update_expr_comments << p.eat_comments(same_line: true)
|
||||
@ -475,6 +477,7 @@ fn (mut p Parser) struct_init(typ_str string, kind ast.StructInitKind) ast.Struc
|
||||
typ: typ
|
||||
fields: fields
|
||||
update_expr: update_expr
|
||||
update_expr_pos: update_expr_pos
|
||||
update_expr_comments: update_expr_comments
|
||||
has_update_expr: has_update_expr
|
||||
name_pos: first_pos
|
||||
|
Loading…
Reference in New Issue
Block a user