markused: fix markused behavior on struct field's default expression (fix #23909) (#23933)

This commit is contained in:
ChAoS_UnItY (Kyle Lin) 2025-03-15 13:35:34 +08:00 committed by GitHub
parent a22a3f7760
commit c69b125162
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 53 additions and 3 deletions

View File

@ -51,6 +51,12 @@ pub fn (node &FnDecl) fkey() string {
return node.name
}
// sfkey returns a unique name of the struct field.
// it is used in v.markused.
pub fn (node &StructField) sfkey() string {
return '${int(node.container_typ)}.${node.name}}'
}
pub fn (node &Fn) fkey() string {
if node.is_method {
return '${int(node.receiver_type)}.${node.name}'

View File

@ -8,7 +8,7 @@ import v.pref
// mark_used walks the AST, starting at main() and marks all used fns transitively
pub fn mark_used(mut table ast.Table, mut pref_ pref.Preferences, ast_files []&ast.File) {
mut all_fns, all_consts, all_globals := all_fn_const_and_global(ast_files)
mut all_fns, all_consts, all_globals, all_fields := all_global_decl(ast_files)
util.timing_start('MARKUSED')
defer {
util.timing_measure('MARKUSED')
@ -464,11 +464,13 @@ pub fn mark_used(mut table ast.Table, mut pref_ pref.Preferences, ast_files []&a
all_fns: all_fns
all_consts: all_consts
all_globals: all_globals
all_fields: all_fields
pref: pref_
)
walker.mark_markused_consts() // tagged with `@[markused]`
walker.mark_markused_globals() // tagged with `@[markused]`
walker.mark_markused_fns() // tagged with `@[markused]`, `@[export]` and veb actions
walker.mark_struct_field_default_expr()
for k, _ in table.used_features.comptime_calls {
walker.fn_by_name(k)
@ -553,7 +555,7 @@ pub fn mark_used(mut table ast.Table, mut pref_ pref.Preferences, ast_files []&a
}
}
fn all_fn_const_and_global(ast_files []&ast.File) (map[string]ast.FnDecl, map[string]ast.ConstField, map[string]ast.GlobalField) {
fn all_global_decl(ast_files []&ast.File) (map[string]ast.FnDecl, map[string]ast.ConstField, map[string]ast.GlobalField, map[string]ast.StructField) {
util.timing_start(@METHOD)
defer {
util.timing_measure(@METHOD)
@ -561,6 +563,7 @@ fn all_fn_const_and_global(ast_files []&ast.File) (map[string]ast.FnDecl, map[st
mut all_fns := map[string]ast.FnDecl{}
mut all_consts := map[string]ast.ConstField{}
mut all_globals := map[string]ast.GlobalField{}
mut all_fields := map[string]ast.StructField{}
for i in 0 .. ast_files.len {
for node in ast_files[i].stmts {
match node {
@ -582,11 +585,17 @@ fn all_fn_const_and_global(ast_files []&ast.File) (map[string]ast.FnDecl, map[st
all_globals[gkey] = gfield
}
}
ast.StructDecl {
for sfield in node.fields {
sfkey := sfield.sfkey()
all_fields[sfkey] = sfield
}
}
else {}
}
}
}
return all_fns, all_consts, all_globals
return all_fns, all_consts, all_globals, all_fields
}
fn mark_all_methods_used(mut table ast.Table, mut all_fn_root_names []string, typ ast.Type) {

View File

@ -15,6 +15,7 @@ pub mut:
used_consts map[string]bool // used_consts['os.args'] == true
used_globals map[string]bool
used_structs map[string]bool
used_fields map[string]bool
n_asserts int
pref &pref.Preferences = unsafe { nil }
mut:
@ -22,6 +23,7 @@ mut:
all_fns map[string]ast.FnDecl
all_consts map[string]ast.ConstField
all_globals map[string]ast.GlobalField
all_fields map[string]ast.StructField
}
pub fn Walker.new(params Walker) &Walker {
@ -90,6 +92,16 @@ pub fn (mut w Walker) mark_global_as_used(ckey string) {
}
}
pub fn (mut w Walker) mark_struct_field_default_expr_as_used(sfkey string) {
if w.used_fields[sfkey] {
return
}
w.used_fields[sfkey] = true
sfield := w.all_fields[sfkey] or { return }
w.expr(sfield.default_expr)
}
pub fn (mut w Walker) mark_markused_fns() {
for _, mut func in w.all_fns {
// @[export]
@ -149,6 +161,14 @@ pub fn (mut w Walker) mark_markused_globals() {
}
}
pub fn (mut w Walker) mark_struct_field_default_expr() {
for sfkey, mut structfield in w.all_fields {
if structfield.has_default_expr {
w.mark_struct_field_default_expr_as_used(sfkey)
}
}
}
pub fn (mut w Walker) stmt(node_ ast.Stmt) {
mut node := unsafe { node_ }
match mut node {

View File

@ -0,0 +1,15 @@
module main
import flag
const c_default_port = u16(12345)
struct Options {
headless bool
port u16 = c_default_port @[short: p]
}
fn main() {
args := arguments()
_, _ := flag.to_struct[Options](args, style: .v, skip: 1)!
}