From 0d8cc4588f449a86418558b7cb9031298fc73892 Mon Sep 17 00:00:00 2001 From: Felipe Pena Date: Tue, 15 Jul 2025 12:37:48 -0300 Subject: [PATCH] markused: remove `@[markused]` from option and result fns (#24900) --- vlib/builtin/option.v | 3 -- vlib/builtin/result.v | 1 - vlib/v/ast/table.v | 64 +++++++++++++++++----------------- vlib/v/checker/checker.v | 4 --- vlib/v/checker/fn.v | 2 -- vlib/v/checker/postfix.v | 4 +-- vlib/v/checker/used_features.v | 14 ++++---- vlib/v/markused/markused.v | 20 ++++++++--- vlib/v/markused/walker.v | 30 +++++++++++++++- 9 files changed, 83 insertions(+), 59 deletions(-) diff --git a/vlib/builtin/option.v b/vlib/builtin/option.v index c11b4a4c6a..53611ed2ff 100644 --- a/vlib/builtin/option.v +++ b/vlib/builtin/option.v @@ -21,7 +21,6 @@ struct _option { // derived _option_xxx types } -@[markused] fn _option_none(data voidptr, mut option _option, size int) { unsafe { *option = _option{ @@ -32,7 +31,6 @@ fn _option_none(data voidptr, mut option _option, size int) { } } -@[markused] fn _option_ok(data voidptr, mut option _option, size int) { unsafe { *option = _option{} @@ -41,7 +39,6 @@ fn _option_ok(data voidptr, mut option _option, size int) { } } -@[markused] fn _option_clone(current &_option, mut option _option, size int) { unsafe { *option = _option{ diff --git a/vlib/builtin/result.v b/vlib/builtin/result.v index 5f5897427b..dcc06555dd 100644 --- a/vlib/builtin/result.v +++ b/vlib/builtin/result.v @@ -17,7 +17,6 @@ struct _result { // derived Result_xxx types } -@[markused] fn _result_ok(data voidptr, mut res _result, size int) { unsafe { *res = _result{} diff --git a/vlib/v/ast/table.v b/vlib/v/ast/table.v index dfd2486a35..2f65751732 100644 --- a/vlib/v/ast/table.v +++ b/vlib/v/ast/table.v @@ -10,38 +10,38 @@ import v.util @[heap; minify] pub struct UsedFeatures { pub mut: - dump bool // dump() - index bool // string[0] - range_index bool // string[0..1] - cast_ptr bool // &u8(...) - asserts bool // assert expr - as_cast bool // expr as Type - anon_fn bool // fn () { } - auto_str bool // auto str fns - auto_str_ptr bool // auto str fns for ptr type - arr_prepend bool // arr.prepend() - arr_insert bool // arr.insert() - arr_first bool // arr.first() - arr_last bool // arr.last() - arr_pop bool // arr.pop() - arr_delete bool // arr.delete() - arr_reverse bool // arr.reverse() - arr_init bool // [1, 2, 3] - arr_map bool // []map[key]value - type_name bool // var.type_name() - map_update bool // {...foo} - interpolation bool // '${foo} ${bar}' - option_or_result bool // has panic call - waiter bool // has thread waiter - print_types map[int]bool // print() idx types - used_fns map[string]bool // filled in by markused - used_consts map[string]bool // filled in by markused - used_globals map[string]bool // filled in by markused - 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_arrays int // how many times arrays were used, filled in by markused - used_none int // how many times `none` was used, filled in by markused - external_types bool // true, when external type is used + dump bool // dump() + index bool // string[0] + range_index bool // string[0..1] + cast_ptr bool // &u8(...) + asserts bool // assert expr + as_cast bool // expr as Type + anon_fn bool // fn () { } + auto_str bool // auto str fns + auto_str_ptr bool // auto str fns for ptr type + arr_prepend bool // arr.prepend() + arr_insert bool // arr.insert() + arr_first bool // arr.first() + arr_last bool // arr.last() + arr_pop bool // arr.pop() + arr_delete bool // arr.delete() + arr_reverse bool // arr.reverse() + arr_init bool // [1, 2, 3] + arr_map bool // []map[key]value + type_name bool // var.type_name() + map_update bool // {...foo} + interpolation bool // '${foo} ${bar}' + print_options bool // print option type + waiter bool // has thread waiter + print_types map[int]bool // print() idx types + used_fns map[string]bool // filled in by markused + used_consts map[string]bool // filled in by markused + used_globals map[string]bool // filled in by markused + 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_arrays int // how many times arrays were used, filled in by markused + used_none int // how many times `none` was used, filled in by markused + external_types bool // true, when external type is used // json bool // json is imported debugger bool // debugger is used comptime_calls map[string]bool // resolved name to call on comptime diff --git a/vlib/v/checker/checker.v b/vlib/v/checker/checker.v index 59a7d6d26f..38b98839c6 100644 --- a/vlib/v/checker/checker.v +++ b/vlib/v/checker/checker.v @@ -1420,8 +1420,6 @@ fn (mut c Checker) check_expr_option_or_result_call(expr ast.Expr, ret_type ast. } fn (mut c Checker) check_or_expr(node ast.OrExpr, ret_type ast.Type, expr_return_type ast.Type, expr ast.Expr) { - c.markused_option_or_result(!c.is_builtin_mod && node.kind != .absent && c.mod != 'strings') - if node.kind == .propagate_option { if c.table.cur_fn != unsafe { nil } && !c.table.cur_fn.return_type.has_flag(.option) && !c.table.cur_fn.is_main && !c.table.cur_fn.is_test && !c.inside_const { @@ -1823,8 +1821,6 @@ fn (mut c Checker) selector_expr(mut node ast.SelectorExpr) ast.Type { c.check_or_expr(node.or_block, unwrapped_typ, c.expected_or_type, node) c.expected_or_type = ast.void_type } - c.markused_option_or_result(node.or_block.kind != .absent - && !c.table.used_features.option_or_result) return field.typ } if mut method := c.table.sym(c.unwrap_generic(typ)).find_method_with_generic_parent(field_name) { diff --git a/vlib/v/checker/fn.v b/vlib/v/checker/fn.v index 4b1d761844..2d802104a7 100644 --- a/vlib/v/checker/fn.v +++ b/vlib/v/checker/fn.v @@ -771,8 +771,6 @@ fn (mut c Checker) call_expr(mut node ast.CallExpr) ast.Type { c.inside_or_block_value = true c.check_or_expr(node.or_block, typ, c.expected_or_type, node) c.inside_or_block_value = old_inside_or_block_value - } else if node.or_block.kind == .propagate_option || node.or_block.kind == .propagate_result { - c.markused_option_or_result(!c.is_builtin_mod && c.mod != 'strings') } c.expected_or_type = old_expected_or_type c.markused_call_expr(left_type, mut node) diff --git a/vlib/v/checker/postfix.v b/vlib/v/checker/postfix.v index 559d0b8646..888e8a333f 100644 --- a/vlib/v/checker/postfix.v +++ b/vlib/v/checker/postfix.v @@ -37,9 +37,7 @@ fn (mut c Checker) postfix_expr(mut node ast.PostfixExpr) ast.Type { c.error('invalid operation: ${node.op.str()} (non-numeric type `${typ_str}`)', node.pos) } else { - if node.op == .question { - c.table.used_features.option_or_result = true - } else { + if node.op != .question { node.auto_locked, _ = c.fail_if_immutable(mut node.expr) } } diff --git a/vlib/v/checker/used_features.v b/vlib/v/checker/used_features.v index 3a0ddf33c1..05b3ee4939 100644 --- a/vlib/v/checker/used_features.v +++ b/vlib/v/checker/used_features.v @@ -1,14 +1,9 @@ +// Copyright (c) 2019-2024 Felipe Pena. All rights reserved. +// Use of this source code is governed by an MIT license that can be found in the LICENSE file. module checker import v.ast -@[inline] -fn (mut c Checker) markused_option_or_result(check bool) { - if check { - c.table.used_features.option_or_result = true - } -} - @[inline] fn (mut c Checker) markused_comptime_call(check bool, key string) { if check { @@ -135,7 +130,7 @@ fn (mut c Checker) markused_fn_call(mut node ast.CallExpr) { c.table.used_features.auto_str = true } else { if node.args[0].typ.has_option_or_result() { - c.table.used_features.option_or_result = true + c.table.used_features.print_options = true } c.table.used_features.print_types[node.args[0].typ.idx()] = true if !c.table.used_features.auto_str_ptr && node.args[0].expr is ast.Ident { @@ -181,6 +176,9 @@ fn (mut c Checker) markused_string_inter_lit(mut node ast.StringInterLiteral, ft if ftyp.is_ptr() { c.table.used_features.auto_str_ptr = true } + if ftyp.has_option_or_result() { + c.table.used_features.print_options = true + } c.table.used_features.interpolation = true } diff --git a/vlib/v/markused/markused.v b/vlib/v/markused/markused.v index e6e5de9c0b..e21be2a02d 100644 --- a/vlib/v/markused/markused.v +++ b/vlib/v/markused/markused.v @@ -184,7 +184,7 @@ pub fn mark_used(mut table ast.Table, mut pref_ pref.Preferences, ast_files []&a core_fns << '__new_array_with_array_default' core_fns << ref_array_idx_str + '.set' } - if table.used_features.option_or_result { + if table.used_features.print_options { include_panic_deps = true core_fns << '_option_ok' core_fns << '_result_ok' @@ -386,10 +386,6 @@ pub fn mark_used(mut table ast.Table, mut pref_ pref.Preferences, ast_files []&a all_fn_root_names << 'panic_debug' all_fn_root_names << 'tos3' } - if table.used_features.option_or_result { - all_fn_root_names << 'panic_option_not_set' - all_fn_root_names << 'panic_result_not_set' - } if pref_.is_test { all_fn_root_names << 'main.cb_assertion_ok' all_fn_root_names << 'main.cb_assertion_failed' @@ -534,9 +530,23 @@ pub fn mark_used(mut table ast.Table, mut pref_ pref.Preferences, ast_files []&a } } + if walker.used_panic > 0 { + walker.mark_fn_as_used('panic_option_not_set') + walker.mark_fn_as_used('panic_result_not_set') + } if walker.used_none > 0 || table.used_features.auto_str { walker.mark_fn_as_used('_option_none') } + if walker.used_option > 0 { + walker.mark_fn_as_used('_option_clone') + walker.mark_fn_as_used('_option_ok') + } + if walker.used_result > 0 { + walker.mark_fn_as_used('_result_ok') + } + if (walker.used_option + walker.used_result + walker.used_none) > 0 { + walker.mark_const_as_used('none__') + } if trace_skip_unused_fn_names { for key, _ in walker.used_fns { diff --git a/vlib/v/markused/walker.v b/vlib/v/markused/walker.v index 5c3bd5604b..6de8d3119b 100644 --- a/vlib/v/markused/walker.v +++ b/vlib/v/markused/walker.v @@ -17,7 +17,10 @@ pub mut: used_structs map[string]bool used_fields map[string]bool used_ifaces map[string]bool - used_none int + used_none int // _option_none + used_option int // _option_ok + used_result int // _result_ok + used_panic int // option/result propagation n_asserts int pref &pref.Preferences = unsafe { nil } mut: @@ -343,6 +346,9 @@ fn (mut w Walker) expr(node_ ast.Expr) { ast.CastExpr { w.expr(node.expr) w.expr(node.arg) + if node.typ.has_flag(.option) { + w.used_option++ + } } ast.ChanInit { w.expr(node.cap_expr) @@ -609,6 +615,12 @@ pub fn (mut w Walker) a_struct_info(sname string, info ast.Struct) { } if ifield.typ != 0 { fsym := w.table.sym(ifield.typ) + if ifield.typ.has_flag(.option) { + w.used_option++ + if !ifield.has_default_expr { + w.used_none++ + } + } match fsym.info { ast.Struct { w.a_struct_info(fsym.name, fsym.info) @@ -660,6 +672,11 @@ pub fn (mut w Walker) fn_decl(mut node ast.FnDecl) { if node.no_body { return } + if node.return_type.has_flag(.option) { + w.used_option++ + } else if node.return_type.has_flag(.result) { + w.used_result++ + } w.mark_fn_as_used(fkey) w.stmts(node.stmts) w.defer_stmts(node.defer_stmts) @@ -754,6 +771,11 @@ pub fn (mut w Walker) call_expr(mut node ast.CallExpr) { if !node.is_method || receiver_typ == stmt.receiver.typ { w.stmts(stmt.stmts) } + if node.return_type.has_flag(.option) { + w.used_option++ + } else if node.return_type.has_flag(.result) { + w.used_result++ + } } } @@ -784,6 +806,12 @@ pub fn (mut w Walker) const_fields(cfields []ast.ConstField) { pub fn (mut w Walker) or_block(node ast.OrExpr) { if node.kind == .block { w.stmts(node.stmts) + } else if node.kind == .propagate_option { + w.used_option++ + w.used_panic++ + } else if node.kind == .propagate_result { + w.used_result++ + w.used_panic++ } }