mirror of
https://github.com/vlang/v.git
synced 2023-08-10 21:13:21 +03:00
checker: disallow Bar{...foo}
when Bar needs more fields, than what foo
has (#16609)
This commit is contained in:
parent
458e68e196
commit
2261606b56
@ -4003,6 +4003,22 @@ fn (mut c Checker) error(message string, pos token.Pos) {
|
||||
c.warn_or_error(msg, pos, false)
|
||||
}
|
||||
|
||||
fn (c &Checker) check_struct_signature_init_fields(from ast.Struct, to ast.Struct, node ast.StructInit) bool {
|
||||
if node.fields.len == 0 {
|
||||
return from.fields.len == to.fields.len
|
||||
}
|
||||
|
||||
mut count_not_in_from := 0
|
||||
for field in node.fields {
|
||||
filtered := from.fields.filter(it.name == field.name)
|
||||
if filtered.len != 1 {
|
||||
count_not_in_from++
|
||||
}
|
||||
}
|
||||
|
||||
return (from.fields.len + count_not_in_from) == to.fields.len
|
||||
}
|
||||
|
||||
// check `to` has all fields of `from`
|
||||
fn (c &Checker) check_struct_signature(from ast.Struct, to ast.Struct) bool {
|
||||
// Note: `to` can have extra fields
|
||||
|
@ -603,7 +603,8 @@ fn (mut c Checker) struct_init(mut node ast.StructInit) ast.Type {
|
||||
from_info := from_sym.info as ast.Struct
|
||||
to_info := to_sym.info as ast.Struct
|
||||
// TODO this check is too strict
|
||||
if !c.check_struct_signature(from_info, to_info) {
|
||||
if !c.check_struct_signature(from_info, to_info)
|
||||
|| !c.check_struct_signature_init_fields(from_info, to_info, node) {
|
||||
c.error('struct `${from_sym.name}` is not compatible with struct `${to_sym.name}`',
|
||||
node.update_expr.pos())
|
||||
}
|
||||
|
14
vlib/v/checker/tests/check_incompatible_struct.out
Normal file
14
vlib/v/checker/tests/check_incompatible_struct.out
Normal file
@ -0,0 +1,14 @@
|
||||
vlib/v/checker/tests/check_incompatible_struct.vv:17:6: error: struct `Foo` is not compatible with struct `Bar`
|
||||
15 | }
|
||||
16 | bar3 := Bar{
|
||||
17 | ...foo
|
||||
| ~~~
|
||||
18 | b: 1
|
||||
19 | }
|
||||
vlib/v/checker/tests/check_incompatible_struct.vv:26:6: error: struct `Foo` is not compatible with struct `Bar`
|
||||
24 | }
|
||||
25 | bar := Bar{
|
||||
26 | ...foo
|
||||
| ~~~
|
||||
27 | }
|
||||
28 | print(bar)
|
32
vlib/v/checker/tests/check_incompatible_struct.vv
Normal file
32
vlib/v/checker/tests/check_incompatible_struct.vv
Normal file
@ -0,0 +1,32 @@
|
||||
struct Foo {
|
||||
b int
|
||||
}
|
||||
|
||||
struct Bar {
|
||||
a int
|
||||
b int
|
||||
}
|
||||
|
||||
fn main() {
|
||||
foo := Foo{2}
|
||||
bar2 := Bar{
|
||||
...foo
|
||||
a: 1
|
||||
}
|
||||
bar3 := Bar{
|
||||
...foo
|
||||
b: 1
|
||||
}
|
||||
bar4 := Bar{
|
||||
...foo
|
||||
b: 1
|
||||
a: 2
|
||||
}
|
||||
bar := Bar{
|
||||
...foo
|
||||
}
|
||||
print(bar)
|
||||
print(bar2)
|
||||
print(bar3)
|
||||
print(bar4)
|
||||
}
|
Loading…
Reference in New Issue
Block a user