mirror of
https://github.com/vlang/v.git
synced 2025-09-16 02:49:31 -04:00
checker: fix checking of default field initialisations, that are part of unions of structs tagged with @[noinit]
(#21587)
This commit is contained in:
parent
80397e679e
commit
09eaae5f7a
@ -341,6 +341,8 @@ pub:
|
||||
is_deprecated bool
|
||||
pub mut:
|
||||
is_recursive bool
|
||||
is_part_of_union bool
|
||||
container_typ Type
|
||||
default_expr Expr
|
||||
default_expr_typ Type
|
||||
name string
|
||||
|
@ -14,6 +14,13 @@ fn (mut c Checker) struct_decl(mut node ast.StructDecl) {
|
||||
mut struct_sym, struct_typ_idx := c.table.find_sym_and_type_idx(node.name)
|
||||
mut has_generic_types := false
|
||||
if mut struct_sym.info is ast.Struct {
|
||||
for mut symfield in struct_sym.info.fields {
|
||||
symfield.container_typ = struct_typ_idx
|
||||
if struct_sym.info.is_union {
|
||||
symfield.is_part_of_union = true
|
||||
}
|
||||
}
|
||||
|
||||
if node.language == .v && !c.is_builtin_mod && !struct_sym.info.is_anon {
|
||||
c.check_valid_pascal_case(node.name, 'struct name', node.pos)
|
||||
}
|
||||
@ -844,12 +851,22 @@ or use an explicit `unsafe{ a[..] }`, if you do not want a copy of the slice.',
|
||||
node.pos)
|
||||
}
|
||||
if !node.has_update_expr && !field.has_default_expr && !field.typ.is_ptr()
|
||||
&& !field.typ.has_flag(.option) && c.table.final_sym(field.typ).kind == .struct_ {
|
||||
mut zero_struct_init := ast.StructInit{
|
||||
pos: node.pos
|
||||
typ: field.typ
|
||||
&& !field.typ.has_flag(.option) {
|
||||
field_final_sym := c.table.final_sym(field.typ)
|
||||
if field_final_sym.kind == .struct_ {
|
||||
mut zero_struct_init := ast.StructInit{
|
||||
pos: node.pos
|
||||
typ: field.typ
|
||||
}
|
||||
if field.is_part_of_union {
|
||||
if field.name in inited_fields {
|
||||
// fields that are part of an union, should only be checked, when they are explicitly initialised
|
||||
c.struct_init(mut zero_struct_init, true, mut inited_fields)
|
||||
}
|
||||
} else {
|
||||
c.struct_init(mut zero_struct_init, true, mut inited_fields)
|
||||
}
|
||||
}
|
||||
c.struct_init(mut zero_struct_init, true, mut inited_fields)
|
||||
}
|
||||
}
|
||||
for embed in info.embeds {
|
||||
|
22
vlib/v/tests/modules/structs_with_noinit/shapes.v
Normal file
22
vlib/v/tests/modules/structs_with_noinit/shapes.v
Normal file
@ -0,0 +1,22 @@
|
||||
module structs_with_noinit
|
||||
|
||||
@[noinit]
|
||||
pub struct Image {}
|
||||
|
||||
@[noinit]
|
||||
pub struct Rect {}
|
||||
|
||||
@[noinit]
|
||||
pub struct Circle {}
|
||||
|
||||
pub fn make_circle() Circle {
|
||||
return Circle{}
|
||||
}
|
||||
|
||||
pub fn make_image() Image {
|
||||
return Image{}
|
||||
}
|
||||
|
||||
pub fn make_rect() Rect {
|
||||
return Rect{}
|
||||
}
|
@ -0,0 +1,44 @@
|
||||
module main
|
||||
|
||||
import structs_with_noinit
|
||||
|
||||
enum RenderableKind {
|
||||
circle
|
||||
image
|
||||
rect
|
||||
}
|
||||
|
||||
union RenderableValue {
|
||||
circle structs_with_noinit.Circle
|
||||
image structs_with_noinit.Image
|
||||
rect structs_with_noinit.Rect
|
||||
}
|
||||
|
||||
struct Renderable {
|
||||
RenderableValue
|
||||
kind RenderableKind
|
||||
}
|
||||
|
||||
fn draw(r Renderable) int {
|
||||
match r.kind {
|
||||
.circle {
|
||||
println('()')
|
||||
return 999
|
||||
}
|
||||
.rect {
|
||||
println('[]')
|
||||
}
|
||||
.image {
|
||||
println('o_O')
|
||||
}
|
||||
}
|
||||
return 1
|
||||
}
|
||||
|
||||
fn test_initialisation_of_a_struct_containing_embedded_union_field() {
|
||||
r := Renderable{
|
||||
kind: .circle
|
||||
circle: structs_with_noinit.make_circle()
|
||||
}
|
||||
assert draw(r) == 999
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user