Skip to content

Commit 7d32715

Browse files
authored
parser: fix comptime for lock shared field (fix #26143) (#26146)
1 parent 20ba1aa commit 7d32715

File tree

4 files changed

+26
-60
lines changed

4 files changed

+26
-60
lines changed

vlib/v/ast/ast.v

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2516,6 +2516,7 @@ pub fn (e &Expr) is_lockable() bool {
25162516
return match e {
25172517
Ident { true }
25182518
SelectorExpr { e.expr.is_lockable() }
2519+
ComptimeSelector { true }
25192520
else { false }
25202521
}
25212522
}

vlib/v/parser/lock.v

Lines changed: 4 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -1,64 +1,7 @@
11
module parser
22

3-
import v.token
43
import v.ast
54

6-
// parse `x` or `x.y.z` - no index, no struct literals (`{` starts lock block)
7-
fn (mut p Parser) lockable() ast.Expr {
8-
mut names := []string{}
9-
mut positions := []token.Pos{}
10-
mut pos := p.tok.pos()
11-
for {
12-
if p.tok.kind != .name {
13-
p.unexpected(got: '`${p.tok.lit}`', expecting: 'field or variable name')
14-
}
15-
names << p.tok.lit
16-
positions << pos
17-
p.next()
18-
if p.tok.kind != .dot {
19-
break
20-
}
21-
p.next()
22-
pos.extend(p.tok.pos())
23-
}
24-
mut expr := ast.Expr(ast.Ident{
25-
language: ast.Language.v
26-
pos: positions[0]
27-
mod: p.mod
28-
name: names[0]
29-
is_mut: true
30-
info: ast.IdentVar{}
31-
scope: p.scope
32-
})
33-
for i := 1; i < names.len; i++ {
34-
expr = ast.SelectorExpr{
35-
expr: expr
36-
field_name: names[i]
37-
next_token: if i < names.len - 1 { token.Kind.dot } else { p.tok.kind }
38-
is_mut: true
39-
pos: positions[i]
40-
scope: p.scope
41-
}
42-
}
43-
return expr
44-
}
45-
46-
// like `expr_list()` but only lockables are allowed, `{` starts lock block (not struct literal)
47-
fn (mut p Parser) lockable_list() []ast.Expr {
48-
mut exprs := []ast.Expr{}
49-
for {
50-
expr := p.lockable()
51-
if expr !is ast.Comment {
52-
exprs << expr
53-
if p.tok.kind != .comma {
54-
break
55-
}
56-
p.next()
57-
}
58-
}
59-
return exprs
60-
}
61-
625
fn (mut p Parser) lock_expr() ast.LockExpr {
636
// TODO: Handle aliasing sync
647
p.register_auto_import('sync')
@@ -79,10 +22,12 @@ fn (mut p Parser) lock_expr() ast.LockExpr {
7922
break
8023
}
8124
if p.tok.kind == .name {
82-
exprs := p.lockable_list()
25+
p.inside_lock_exprs = true
26+
exprs := p.expr_list(true)
27+
p.inside_lock_exprs = false
8328
for e in exprs {
8429
if !e.is_lockable() {
85-
p.error_with_pos('`${e}` cannot be locked - only `x` or `x.y` are supported',
30+
p.error_with_pos('`${e}` cannot be locked - only `x`, `x.y` or `x.$(y)` are supported',
8631
e.pos())
8732
}
8833
lockeds << e

vlib/v/parser/parser.v

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,7 @@ mut:
7373
inside_orm bool
7474
inside_chan_decl bool
7575
inside_attr_decl bool
76+
inside_lock_exprs bool
7677
array_dim int // array dim parsing level
7778
fixed_array_dim int // fixed array dim parsing level
7879
or_is_handled bool // ignore `or` in this expression
@@ -1789,7 +1790,7 @@ fn (mut p Parser) name_expr() ast.Expr {
17891790
} else if !known_var && (p.peek_tok.kind == .lcbr || is_generic_struct_init)
17901791
&& (!p.inside_match || (p.inside_select && prev_tok_kind == .arrow && lit0_is_capital))
17911792
&& !p.inside_match_case && (!p.inside_if || p.inside_select)
1792-
&& (!p.inside_for || p.inside_select) {
1793+
&& (!p.inside_for || p.inside_select) && !p.inside_lock_exprs {
17931794
alias_array_type := p.alias_array_type()
17941795
if alias_array_type != ast.void_type {
17951796
return p.array_init(is_option, alias_array_type)
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
struct MyS {
2+
a int
3+
cache shared map[u64]string
4+
}
5+
6+
fn encode[T](val T) string {
7+
$for field in T.fields {
8+
$if field.is_shared {
9+
rlock val.$(field.name) {
10+
return field.name
11+
}
12+
}
13+
}
14+
return ''
15+
}
16+
17+
fn test_comptime_for_lock_field() {
18+
assert encode(MyS{}) == 'cache'
19+
}

0 commit comments

Comments
 (0)