markused: fix interface fields and chan usage (fix #24961) (#24962)

This commit is contained in:
Felipe Pena 2025-07-24 12:25:41 -03:00 committed by GitHub
parent 05479f3bd9
commit a309593f56
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 63 additions and 14 deletions

View File

@ -1185,6 +1185,9 @@ pub fn (mut g Gen) write_typeof_functions() {
if inter_info.is_generic {
continue
}
if g.pref.skip_unused && sym.idx !in g.table.used_features.used_syms {
continue
}
g.definitions.writeln('${g.static_non_parallel}char * v_typeof_interface_${sym.cname}(int sidx);')
if g.pref.parallel_cc {
g.extern_out.writeln('extern char * v_typeof_interface_${sym.cname}(int sidx);')
@ -1620,6 +1623,13 @@ fn (mut g Gen) write_chan_pop_option_fns() {
if opt_el_type in done {
continue
}
if g.pref.skip_unused {
if sym := g.table.find_sym(opt_el_type) {
if sym.idx !in g.table.used_features.used_syms {
continue
}
}
}
done << opt_el_type
g.channel_definitions.writeln('
static inline ${opt_el_type} __Option_${styp}_popval(${styp} ch) {
@ -1642,6 +1652,13 @@ fn (mut g Gen) write_chan_push_option_fns() {
if styp in done {
continue
}
if g.pref.skip_unused {
if sym := g.table.find_sym(el_type) {
if sym.idx !in g.table.used_features.used_syms {
continue
}
}
}
done << styp
g.register_option(ast.void_type.set_flag(.option))
g.channel_definitions.writeln('
@ -1744,10 +1761,14 @@ pub fn (mut g Gen) write_typedef_types() {
}
.chan {
if sym.name != 'chan' {
g.type_definitions.writeln('typedef chan ${sym.cname};')
chan_inf := sym.chan_info()
chan_elem_type := chan_inf.elem_type
is_fixed_arr := g.table.sym(chan_elem_type).kind == .array_fixed
esym := g.table.sym(chan_elem_type)
if g.pref.skip_unused && esym.idx !in g.table.used_features.used_syms {
continue
}
g.type_definitions.writeln('typedef chan ${sym.cname};')
is_fixed_arr := esym.kind == .array_fixed
if !chan_elem_type.has_flag(.generic) {
el_stype := if is_fixed_arr { '_v_' } else { '' } + g.styp(chan_elem_type)
val_arg_pop := if is_fixed_arr { '&val.ret_arr' } else { '&val' }
@ -1798,6 +1819,9 @@ static inline void __${sym.cname}_pushval(${sym.cname} ch, ${push_arg} val) {
}
}
for sym in interface_non_generic_syms {
if g.pref.skip_unused && sym.idx !in g.table.used_features.used_syms {
continue
}
g.write_interface_typesymbol_declaration(sym)
}
}
@ -6444,7 +6468,8 @@ fn (mut g Gen) write_debug_calls_typeof_functions() {
continue
}
inter_info := sym.info as ast.Interface
if inter_info.is_generic {
if inter_info.is_generic
|| (g.pref.skip_unused && sym.idx !in g.table.used_features.used_syms) {
continue
}
g.writeln('\tv_typeof_interface_${sym.cname}(0);')
@ -6646,6 +6671,9 @@ fn (mut g Gen) write_builtin_types() {
// everything except builtin will get sorted
for builtin_name in ast.builtins {
sym := g.table.sym_by_idx(g.table.type_idxs[builtin_name])
if g.pref.skip_unused && sym.idx !in g.table.used_features.used_syms {
continue
}
if sym.info is ast.Interface {
g.write_interface_typedef(sym)
if !sym.info.is_generic {
@ -7802,6 +7830,9 @@ fn (mut g Gen) interface_table() string {
if inter_info.is_generic {
continue
}
if g.pref.skip_unused && isym.idx !in g.table.used_features.used_syms {
continue
}
// interface_name is for example Speaker
interface_name := isym.cname
// generate a struct that references interface methods

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_fields, all_decltypes := all_global_decl(ast_files)
mut all_fns, all_consts, all_globals, all_fields, all_decltypes, all_structs := all_global_decl(ast_files)
util.timing_start('MARKUSED')
defer {
util.timing_measure('MARKUSED')
@ -447,6 +447,7 @@ pub fn mark_used(mut table ast.Table, mut pref_ pref.Preferences, ast_files []&a
all_globals: all_globals
all_fields: all_fields
all_decltypes: all_decltypes
all_structs: all_structs
pref: pref_
)
walker.mark_markused_consts() // tagged with `@[markused]`
@ -586,7 +587,7 @@ pub fn mark_used(mut table ast.Table, mut pref_ pref.Preferences, ast_files []&a
}
}
fn all_global_decl(ast_files []&ast.File) (map[string]ast.FnDecl, map[string]ast.ConstField, map[string]ast.GlobalField, map[string]ast.StructField, map[string]ast.Type) {
fn all_global_decl(ast_files []&ast.File) (map[string]ast.FnDecl, map[string]ast.ConstField, map[string]ast.GlobalField, map[string]ast.StructField, map[string]ast.Type, map[string]ast.StructDecl) {
util.timing_start(@METHOD)
defer {
util.timing_measure(@METHOD)
@ -596,6 +597,7 @@ fn all_global_decl(ast_files []&ast.File) (map[string]ast.FnDecl, map[string]ast
mut all_globals := map[string]ast.GlobalField{}
mut all_fields := map[string]ast.StructField{}
mut all_decltypes := map[string]ast.Type{}
mut all_structs := map[string]ast.StructDecl{}
for i in 0 .. ast_files.len {
for node in ast_files[i].stmts {
match node {
@ -622,6 +624,7 @@ fn all_global_decl(ast_files []&ast.File) (map[string]ast.FnDecl, map[string]ast
sfkey := sfield.sfkey()
all_fields[sfkey] = sfield
}
all_structs[node.name] = node
}
ast.TypeDecl {
all_decltypes[node.name] = node.typ
@ -630,7 +633,7 @@ fn all_global_decl(ast_files []&ast.File) (map[string]ast.FnDecl, map[string]ast
}
}
}
return all_fns, all_consts, all_globals, all_fields, all_decltypes
return all_fns, all_consts, all_globals, all_fields, all_decltypes, all_structs
}
fn mark_all_methods_used(mut table ast.Table, mut all_fn_root_names []string, typ ast.Type) {

View File

@ -30,6 +30,7 @@ mut:
all_globals map[string]ast.GlobalField
all_fields map[string]ast.StructField
all_decltypes map[string]ast.Type
all_structs map[string]ast.StructDecl
}
pub fn Walker.new(params Walker) &Walker {
@ -301,6 +302,9 @@ pub fn (mut w Walker) stmt(node_ ast.Stmt) {
}
}
ast.StructDecl {
for typ in node.implements_types {
w.mark_by_type(typ.typ)
}
w.struct_fields(node.fields)
}
ast.DeferStmt {
@ -921,8 +925,7 @@ pub fn (mut w Walker) mark_by_type(typ ast.Type) {
if typ.has_flag(.generic) {
return
}
sym := w.table.sym(typ)
w.mark_by_sym(sym)
w.mark_by_sym(w.table.sym(typ))
}
pub fn (mut w Walker) mark_by_sym(isym ast.TypeSymbol) {
@ -945,24 +948,28 @@ pub fn (mut w Walker) mark_by_sym(isym ast.TypeSymbol) {
}
}
match fsym.info {
ast.Struct, ast.SumType, ast.FnType, ast.Alias, ast.Chan {
w.mark_by_sym(fsym)
}
ast.Array, ast.ArrayFixed {
w.features.used_arrays++
w.mark_by_type(ifield.typ)
w.mark_by_sym(fsym)
}
ast.Map {
w.features.used_maps++
w.mark_by_type(ifield.typ)
w.mark_by_sym(fsym)
}
else {
w.mark_by_sym(fsym)
}
else {}
}
}
}
for embed in isym.info.embeds {
w.mark_by_type(embed)
}
if decl := w.all_structs[isym.name] {
for iface_typ in decl.implements_types {
w.mark_by_type(iface_typ.typ)
}
}
}
ast.ArrayFixed, ast.Array {
w.mark_by_type(isym.info.elem_type)
@ -1024,6 +1031,9 @@ pub fn (mut w Walker) mark_by_sym(isym ast.TypeSymbol) {
if isym.info.parent_type != 0 {
w.mark_by_type(isym.info.parent_type)
}
for field in isym.info.fields {
w.mark_by_type(field.typ)
}
for method in isym.methods {
if method.receiver_type != 0 {
w.mark_by_type(method.receiver_type)

View File

@ -0,0 +1,5 @@
struct Foo {}
interface Bar {
a Foo
}