mirror of
https://github.com/vlang/v.git
synced 2023-08-10 21:13:21 +03:00
This commit is contained in:
parent
0992914bd6
commit
289f8f2f24
@ -482,12 +482,23 @@ pub fn (mut c Checker) struct_init(mut node ast.StructInit) ast.Type {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Check uninitialized refs/sum types
|
// Check uninitialized refs/sum types
|
||||||
for i, field in info.fields {
|
// The variable `fields` contains two parts, the first part is the same as info.fields,
|
||||||
|
// and the second part is all fields embedded in the structure
|
||||||
|
// If the return value data composition form in `c.table.struct_fields()` is modified,
|
||||||
|
// need to modify here accordingly.
|
||||||
|
fields := c.table.struct_fields(type_sym)
|
||||||
|
mut checked_structs := []ast.Type{}
|
||||||
|
for i, field in fields {
|
||||||
if field.name in inited_fields {
|
if field.name in inited_fields {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
sym := c.table.sym(field.typ)
|
||||||
|
if field.name.len > 0 && field.name[0].is_capital() && sym.info is ast.Struct
|
||||||
|
&& sym.language == .v {
|
||||||
|
continue
|
||||||
|
}
|
||||||
if field.has_default_expr {
|
if field.has_default_expr {
|
||||||
if field.default_expr_typ == 0 {
|
if i < info.fields.len && field.default_expr_typ == 0 {
|
||||||
if field.default_expr is ast.StructInit {
|
if field.default_expr is ast.StructInit {
|
||||||
idx := c.table.find_type_idx(field.default_expr.typ_str)
|
idx := c.table.find_type_idx(field.default_expr.typ_str)
|
||||||
if idx != 0 {
|
if idx != 0 {
|
||||||
@ -503,11 +514,15 @@ pub fn (mut c Checker) struct_init(mut node ast.StructInit) ast.Type {
|
|||||||
}
|
}
|
||||||
if field.typ.is_ptr() && !field.typ.has_flag(.shared_f) && !node.has_update_expr
|
if field.typ.is_ptr() && !field.typ.has_flag(.shared_f) && !node.has_update_expr
|
||||||
&& !c.pref.translated && !c.file.is_translated {
|
&& !c.pref.translated && !c.file.is_translated {
|
||||||
c.error('reference field `${type_sym.name}.$field.name` must be initialized',
|
c.warn('reference field `${type_sym.name}.$field.name` must be initialized',
|
||||||
node.pos)
|
node.pos)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if sym.kind == .struct_ && !(sym.info as ast.Struct).is_typedef {
|
||||||
|
c.check_ref_fields_initialized(sym, mut checked_structs, '${type_sym.name}.$field.name',
|
||||||
|
node)
|
||||||
}
|
}
|
||||||
// Do not allow empty uninitialized interfaces
|
// Do not allow empty uninitialized interfaces
|
||||||
sym := c.table.sym(field.typ)
|
|
||||||
mut has_noinit := false
|
mut has_noinit := false
|
||||||
for attr in field.attrs {
|
for attr in field.attrs {
|
||||||
if attr.name == 'noinit' {
|
if attr.name == 'noinit' {
|
||||||
@ -542,13 +557,6 @@ pub fn (mut c Checker) struct_init(mut node ast.StructInit) ast.Type {
|
|||||||
node.pos)
|
node.pos)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Check for struct type
|
|
||||||
if sym.kind == .struct_ && !(sym.info as ast.Struct).is_typedef {
|
|
||||||
mut checked_structs := []ast.Type{}
|
|
||||||
checked_structs << field.typ
|
|
||||||
c.check_ref_fields_initialized(sym.info as ast.Struct, mut checked_structs,
|
|
||||||
'${node.typ_str}.$field.name', node)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {}
|
else {}
|
||||||
@ -575,24 +583,29 @@ pub fn (mut c Checker) struct_init(mut node ast.StructInit) ast.Type {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Recursively check whether the struct type field is initialized
|
// Recursively check whether the struct type field is initialized
|
||||||
fn (mut c Checker) check_ref_fields_initialized(struct_ &ast.Struct, mut checked_structs []ast.Type, linked_name string, node &ast.StructInit) {
|
fn (mut c Checker) check_ref_fields_initialized(struct_sym &ast.TypeSymbol, mut checked_structs []ast.Type, linked_name string, node &ast.StructInit) {
|
||||||
if c.pref.translated || c.file.is_translated {
|
if c.pref.translated || c.file.is_translated {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
for field in struct_.fields {
|
fields := c.table.struct_fields(struct_sym)
|
||||||
|
for field in fields {
|
||||||
|
sym := c.table.sym(field.typ)
|
||||||
|
if field.name.len > 0 && field.name[0].is_capital() && sym.info is ast.Struct
|
||||||
|
&& sym.language == .v {
|
||||||
|
continue
|
||||||
|
}
|
||||||
if field.typ.is_ptr() && !field.typ.has_flag(.shared_f) && !field.has_default_expr {
|
if field.typ.is_ptr() && !field.typ.has_flag(.shared_f) && !field.has_default_expr {
|
||||||
c.warn('reference field `${linked_name}.$field.name` must be initialized',
|
c.warn('reference field `${linked_name}.$field.name` must be initialized',
|
||||||
node.pos)
|
node.pos)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
sym := c.table.sym(field.typ)
|
|
||||||
if sym.kind == .struct_ {
|
if sym.kind == .struct_ {
|
||||||
info := sym.info as ast.Struct
|
info := sym.info as ast.Struct
|
||||||
if info.is_typedef || field.typ in checked_structs {
|
if info.is_typedef || field.typ in checked_structs {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
checked_structs << field.typ
|
checked_structs << field.typ
|
||||||
c.check_ref_fields_initialized(info, mut checked_structs, '${linked_name}.$field.name',
|
c.check_ref_fields_initialized(sym, mut checked_structs, '${linked_name}.$field.name',
|
||||||
node)
|
node)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,11 +1,4 @@
|
|||||||
vlib/v/checker/tests/reference_field_must_be_initialized.vv:8:7: warning: reference field `Node.next.next` must be initialized
|
vlib/v/checker/tests/reference_field_must_be_initialized.vv:8:7: warning: reference field `Node.next` must be initialized
|
||||||
6 |
|
|
||||||
7 | fn main(){
|
|
||||||
8 | n := Node{ data: 123 }
|
|
||||||
| ~~~~~~~~~~~~~~~~~
|
|
||||||
9 | eprintln('n.data: $n.data')
|
|
||||||
10 | }
|
|
||||||
vlib/v/checker/tests/reference_field_must_be_initialized.vv:8:7: error: reference field `Node.next` must be initialized
|
|
||||||
6 |
|
6 |
|
||||||
7 | fn main(){
|
7 | fn main(){
|
||||||
8 | n := Node{ data: 123 }
|
8 | n := Node{ data: 123 }
|
||||||
|
@ -1,7 +1,13 @@
|
|||||||
vlib/v/checker/tests/struct_ref_fields_uninitialized_err.vv:11:7: warning: reference field `Outer.c.b` must be initialized
|
vlib/v/checker/tests/struct_ref_fields_uninitialized_err.vv:22:7: warning: reference field `Outer.c.b` must be initialized
|
||||||
9 |
|
20 |
|
||||||
10 | fn main() {
|
21 | fn main() {
|
||||||
11 | o := Outer{}
|
22 | _ := Outer{}
|
||||||
| ~~~~~~~
|
| ~~~~~~~
|
||||||
12 | dump(o)
|
23 | _ := Struct{}
|
||||||
13 | }
|
24 | }
|
||||||
|
vlib/v/checker/tests/struct_ref_fields_uninitialized_err.vv:23:7: warning: reference field `Struct.ref2` must be initialized
|
||||||
|
21 | fn main() {
|
||||||
|
22 | _ := Outer{}
|
||||||
|
23 | _ := Struct{}
|
||||||
|
| ~~~~~~~~
|
||||||
|
24 | }
|
||||||
|
@ -7,7 +7,18 @@ struct Outer {
|
|||||||
c ContainsRef
|
c ContainsRef
|
||||||
}
|
}
|
||||||
|
|
||||||
fn main() {
|
struct Ref {}
|
||||||
o := Outer{}
|
|
||||||
dump(o)
|
struct EmbedStruct {
|
||||||
|
ref1 &Ref = unsafe { nil }
|
||||||
|
ref2 &Ref
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Struct {
|
||||||
|
EmbedStruct
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
_ := Outer{}
|
||||||
|
_ := Struct{}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user