mirror of
https://github.com/vlang/v.git
synced 2025-09-17 11:26:17 -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
|
is_deprecated bool
|
||||||
pub mut:
|
pub mut:
|
||||||
is_recursive bool
|
is_recursive bool
|
||||||
|
is_part_of_union bool
|
||||||
|
container_typ Type
|
||||||
default_expr Expr
|
default_expr Expr
|
||||||
default_expr_typ Type
|
default_expr_typ Type
|
||||||
name string
|
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 struct_sym, struct_typ_idx := c.table.find_sym_and_type_idx(node.name)
|
||||||
mut has_generic_types := false
|
mut has_generic_types := false
|
||||||
if mut struct_sym.info is ast.Struct {
|
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 {
|
if node.language == .v && !c.is_builtin_mod && !struct_sym.info.is_anon {
|
||||||
c.check_valid_pascal_case(node.name, 'struct name', node.pos)
|
c.check_valid_pascal_case(node.name, 'struct name', node.pos)
|
||||||
}
|
}
|
||||||
@ -844,13 +851,23 @@ or use an explicit `unsafe{ a[..] }`, if you do not want a copy of the slice.',
|
|||||||
node.pos)
|
node.pos)
|
||||||
}
|
}
|
||||||
if !node.has_update_expr && !field.has_default_expr && !field.typ.is_ptr()
|
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_ {
|
&& !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{
|
mut zero_struct_init := ast.StructInit{
|
||||||
pos: node.pos
|
pos: node.pos
|
||||||
typ: field.typ
|
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)
|
c.struct_init(mut zero_struct_init, true, mut inited_fields)
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
c.struct_init(mut zero_struct_init, true, mut inited_fields)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
for embed in info.embeds {
|
for embed in info.embeds {
|
||||||
mut zero_struct_init := ast.StructInit{
|
mut zero_struct_init := ast.StructInit{
|
||||||
|
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