Skip to content

Commit c69b125

Browse files
authored
markused: fix markused behavior on struct field's default expression (fix #23909) (#23933)
1 parent a22a3f7 commit c69b125

6 files changed

Lines changed: 53 additions & 3 deletions

File tree

‎vlib/v/ast/str.v‎

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,12 @@ pub fn (node &FnDecl) fkey() string {
5151
return node.name
5252
}
5353

54+
// sfkey returns a unique name of the struct field.
55+
// it is used in v.markused.
56+
pub fn (node &StructField) sfkey() string {
57+
return '${int(node.container_typ)}.${node.name}}'
58+
}
59+
5460
pub fn (node &Fn) fkey() string {
5561
if node.is_method {
5662
return '${int(node.receiver_type)}.${node.name}'

‎vlib/v/markused/markused.v‎

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import v.pref
88

99
// mark_used walks the AST, starting at main() and marks all used fns transitively
1010
pub fn mark_used(mut table ast.Table, mut pref_ pref.Preferences, ast_files []&ast.File) {
11-
mut all_fns, all_consts, all_globals := all_fn_const_and_global(ast_files)
11+
mut all_fns, all_consts, all_globals, all_fields := all_global_decl(ast_files)
1212
util.timing_start('MARKUSED')
1313
defer {
1414
util.timing_measure('MARKUSED')
@@ -464,11 +464,13 @@ pub fn mark_used(mut table ast.Table, mut pref_ pref.Preferences, ast_files []&a
464464
all_fns: all_fns
465465
all_consts: all_consts
466466
all_globals: all_globals
467+
all_fields: all_fields
467468
pref: pref_
468469
)
469470
walker.mark_markused_consts() // tagged with `@[markused]`
470471
walker.mark_markused_globals() // tagged with `@[markused]`
471472
walker.mark_markused_fns() // tagged with `@[markused]`, `@[export]` and veb actions
473+
walker.mark_struct_field_default_expr()
472474

473475
for k, _ in table.used_features.comptime_calls {
474476
walker.fn_by_name(k)
@@ -553,14 +555,15 @@ pub fn mark_used(mut table ast.Table, mut pref_ pref.Preferences, ast_files []&a
553555
}
554556
}
555557

556-
fn all_fn_const_and_global(ast_files []&ast.File) (map[string]ast.FnDecl, map[string]ast.ConstField, map[string]ast.GlobalField) {
558+
fn all_global_decl(ast_files []&ast.File) (map[string]ast.FnDecl, map[string]ast.ConstField, map[string]ast.GlobalField, map[string]ast.StructField) {
557559
util.timing_start(@METHOD)
558560
defer {
559561
util.timing_measure(@METHOD)
560562
}
561563
mut all_fns := map[string]ast.FnDecl{}
562564
mut all_consts := map[string]ast.ConstField{}
563565
mut all_globals := map[string]ast.GlobalField{}
566+
mut all_fields := map[string]ast.StructField{}
564567
for i in 0 .. ast_files.len {
565568
for node in ast_files[i].stmts {
566569
match node {
@@ -582,11 +585,17 @@ fn all_fn_const_and_global(ast_files []&ast.File) (map[string]ast.FnDecl, map[st
582585
all_globals[gkey] = gfield
583586
}
584587
}
588+
ast.StructDecl {
589+
for sfield in node.fields {
590+
sfkey := sfield.sfkey()
591+
all_fields[sfkey] = sfield
592+
}
593+
}
585594
else {}
586595
}
587596
}
588597
}
589-
return all_fns, all_consts, all_globals
598+
return all_fns, all_consts, all_globals, all_fields
590599
}
591600

592601
fn mark_all_methods_used(mut table ast.Table, mut all_fn_root_names []string, typ ast.Type) {

‎vlib/v/markused/walker.v‎

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,13 +15,15 @@ pub mut:
1515
used_consts map[string]bool // used_consts['os.args'] == true
1616
used_globals map[string]bool
1717
used_structs map[string]bool
18+
used_fields map[string]bool
1819
n_asserts int
1920
pref &pref.Preferences = unsafe { nil }
2021
mut:
2122
files []&ast.File
2223
all_fns map[string]ast.FnDecl
2324
all_consts map[string]ast.ConstField
2425
all_globals map[string]ast.GlobalField
26+
all_fields map[string]ast.StructField
2527
}
2628

2729
pub fn Walker.new(params Walker) &Walker {
@@ -90,6 +92,16 @@ pub fn (mut w Walker) mark_global_as_used(ckey string) {
9092
}
9193
}
9294

95+
pub fn (mut w Walker) mark_struct_field_default_expr_as_used(sfkey string) {
96+
if w.used_fields[sfkey] {
97+
return
98+
}
99+
w.used_fields[sfkey] = true
100+
sfield := w.all_fields[sfkey] or { return }
101+
102+
w.expr(sfield.default_expr)
103+
}
104+
93105
pub fn (mut w Walker) mark_markused_fns() {
94106
for _, mut func in w.all_fns {
95107
// @[export]
@@ -149,6 +161,14 @@ pub fn (mut w Walker) mark_markused_globals() {
149161
}
150162
}
151163

164+
pub fn (mut w Walker) mark_struct_field_default_expr() {
165+
for sfkey, mut structfield in w.all_fields {
166+
if structfield.has_default_expr {
167+
w.mark_struct_field_default_expr_as_used(sfkey)
168+
}
169+
}
170+
}
171+
152172
pub fn (mut w Walker) stmt(node_ ast.Stmt) {
153173
mut node := unsafe { node_ }
154174
match mut node {

‎vlib/v/tests/skip_unused/struct_field_default_expr.run.out‎

Whitespace-only changes.

‎vlib/v/tests/skip_unused/struct_field_default_expr.skip_unused.run.out‎

Whitespace-only changes.
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
module main
2+
3+
import flag
4+
5+
const c_default_port = u16(12345)
6+
7+
struct Options {
8+
headless bool
9+
port u16 = c_default_port @[short: p]
10+
}
11+
12+
fn main() {
13+
args := arguments()
14+
_, _ := flag.to_struct[Options](args, style: .v, skip: 1)!
15+
}

0 commit comments

Comments
 (0)