Skip to content

Commit

Permalink
checker: fix missing struct field type checking for type mismatch (re…
Browse files Browse the repository at this point in the history
…f vs non-ref in `mt sync.Mutex = sync.new_mutex()`) (fix #18088) (#21949)
  • Loading branch information
felipensp authored Jul 29, 2024
1 parent 6f20516 commit 5d31e77
Show file tree
Hide file tree
Showing 3 changed files with 61 additions and 3 deletions.
17 changes: 14 additions & 3 deletions vlib/v/checker/struct.v
Original file line number Diff line number Diff line change
Expand Up @@ -111,9 +111,20 @@ fn (mut c Checker) struct_decl(mut node ast.StructDecl) {
if field.has_default_expr {
c.expected_type = field.typ
field.default_expr_typ = c.expr(mut field.default_expr)
if field.typ.is_ptr() && !field.default_expr_typ.is_ptr()
&& field.default_expr is ast.StructInit {
c.error('reference field must be initialized with reference', field.default_expr.pos())
if field.typ.is_ptr() != field.default_expr_typ.is_ptr() {
match field.default_expr {
ast.CallExpr {
err_desc := if field.typ.is_ptr() { 'is' } else { 'is not' }
val_desc := if field.default_expr_typ.is_ptr() { 'is' } else { 'is not' }
c.error('field ${err_desc} reference but default value ${val_desc} reference',
field.default_expr.pos())
}
ast.StructInit {
c.error('reference field must be initialized with reference',
field.default_expr.pos())
}
else {}
}
}

// disallow map `mut a = b`
Expand Down
7 changes: 7 additions & 0 deletions vlib/v/checker/tests/struct_field_mismatch_ref_err.out
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
vlib/v/checker/tests/struct_field_mismatch_ref_err.vv:6:26: error: field is not reference but default value is reference
4 | struct SafeCounter {
5 | mut:
6 | mt sync.Mutex = sync.new_mutex()
| ~~~~~~~~~~~
7 | pub mut:
8 | value map[string]int
40 changes: 40 additions & 0 deletions vlib/v/checker/tests/struct_field_mismatch_ref_err.vv
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import sync
import time

struct SafeCounter {
mut:
mt sync.Mutex = sync.new_mutex()
pub mut:
value map[string]int
}

fn (mut c SafeCounter) inc(key string) {
c.mt.@lock()
defer {
c.mt.unlock()
}
c.value[key]++
}

fn (mut c SafeCounter) value(key string) int {
c.mt.@lock()
defer {
c.mt.unlock()
}
return c.value[key]
}

fn main() {
mut counter := &SafeCounter{}

for i := 0; i < 5; i++ {
spawn fn [mut counter] () {
for j := 0; j < 100; j++ {
counter.inc('key')
}
}()
}

time.sleep(1 * time.second)
println(counter.value('key'))
}

0 comments on commit 5d31e77

Please sign in to comment.