mirror of
https://github.com/vlang/v.git
synced 2025-09-11 08:25:42 -04:00
markused: improve the tracking of used closures (#25009)
This commit is contained in:
parent
ac00d441ad
commit
5ec3cc17e1
@ -605,6 +605,7 @@ fn (t Tree) fn_decl(node ast.FnDecl) &Node {
|
|||||||
obj.add_terse('is_unsafe', t.bool_node(node.is_unsafe))
|
obj.add_terse('is_unsafe', t.bool_node(node.is_unsafe))
|
||||||
obj.add_terse('is_markused', t.bool_node(node.is_markused))
|
obj.add_terse('is_markused', t.bool_node(node.is_markused))
|
||||||
obj.add_terse('is_file_translated', t.bool_node(node.is_file_translated))
|
obj.add_terse('is_file_translated', t.bool_node(node.is_file_translated))
|
||||||
|
obj.add_terse('is_closure', t.bool_node(node.is_closure))
|
||||||
obj.add_terse('receiver', t.struct_field(node.receiver))
|
obj.add_terse('receiver', t.struct_field(node.receiver))
|
||||||
obj.add('receiver_pos', t.pos(node.receiver_pos))
|
obj.add('receiver_pos', t.pos(node.receiver_pos))
|
||||||
obj.add_terse('is_method', t.bool_node(node.is_method))
|
obj.add_terse('is_method', t.bool_node(node.is_method))
|
||||||
|
@ -573,7 +573,7 @@ pub:
|
|||||||
pub struct AnonFn {
|
pub struct AnonFn {
|
||||||
pub mut:
|
pub mut:
|
||||||
decl FnDecl
|
decl FnDecl
|
||||||
inherited_vars []Param
|
inherited_vars []Param // note: closures have inherited_vars.len > 0
|
||||||
typ Type // the type of anonymous fn. Both .typ and .decl.name are auto generated
|
typ Type // the type of anonymous fn. Both .typ and .decl.name are auto generated
|
||||||
has_gen map[string]bool // a map of the names of all generic anon functions, generated from it
|
has_gen map[string]bool // a map of the names of all generic anon functions, generated from it
|
||||||
}
|
}
|
||||||
@ -602,6 +602,7 @@ pub:
|
|||||||
is_must_use bool // true, when @[must_use] is used on a fn. Calls to such functions, that ignore the return value, will cause warnings.
|
is_must_use bool // true, when @[must_use] is used on a fn. Calls to such functions, that ignore the return value, will cause warnings.
|
||||||
is_markused bool // true, when an explicit `@[markused]` tag was put on a fn; `-skip-unused` will not remove that fn
|
is_markused bool // true, when an explicit `@[markused]` tag was put on a fn; `-skip-unused` will not remove that fn
|
||||||
is_file_translated bool // true, when the file it resides in is `@[translated]`
|
is_file_translated bool // true, when the file it resides in is `@[translated]`
|
||||||
|
is_closure bool // true, for actual closures like `fn [inherited] () {}` . It is false for normal anonymous functions, and for named functions/methods too.
|
||||||
receiver StructField // TODO: this is not a struct field
|
receiver StructField // TODO: this is not a struct field
|
||||||
receiver_pos token.Pos // `(u User)` in `fn (u User) name()` position
|
receiver_pos token.Pos // `(u User)` in `fn (u User) name()` position
|
||||||
is_method bool
|
is_method bool
|
||||||
|
@ -35,6 +35,7 @@ pub mut:
|
|||||||
used_veb_types []Type // veb context types, filled in by checker
|
used_veb_types []Type // veb context types, filled in by checker
|
||||||
used_maps int // how many times maps were used, filled in by markused
|
used_maps int // how many times maps were used, filled in by markused
|
||||||
used_none int // how many times `none` was used, filled in by markused
|
used_none int // how many times `none` was used, filled in by markused
|
||||||
|
used_closures int // number of used closures, either directly with `fn [state] () {}`, or indirectly (though `instance.method` promotions)
|
||||||
// json bool // json is imported
|
// json bool // json is imported
|
||||||
comptime_calls map[string]bool // resolved name to call on comptime
|
comptime_calls map[string]bool // resolved name to call on comptime
|
||||||
comptime_syms map[Type]bool // resolved syms (generic)
|
comptime_syms map[Type]bool // resolved syms (generic)
|
||||||
|
@ -363,13 +363,15 @@ pub fn mark_used(mut table ast.Table, mut pref_ pref.Preferences, ast_files []&a
|
|||||||
table.used_features.used_consts = walker.used_consts.move()
|
table.used_features.used_consts = walker.used_consts.move()
|
||||||
table.used_features.used_globals = walker.used_globals.move()
|
table.used_features.used_globals = walker.used_globals.move()
|
||||||
table.used_features.used_syms = walker.used_syms.move()
|
table.used_features.used_syms = walker.used_syms.move()
|
||||||
|
table.used_features.used_closures = walker.used_closures
|
||||||
|
|
||||||
if trace_skip_unused {
|
if trace_skip_unused {
|
||||||
eprintln('>> t.used_fns: ${table.used_features.used_fns.keys()}')
|
eprintln('>> t.used_fns: ${table.used_features.used_fns.keys()}')
|
||||||
eprintln('>> t.used_consts: ${table.used_features.used_consts.keys()}')
|
eprintln('>> t.used_consts: ${table.used_features.used_consts.keys()}')
|
||||||
eprintln('>> t.used_globals: ${table.used_features.used_globals.keys()}')
|
eprintln('>> t.used_globals: ${table.used_features.used_globals.keys()}')
|
||||||
eprintln('>> t.used_syms: ${table.used_features.used_syms.keys()}')
|
eprintln('>> t.used_syms: ${table.used_features.used_syms.keys()}')
|
||||||
eprintln('>> walker.table.used_features.used_maps: ${walker.table.used_features.used_maps}')
|
eprintln('>> t.used_maps: ${table.used_features.used_maps}')
|
||||||
|
eprintln('>> t.used_closures: ${table.used_features.used_closures}')
|
||||||
}
|
}
|
||||||
if trace_skip_unused_just_unused_fns {
|
if trace_skip_unused_just_unused_fns {
|
||||||
all_fns_keys := all_fns.keys()
|
all_fns_keys := all_fns.keys()
|
||||||
|
@ -21,6 +21,7 @@ pub mut:
|
|||||||
used_option int // _option_ok
|
used_option int // _option_ok
|
||||||
used_result int // _result_ok
|
used_result int // _result_ok
|
||||||
used_panic int // option/result propagation
|
used_panic int // option/result propagation
|
||||||
|
used_closures int // fn [x] (){}, and `instance.method` used in an expression
|
||||||
pref &pref.Preferences = unsafe { nil }
|
pref &pref.Preferences = unsafe { nil }
|
||||||
mut:
|
mut:
|
||||||
all_fns map[string]ast.FnDecl
|
all_fns map[string]ast.FnDecl
|
||||||
@ -712,6 +713,9 @@ fn (mut w Walker) expr(node_ ast.Expr) {
|
|||||||
}
|
}
|
||||||
w.mark_by_type(node.typ)
|
w.mark_by_type(node.typ)
|
||||||
w.or_block(node.or_block)
|
w.or_block(node.or_block)
|
||||||
|
if node.has_hidden_receiver {
|
||||||
|
w.used_closures++
|
||||||
|
}
|
||||||
}
|
}
|
||||||
ast.SqlExpr {
|
ast.SqlExpr {
|
||||||
w.expr(node.db_expr)
|
w.expr(node.db_expr)
|
||||||
@ -811,9 +815,6 @@ pub fn (mut w Walker) fn_decl(mut node ast.FnDecl) {
|
|||||||
if w.used_fns[fkey] {
|
if w.used_fns[fkey] {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if node.no_body {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if w.trace_enabled {
|
if w.trace_enabled {
|
||||||
w.level++
|
w.level++
|
||||||
defer { w.level-- }
|
defer { w.level-- }
|
||||||
@ -824,6 +825,12 @@ pub fn (mut w Walker) fn_decl(mut node ast.FnDecl) {
|
|||||||
}
|
}
|
||||||
eprintln('>>>${' '.repeat(w.level)}${receiver_name}${node.name} [decl]')
|
eprintln('>>>${' '.repeat(w.level)}${receiver_name}${node.name} [decl]')
|
||||||
}
|
}
|
||||||
|
if node.is_closure {
|
||||||
|
w.used_closures++
|
||||||
|
}
|
||||||
|
if node.no_body {
|
||||||
|
return
|
||||||
|
}
|
||||||
if node.is_method {
|
if node.is_method {
|
||||||
w.mark_by_type(node.receiver.typ)
|
w.mark_by_type(node.receiver.typ)
|
||||||
}
|
}
|
||||||
|
@ -914,6 +914,7 @@ fn (mut p Parser) anon_fn() ast.AnonFn {
|
|||||||
return_type_pos: return_type_pos
|
return_type_pos: return_type_pos
|
||||||
params: params
|
params: params
|
||||||
is_variadic: is_variadic
|
is_variadic: is_variadic
|
||||||
|
is_closure: inherited_vars.len > 0
|
||||||
is_method: false
|
is_method: false
|
||||||
generic_names: generic_names
|
generic_names: generic_names
|
||||||
is_anon: true
|
is_anon: true
|
||||||
|
Loading…
x
Reference in New Issue
Block a user