Skip to content

Commit

Permalink
checker: fix missing check for struct initialization with @[noinit]
Browse files Browse the repository at this point in the history
… attribute, through using `T{}` (#20516)
  • Loading branch information
felipensp committed Jan 13, 2024
1 parent 35e91a7 commit ea6a5d8
Show file tree
Hide file tree
Showing 6 changed files with 28 additions and 3 deletions.
2 changes: 1 addition & 1 deletion vlib/v/checker/fn.v
Expand Up @@ -99,7 +99,7 @@ fn (mut c Checker) fn_decl(mut node ast.FnDecl) {
if node.language == .v && node.attrs.len > 0 {
if attr_export := node.attrs.find_first('export') {
if attr_export.arg == '' {
c.error('missing argument for [export] attribute', attr_export.pos)
c.error('missing argument for @[export] attribute', attr_export.pos)
}
}
}
Expand Down
6 changes: 5 additions & 1 deletion vlib/v/checker/struct.v
Expand Up @@ -475,7 +475,7 @@ fn (mut c Checker) struct_init(mut node ast.StructInit, is_field_zero_struct_ini
if type_sym.kind == .struct_ {
info := type_sym.info as ast.Struct
if info.attrs.len > 0 && info.attrs.contains('noinit') && type_sym.mod != c.mod {
c.error('struct `${type_sym.name}` is declared with a `[noinit]` attribute, so ' +
c.error('struct `${type_sym.name}` is declared with a `@[noinit]` attribute, so ' +
'it cannot be initialized with `${type_sym.name}{}`', node.pos)
}
}
Expand All @@ -498,6 +498,10 @@ fn (mut c Checker) struct_init(mut node ast.StructInit, is_field_zero_struct_ini
sym := c.table.sym(c.unwrap_generic(node.typ))
if sym.kind == .struct_ {
info := sym.info as ast.Struct
if info.attrs.len > 0 && info.attrs.contains('noinit') && sym.mod != c.mod {
c.error('struct `${sym.name}` is declared with a `@[noinit]` attribute, so ' +
'it cannot be initialized with `${sym.name}{}`', node.pos)
}
if node.no_keys && node.init_fields.len != info.fields.len {
fname := if info.fields.len != 1 { 'fields' } else { 'field' }
c.error('initializing struct `${sym.name}` needs `${info.fields.len}` ${fname}, but got `${node.init_fields.len}`',
Expand Down
2 changes: 1 addition & 1 deletion vlib/v/checker/tests/missing_export_attr_arg_err.out
@@ -1,4 +1,4 @@
vlib/v/checker/tests/missing_export_attr_arg_err.vv:1:1: error: missing argument for [export] attribute
vlib/v/checker/tests/missing_export_attr_arg_err.vv:1:1: error: missing argument for @[export] attribute
1 | @[export]
| ~~~~~~~~~
2 | fn foo() string{
Expand Down
6 changes: 6 additions & 0 deletions vlib/v/checker/tests/modules/module_struct_noinit.out
@@ -0,0 +1,6 @@
vlib/v/checker/tests/modules/module_struct_noinit/src/main.v:9:9: error: struct `mod.Foo` is declared with a `@[noinit]` attribute, so it cannot be initialized with `mod.Foo{}`
7 |
8 | fn default_value[T]() T {
9 | return T{}
| ~~~
10 | }
10 changes: 10 additions & 0 deletions vlib/v/checker/tests/modules/module_struct_noinit/src/main.v
@@ -0,0 +1,10 @@
import mod

fn main() {
dump(default_value[mod.Foo]())
println(default_value[mod.Foo]())
}

fn default_value[T]() T {
return T{}
}
5 changes: 5 additions & 0 deletions vlib/v/checker/tests/modules/module_struct_noinit/src/mod.v
@@ -0,0 +1,5 @@
module mod

@[noinit]
pub struct Foo {
}

0 comments on commit ea6a5d8

Please sign in to comment.