mirror of
https://github.com/vlang/v.git
synced 2025-09-09 15:27:05 -04:00
checker: cleanup used_features logic (#23502)
This commit is contained in:
parent
496451ecbb
commit
1b9f15d60d
@ -10,7 +10,6 @@ import v.util
|
|||||||
@[heap; minify]
|
@[heap; minify]
|
||||||
pub struct UsedFeatures {
|
pub struct UsedFeatures {
|
||||||
pub mut:
|
pub mut:
|
||||||
interfaces bool // interface
|
|
||||||
dump bool // dump()
|
dump bool // dump()
|
||||||
index bool // string[0]
|
index bool // string[0]
|
||||||
range_index bool // string[0..1]
|
range_index bool // string[0..1]
|
||||||
|
@ -1392,9 +1392,8 @@ 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) {
|
fn (mut c Checker) check_or_expr(node ast.OrExpr, ret_type ast.Type, expr_return_type ast.Type, expr ast.Expr) {
|
||||||
if c.pref.skip_unused && !c.is_builtin_mod && node.kind != .absent && c.mod != 'strings' {
|
c.markused_option_or_result(!c.is_builtin_mod && node.kind != .absent && c.mod != 'strings')
|
||||||
c.table.used_features.option_or_result = true
|
|
||||||
}
|
|
||||||
if node.kind == .propagate_option {
|
if node.kind == .propagate_option {
|
||||||
if c.table.cur_fn != unsafe { nil } && !c.table.cur_fn.return_type.has_flag(.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 {
|
&& !c.table.cur_fn.is_main && !c.table.cur_fn.is_test && !c.inside_const {
|
||||||
@ -1794,16 +1793,12 @@ 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.check_or_expr(node.or_block, unwrapped_typ, c.expected_or_type, node)
|
||||||
c.expected_or_type = ast.void_type
|
c.expected_or_type = ast.void_type
|
||||||
}
|
}
|
||||||
if c.pref.skip_unused && node.or_block.kind != .absent
|
c.markused_option_or_result(node.or_block.kind != .absent
|
||||||
&& !c.table.used_features.option_or_result {
|
&& !c.table.used_features.option_or_result)
|
||||||
c.table.used_features.option_or_result = true
|
|
||||||
}
|
|
||||||
return field.typ
|
return field.typ
|
||||||
}
|
}
|
||||||
if mut method := c.table.sym(c.unwrap_generic(typ)).find_method_with_generic_parent(field_name) {
|
if mut method := c.table.sym(c.unwrap_generic(typ)).find_method_with_generic_parent(field_name) {
|
||||||
if c.pref.skip_unused && typ.has_flag(.generic) {
|
c.markused_comptime_call(typ.has_flag(.generic), '${int(method.params[0].typ)}.${field_name}')
|
||||||
c.table.used_features.comptime_calls['${int(method.params[0].typ)}.${field_name}'] = true
|
|
||||||
}
|
|
||||||
if c.expected_type != 0 && c.expected_type != ast.none_type {
|
if c.expected_type != 0 && c.expected_type != ast.none_type {
|
||||||
fn_type := ast.new_type(c.table.find_or_register_fn_type(method, false, true))
|
fn_type := ast.new_type(c.table.find_or_register_fn_type(method, false, true))
|
||||||
// if the expected type includes the receiver, don't hide it behind a closure
|
// if the expected type includes the receiver, don't hide it behind a closure
|
||||||
@ -2383,15 +2378,7 @@ fn (mut c Checker) assert_stmt(mut node ast.AssertStmt) {
|
|||||||
cur_exp_typ := c.expected_type
|
cur_exp_typ := c.expected_type
|
||||||
c.expected_type = ast.bool_type
|
c.expected_type = ast.bool_type
|
||||||
assert_type := c.check_expr_option_or_result_call(node.expr, c.expr(mut node.expr))
|
assert_type := c.check_expr_option_or_result_call(node.expr, c.expr(mut node.expr))
|
||||||
if c.pref.skip_unused && !c.table.used_features.auto_str && !c.is_builtin_mod
|
c.markused_assertstmt_auto_str(mut node)
|
||||||
&& mut node.expr is ast.InfixExpr {
|
|
||||||
if !c.table.sym(c.unwrap_generic(node.expr.left_type)).has_method('str') {
|
|
||||||
c.table.used_features.auto_str = true
|
|
||||||
}
|
|
||||||
if !c.table.sym(c.unwrap_generic(node.expr.right_type)).has_method('str') {
|
|
||||||
c.table.used_features.auto_str = true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if assert_type != ast.bool_type_idx {
|
if assert_type != ast.bool_type_idx {
|
||||||
atype_name := c.table.sym(assert_type).name
|
atype_name := c.table.sym(assert_type).name
|
||||||
c.error('assert can be used only with `bool` expressions, but found `${atype_name}` instead',
|
c.error('assert can be used only with `bool` expressions, but found `${atype_name}` instead',
|
||||||
@ -3051,17 +3038,7 @@ pub fn (mut c Checker) expr(mut node ast.Expr) ast.Type {
|
|||||||
c.table.used_features.dump = true
|
c.table.used_features.dump = true
|
||||||
c.expected_type = ast.string_type
|
c.expected_type = ast.string_type
|
||||||
node.expr_type = c.expr(mut node.expr)
|
node.expr_type = c.expr(mut node.expr)
|
||||||
if c.pref.skip_unused && !c.is_builtin_mod {
|
c.markused_dumpexpr(mut node)
|
||||||
if !c.table.sym(c.unwrap_generic(node.expr_type)).has_method('str') {
|
|
||||||
c.table.used_features.auto_str = true
|
|
||||||
if node.expr_type.is_ptr() {
|
|
||||||
c.table.used_features.auto_str_ptr = true
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
c.table.used_features.print_types[node.expr_type.idx()] = true
|
|
||||||
}
|
|
||||||
c.table.used_features.print_types[ast.int_type_idx] = true
|
|
||||||
}
|
|
||||||
if c.comptime.inside_comptime_for && mut node.expr is ast.Ident {
|
if c.comptime.inside_comptime_for && mut node.expr is ast.Ident {
|
||||||
if node.expr.ct_expr {
|
if node.expr.ct_expr {
|
||||||
node.expr_type = c.type_resolver.get_type(node.expr as ast.Ident)
|
node.expr_type = c.type_resolver.get_type(node.expr as ast.Ident)
|
||||||
@ -3284,10 +3261,7 @@ pub fn (mut c Checker) expr(mut node ast.Expr) ast.Type {
|
|||||||
ast.StructInit {
|
ast.StructInit {
|
||||||
if node.unresolved {
|
if node.unresolved {
|
||||||
mut expr_ := c.table.resolve_init(node, c.unwrap_generic(node.typ))
|
mut expr_ := c.table.resolve_init(node, c.unwrap_generic(node.typ))
|
||||||
if c.pref.skip_unused && c.table.used_features.used_maps == 0
|
c.markused_used_maps(c.table.used_features.used_maps == 0 && expr_ is ast.MapInit)
|
||||||
&& expr_ is ast.MapInit {
|
|
||||||
c.table.used_features.used_maps++
|
|
||||||
}
|
|
||||||
return c.expr(mut expr_)
|
return c.expr(mut expr_)
|
||||||
}
|
}
|
||||||
mut inited_fields := []string{}
|
mut inited_fields := []string{}
|
||||||
@ -3374,16 +3348,7 @@ fn (mut c Checker) cast_expr(mut node ast.CastExpr) ast.Type {
|
|||||||
to_type
|
to_type
|
||||||
}
|
}
|
||||||
final_to_is_ptr := to_type.is_ptr() || final_to_type.is_ptr()
|
final_to_is_ptr := to_type.is_ptr() || final_to_type.is_ptr()
|
||||||
if c.pref.skip_unused && !c.is_builtin_mod {
|
c.markused_castexpr(mut node, to_type, mut final_to_sym)
|
||||||
if c.table.used_features.used_maps == 0 && mut final_to_sym.info is ast.SumType {
|
|
||||||
if final_to_sym.info.variants.any(c.table.final_sym(it).kind == .map) {
|
|
||||||
c.table.used_features.used_maps++
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if c.mod !in ['strings', 'math.bits'] && to_type.is_ptr() {
|
|
||||||
c.table.used_features.cast_ptr = true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if to_type.has_flag(.result) {
|
if to_type.has_flag(.result) {
|
||||||
c.error('casting to Result type is forbidden', node.pos)
|
c.error('casting to Result type is forbidden', node.pos)
|
||||||
}
|
}
|
||||||
@ -4003,9 +3968,7 @@ fn (mut c Checker) ident(mut node ast.Ident) ast.Type {
|
|||||||
c.error('`mut` is not allowed with `=` (use `:=` to declare a variable)',
|
c.error('`mut` is not allowed with `=` (use `:=` to declare a variable)',
|
||||||
node.pos)
|
node.pos)
|
||||||
}
|
}
|
||||||
if c.pref.skip_unused && !c.is_builtin_mod && node.language == .v && node.name.contains('.') {
|
c.markused_external_type(!c.is_builtin_mod && node.language == .v && node.name.contains('.'))
|
||||||
c.table.used_features.external_types = true
|
|
||||||
}
|
|
||||||
if mut obj := node.scope.find(node.name) {
|
if mut obj := node.scope.find(node.name) {
|
||||||
match mut obj {
|
match mut obj {
|
||||||
ast.GlobalField {
|
ast.GlobalField {
|
||||||
|
@ -133,32 +133,7 @@ fn (mut c Checker) comptime_call(mut node ast.ComptimeCall) ast.Type {
|
|||||||
// check each arg expression
|
// check each arg expression
|
||||||
node.args[i].typ = c.expr(mut arg.expr)
|
node.args[i].typ = c.expr(mut arg.expr)
|
||||||
}
|
}
|
||||||
if c.pref.skip_unused {
|
c.markused_comptimecall(mut node)
|
||||||
c.table.used_features.comptime_calls['${int(c.unwrap_generic(c.comptime.comptime_for_method.receiver_type))}.${c.comptime.comptime_for_method.name}'] = true
|
|
||||||
if c.inside_anon_fn {
|
|
||||||
// $method passed to anon fn, mark all methods as used
|
|
||||||
sym := c.table.sym(c.unwrap_generic(node.left_type))
|
|
||||||
for m in sym.get_methods() {
|
|
||||||
c.table.used_features.comptime_calls['${int(c.unwrap_generic(m.receiver_type))}.${m.name}'] = true
|
|
||||||
if node.args.len > 0 && m.params.len > 0 {
|
|
||||||
last_param := m.params.last().typ
|
|
||||||
if (last_param.is_int() || last_param.is_bool())
|
|
||||||
&& c.table.final_sym(node.args.last().typ).kind == .array {
|
|
||||||
c.table.used_features.comptime_calls['${ast.string_type_idx}.${c.table.type_to_str(m.params.last().typ)}'] = true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
m := c.comptime.comptime_for_method
|
|
||||||
if node.args.len > 0 && m.params.len > 0 {
|
|
||||||
last_param := m.params.last().typ
|
|
||||||
if (last_param.is_int() || last_param.is_bool())
|
|
||||||
&& c.table.final_sym(node.args.last().typ).kind == .array {
|
|
||||||
c.table.used_features.comptime_calls['${ast.string_type_idx}.${c.table.type_to_str(m.params.last().typ)}'] = true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
c.stmts_ending_with_expression(mut node.or_block.stmts, c.expected_or_type)
|
c.stmts_ending_with_expression(mut node.or_block.stmts, c.expected_or_type)
|
||||||
return c.type_resolver.get_type(node)
|
return c.type_resolver.get_type(node)
|
||||||
}
|
}
|
||||||
@ -223,9 +198,7 @@ fn (mut c Checker) comptime_call(mut node ast.ComptimeCall) ast.Type {
|
|||||||
c.error('could not find method `${method_name}`', node.method_pos)
|
c.error('could not find method `${method_name}`', node.method_pos)
|
||||||
return ast.void_type
|
return ast.void_type
|
||||||
}
|
}
|
||||||
if c.pref.skip_unused {
|
c.markused_comptime_call(true, '${int(left_type)}.${method_name}')
|
||||||
c.table.used_features.comptime_calls['${int(left_type)}.${method_name}'] = true
|
|
||||||
}
|
|
||||||
node.result_type = f.return_type
|
node.result_type = f.return_type
|
||||||
return f.return_type
|
return f.return_type
|
||||||
}
|
}
|
||||||
@ -312,19 +285,7 @@ fn (mut c Checker) comptime_for(mut node ast.ComptimeFor) {
|
|||||||
unwrapped_expr_type := c.unwrap_generic(field.typ)
|
unwrapped_expr_type := c.unwrap_generic(field.typ)
|
||||||
tsym := c.table.sym(unwrapped_expr_type)
|
tsym := c.table.sym(unwrapped_expr_type)
|
||||||
c.table.dumps[int(unwrapped_expr_type.clear_flags(.option, .result, .atomic_f))] = tsym.cname
|
c.table.dumps[int(unwrapped_expr_type.clear_flags(.option, .result, .atomic_f))] = tsym.cname
|
||||||
if c.pref.skip_unused {
|
c.markused_comptimefor(mut node, unwrapped_expr_type)
|
||||||
c.table.used_features.dump = true
|
|
||||||
if c.table.used_features.used_maps == 0 {
|
|
||||||
final_sym := c.table.final_sym(unwrapped_expr_type)
|
|
||||||
if final_sym.info is ast.Map {
|
|
||||||
c.table.used_features.used_maps++
|
|
||||||
} else if final_sym.info is ast.SumType {
|
|
||||||
if final_sym.info.variants.any(c.table.final_sym(it).kind == .map) {
|
|
||||||
c.table.used_features.used_maps++
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if tsym.kind == .array_fixed {
|
if tsym.kind == .array_fixed {
|
||||||
info := tsym.info as ast.ArrayFixed
|
info := tsym.info as ast.ArrayFixed
|
||||||
if !info.is_fn_ret {
|
if !info.is_fn_ret {
|
||||||
|
@ -65,9 +65,7 @@ fn (mut c Checker) array_init(mut node ast.ArrayInit) ast.Type {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
ast.Map {
|
ast.Map {
|
||||||
if c.pref.skip_unused && !c.is_builtin_mod {
|
c.markused_array_method(!c.is_builtin_mod, 'map')
|
||||||
c.table.used_features.arr_map = true
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else {}
|
else {}
|
||||||
}
|
}
|
||||||
|
@ -756,22 +756,10 @@ fn (mut c Checker) call_expr(mut node ast.CallExpr) ast.Type {
|
|||||||
c.check_or_expr(node.or_block, typ, c.expected_or_type, node)
|
c.check_or_expr(node.or_block, typ, c.expected_or_type, node)
|
||||||
c.inside_or_block_value = old_inside_or_block_value
|
c.inside_or_block_value = old_inside_or_block_value
|
||||||
} else if node.or_block.kind == .propagate_option || node.or_block.kind == .propagate_result {
|
} else if node.or_block.kind == .propagate_option || node.or_block.kind == .propagate_result {
|
||||||
if c.pref.skip_unused && !c.is_builtin_mod && c.mod != 'strings' {
|
c.markused_option_or_result(!c.is_builtin_mod && c.mod != 'strings')
|
||||||
c.table.used_features.option_or_result = true
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
c.expected_or_type = old_expected_or_type
|
c.expected_or_type = old_expected_or_type
|
||||||
if c.pref.skip_unused && !c.is_builtin_mod && c.mod == 'main'
|
c.markused_call_expr(mut node)
|
||||||
&& !c.table.used_features.external_types {
|
|
||||||
if node.is_method {
|
|
||||||
if c.table.sym(node.left_type).is_builtin() {
|
|
||||||
c.table.used_features.external_types = true
|
|
||||||
}
|
|
||||||
} else if node.name.contains('.') {
|
|
||||||
c.table.used_features.external_types = true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if !c.inside_const && c.table.cur_fn != unsafe { nil } && !c.table.cur_fn.is_main
|
if !c.inside_const && c.table.cur_fn != unsafe { nil } && !c.table.cur_fn.is_main
|
||||||
&& !c.table.cur_fn.is_test {
|
&& !c.table.cur_fn.is_test {
|
||||||
// TODO: use just `if node.or_block.kind == .propagate_result && !c.table.cur_fn.return_type.has_flag(.result) {` after the deprecation for ?!Type
|
// TODO: use just `if node.or_block.kind == .propagate_result && !c.table.cur_fn.return_type.has_flag(.result) {` after the deprecation for ?!Type
|
||||||
@ -1422,20 +1410,7 @@ fn (mut c Checker) fn_call(mut node ast.CallExpr, mut continue_check &bool) ast.
|
|||||||
if node.args.len > 0 && fn_name in print_everything_fns {
|
if node.args.len > 0 && fn_name in print_everything_fns {
|
||||||
node.args[0].ct_expr = c.comptime.is_comptime(node.args[0].expr)
|
node.args[0].ct_expr = c.comptime.is_comptime(node.args[0].expr)
|
||||||
c.builtin_args(mut node, fn_name, func)
|
c.builtin_args(mut node, fn_name, func)
|
||||||
if c.pref.skip_unused && !c.is_builtin_mod && c.mod != 'math.bits'
|
c.markused_fn_call(mut node)
|
||||||
&& node.args[0].expr !is ast.StringLiteral {
|
|
||||||
if !c.table.sym(c.unwrap_generic(node.args[0].typ)).has_method('str') {
|
|
||||||
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_types[node.args[0].typ.idx()] = true
|
|
||||||
}
|
|
||||||
if node.args[0].typ.is_ptr() {
|
|
||||||
c.table.used_features.auto_str_ptr = true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return func.return_type
|
return func.return_type
|
||||||
}
|
}
|
||||||
// `return error(err)` -> `return err`
|
// `return error(err)` -> `return err`
|
||||||
@ -1980,15 +1955,7 @@ fn (mut c Checker) method_call(mut node ast.CallExpr, mut continue_check &bool)
|
|||||||
continue_check = false
|
continue_check = false
|
||||||
return ast.void_type
|
return ast.void_type
|
||||||
}
|
}
|
||||||
if c.pref.skip_unused {
|
c.markused_method_call(mut node, mut left_expr, left_type)
|
||||||
if !left_type.has_flag(.generic) && mut left_expr is ast.Ident {
|
|
||||||
if left_expr.obj is ast.Var && left_expr.obj.ct_type_var == .smartcast {
|
|
||||||
c.table.used_features.comptime_calls['${int(left_type)}.${node.name}'] = true
|
|
||||||
}
|
|
||||||
} else if left_type.has_flag(.generic) {
|
|
||||||
c.table.used_features.comptime_calls['${int(c.unwrap_generic(left_type))}.${node.name}'] = true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
c.expected_type = left_type
|
c.expected_type = left_type
|
||||||
mut is_generic := left_type.has_flag(.generic)
|
mut is_generic := left_type.has_flag(.generic)
|
||||||
node.left_type = left_type
|
node.left_type = left_type
|
||||||
@ -2119,9 +2086,7 @@ fn (mut c Checker) method_call(mut node ast.CallExpr, mut continue_check &bool)
|
|||||||
if embed_types.len != 0 {
|
if embed_types.len != 0 {
|
||||||
is_method_from_embed = true
|
is_method_from_embed = true
|
||||||
node.from_embed_types = embed_types
|
node.from_embed_types = embed_types
|
||||||
if c.pref.skip_unused && node.left_type.has_flag(.generic) {
|
c.markused_comptime_call(node.left_type.has_flag(.generic), '${int(method.receiver_type)}.${method.name}')
|
||||||
c.table.used_features.comptime_calls['${int(method.receiver_type)}.${method.name}'] = true
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if final_left_sym.kind == .aggregate {
|
if final_left_sym.kind == .aggregate {
|
||||||
@ -2816,9 +2781,7 @@ fn (mut c Checker) check_expected_arg_count(mut node ast.CallExpr, f &ast.Fn) !
|
|||||||
}
|
}
|
||||||
if f.is_variadic {
|
if f.is_variadic {
|
||||||
min_required_params--
|
min_required_params--
|
||||||
if c.pref.skip_unused && !c.is_builtin_mod {
|
c.markused_array_method(!c.is_builtin_mod, '')
|
||||||
c.table.used_features.arr_init = true
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
has_decompose := node.args.any(it.expr is ast.ArrayDecompose)
|
has_decompose := node.args.any(it.expr is ast.ArrayDecompose)
|
||||||
if has_decompose {
|
if has_decompose {
|
||||||
@ -3437,17 +3400,7 @@ fn (mut c Checker) array_builtin_method_call(mut node ast.CallExpr, left_type as
|
|||||||
}
|
}
|
||||||
node.return_type = ast.int_type
|
node.return_type = ast.int_type
|
||||||
} else if method_name in ['first', 'last', 'pop'] {
|
} else if method_name in ['first', 'last', 'pop'] {
|
||||||
if c.pref.skip_unused && !c.is_builtin_mod {
|
c.markused_array_method(!c.is_builtin_mod, method_name)
|
||||||
if method_name == 'first' {
|
|
||||||
c.table.used_features.arr_first = true
|
|
||||||
}
|
|
||||||
if method_name == 'last' {
|
|
||||||
c.table.used_features.arr_last = true
|
|
||||||
}
|
|
||||||
if method_name == 'pop' {
|
|
||||||
c.table.used_features.arr_pop = true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if node.args.len != 0 {
|
if node.args.len != 0 {
|
||||||
c.error('`.${method_name}()` does not have any arguments', arg0.pos)
|
c.error('`.${method_name}()` does not have any arguments', arg0.pos)
|
||||||
}
|
}
|
||||||
@ -3459,9 +3412,7 @@ fn (mut c Checker) array_builtin_method_call(mut node ast.CallExpr, left_type as
|
|||||||
node.receiver_type = node.left_type
|
node.receiver_type = node.left_type
|
||||||
}
|
}
|
||||||
} else if method_name == 'delete' {
|
} else if method_name == 'delete' {
|
||||||
if c.pref.skip_unused && !c.is_builtin_mod {
|
c.markused_array_method(!c.is_builtin_mod, method_name)
|
||||||
c.table.used_features.arr_delete = true
|
|
||||||
}
|
|
||||||
c.check_for_mut_receiver(mut node.left)
|
c.check_for_mut_receiver(mut node.left)
|
||||||
unwrapped_left_sym := c.table.sym(unwrapped_left_type)
|
unwrapped_left_sym := c.table.sym(unwrapped_left_type)
|
||||||
if method := c.table.find_method(unwrapped_left_sym, method_name) {
|
if method := c.table.find_method(unwrapped_left_sym, method_name) {
|
||||||
|
@ -57,10 +57,7 @@ fn (mut c Checker) infix_expr(mut node ast.InfixExpr) ast.Type {
|
|||||||
}
|
}
|
||||||
// `arr << if n > 0 { 10 } else { 11 }` set the right c.expected_type
|
// `arr << if n > 0 { 10 } else { 11 }` set the right c.expected_type
|
||||||
if node.op == .left_shift && c.table.sym(left_type).kind == .array {
|
if node.op == .left_shift && c.table.sym(left_type).kind == .array {
|
||||||
if c.pref.skip_unused && !c.is_builtin_mod && c.mod != 'strings' {
|
c.markused_infiexpr(!c.is_builtin_mod && c.mod != 'strings')
|
||||||
c.table.used_features.index = true
|
|
||||||
c.table.used_features.arr_init = true
|
|
||||||
}
|
|
||||||
if mut node.right is ast.IfExpr {
|
if mut node.right is ast.IfExpr {
|
||||||
if node.right.is_expr && node.right.branches.len > 0 {
|
if node.right.is_expr && node.right.branches.len > 0 {
|
||||||
mut last_stmt := node.right.branches[0].stmts.last()
|
mut last_stmt := node.right.branches[0].stmts.last()
|
||||||
|
@ -12,9 +12,6 @@ fn (mut c Checker) interface_decl(mut node ast.InterfaceDecl) {
|
|||||||
is_js := node.language == .js
|
is_js := node.language == .js
|
||||||
if mut decl_sym.info is ast.Interface {
|
if mut decl_sym.info is ast.Interface {
|
||||||
mut has_generic_types := false
|
mut has_generic_types := false
|
||||||
if c.pref.skip_unused && decl_sym.mod == 'main' {
|
|
||||||
c.table.used_features.interfaces = true
|
|
||||||
}
|
|
||||||
if node.embeds.len > 0 {
|
if node.embeds.len > 0 {
|
||||||
all_embeds := c.expand_iface_embeds(node, 0, node.embeds)
|
all_embeds := c.expand_iface_embeds(node, 0, node.embeds)
|
||||||
// eprintln('> node.name: $node.name | node.embeds.len: $node.embeds.len | all_embeds: $all_embeds.len')
|
// eprintln('> node.name: $node.name | node.embeds.len: $node.embeds.len | all_embeds: $all_embeds.len')
|
||||||
|
@ -53,17 +53,7 @@ fn (mut c Checker) string_inter_lit(mut node ast.StringInterLiteral) ast.Type {
|
|||||||
c.error('expression returning type `char` cannot be used in string interpolation directly, print its address or cast it to an integer instead',
|
c.error('expression returning type `char` cannot be used in string interpolation directly, print its address or cast it to an integer instead',
|
||||||
expr.pos())
|
expr.pos())
|
||||||
}
|
}
|
||||||
if c.pref.skip_unused && !c.is_builtin_mod {
|
c.markused_string_inter_lit(mut node, ftyp)
|
||||||
if !c.table.sym(ftyp).has_method('str') {
|
|
||||||
c.table.used_features.auto_str = true
|
|
||||||
} else {
|
|
||||||
c.table.used_features.print_types[ftyp.idx()] = true
|
|
||||||
}
|
|
||||||
if ftyp.is_ptr() {
|
|
||||||
c.table.used_features.auto_str_ptr = true
|
|
||||||
}
|
|
||||||
c.table.used_features.interpolation = true
|
|
||||||
}
|
|
||||||
c.fail_if_unreadable(expr, ftyp, 'interpolation object')
|
c.fail_if_unreadable(expr, ftyp, 'interpolation object')
|
||||||
node.expr_types << ftyp
|
node.expr_types << ftyp
|
||||||
ftyp_sym := c.table.sym(ftyp)
|
ftyp_sym := c.table.sym(ftyp)
|
||||||
|
199
vlib/v/checker/used_features.v
Normal file
199
vlib/v/checker/used_features.v
Normal file
@ -0,0 +1,199 @@
|
|||||||
|
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 {
|
||||||
|
c.table.used_features.comptime_calls[key] = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn (mut c Checker) markused_assertstmt_auto_str(mut node ast.AssertStmt) {
|
||||||
|
if !c.table.used_features.auto_str && !c.is_builtin_mod && mut node.expr is ast.InfixExpr {
|
||||||
|
if !c.table.sym(c.unwrap_generic(node.expr.left_type)).has_method('str') {
|
||||||
|
c.table.used_features.auto_str = true
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if !c.table.sym(c.unwrap_generic(node.expr.right_type)).has_method('str') {
|
||||||
|
c.table.used_features.auto_str = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn (mut c Checker) markused_dumpexpr(mut node ast.DumpExpr) {
|
||||||
|
if c.is_builtin_mod {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if !c.table.sym(c.unwrap_generic(node.expr_type)).has_method('str') {
|
||||||
|
c.table.used_features.auto_str = true
|
||||||
|
if node.expr_type.is_ptr() {
|
||||||
|
c.table.used_features.auto_str_ptr = true
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
c.table.used_features.print_types[node.expr_type.idx()] = true
|
||||||
|
}
|
||||||
|
c.table.used_features.print_types[ast.int_type_idx] = true
|
||||||
|
}
|
||||||
|
|
||||||
|
@[inline]
|
||||||
|
fn (mut c Checker) markused_used_maps(check bool) {
|
||||||
|
if check {
|
||||||
|
c.table.used_features.used_maps++
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn (mut c Checker) markused_castexpr(mut node ast.CastExpr, to_type ast.Type, mut final_to_sym ast.TypeSymbol) {
|
||||||
|
if c.is_builtin_mod {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if c.table.used_features.used_maps == 0 && mut final_to_sym.info is ast.SumType {
|
||||||
|
if final_to_sym.info.variants.any(c.table.final_sym(it).kind == .map) {
|
||||||
|
c.table.used_features.used_maps++
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if c.mod !in ['strings', 'math.bits'] && to_type.is_ptr() {
|
||||||
|
c.table.used_features.cast_ptr = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn (mut c Checker) markused_external_type(check bool) {
|
||||||
|
if check {
|
||||||
|
c.table.used_features.external_types = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn (mut c Checker) markused_comptimecall(mut node ast.ComptimeCall) {
|
||||||
|
c.markused_comptime_call(true, '${int(c.unwrap_generic(c.comptime.comptime_for_method.receiver_type))}.${c.comptime.comptime_for_method.name}')
|
||||||
|
if c.inside_anon_fn {
|
||||||
|
// $method passed to anon fn, mark all methods as used
|
||||||
|
sym := c.table.sym(c.unwrap_generic(node.left_type))
|
||||||
|
for m in sym.get_methods() {
|
||||||
|
c.table.used_features.comptime_calls['${int(c.unwrap_generic(m.receiver_type))}.${m.name}'] = true
|
||||||
|
if node.args.len > 0 && m.params.len > 0 {
|
||||||
|
last_param := m.params.last().typ
|
||||||
|
if (last_param.is_int() || last_param.is_bool())
|
||||||
|
&& c.table.final_sym(node.args.last().typ).kind == .array {
|
||||||
|
c.table.used_features.comptime_calls['${ast.string_type_idx}.${c.table.type_to_str(m.params.last().typ)}'] = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
m := c.comptime.comptime_for_method
|
||||||
|
if node.args.len > 0 && m.params.len > 0 {
|
||||||
|
last_param := m.params.last().typ
|
||||||
|
if (last_param.is_int() || last_param.is_bool())
|
||||||
|
&& c.table.final_sym(node.args.last().typ).kind == .array {
|
||||||
|
c.table.used_features.comptime_calls['${ast.string_type_idx}.${c.table.type_to_str(m.params.last().typ)}'] = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn (mut c Checker) markused_comptimefor(mut node ast.ComptimeFor, unwrapped_expr_type ast.Type) {
|
||||||
|
c.table.used_features.dump = true
|
||||||
|
if c.table.used_features.used_maps == 0 {
|
||||||
|
final_sym := c.table.final_sym(unwrapped_expr_type)
|
||||||
|
if final_sym.info is ast.Map {
|
||||||
|
c.table.used_features.used_maps++
|
||||||
|
} else if final_sym.info is ast.SumType {
|
||||||
|
if final_sym.info.variants.any(c.table.final_sym(it).kind == .map) {
|
||||||
|
c.table.used_features.used_maps++
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn (mut c Checker) markused_call_expr(mut node ast.CallExpr) {
|
||||||
|
if !c.is_builtin_mod && c.mod == 'main' && !c.table.used_features.external_types {
|
||||||
|
if node.is_method {
|
||||||
|
if c.table.sym(node.left_type).is_builtin() {
|
||||||
|
c.table.used_features.external_types = true
|
||||||
|
}
|
||||||
|
} else if node.name.contains('.') {
|
||||||
|
c.table.used_features.external_types = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn (mut c Checker) markused_fn_call(mut node ast.CallExpr) {
|
||||||
|
if !c.is_builtin_mod && c.mod != 'math.bits' && node.args[0].expr !is ast.StringLiteral {
|
||||||
|
if !c.table.sym(c.unwrap_generic(node.args[0].typ)).has_method('str') {
|
||||||
|
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_types[node.args[0].typ.idx()] = true
|
||||||
|
}
|
||||||
|
if node.args[0].typ.is_ptr() {
|
||||||
|
c.table.used_features.auto_str_ptr = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn (mut c Checker) markused_method_call(mut node ast.CallExpr, mut left_expr ast.Expr, left_type ast.Type) {
|
||||||
|
if !left_type.has_flag(.generic) && mut left_expr is ast.Ident {
|
||||||
|
if left_expr.obj is ast.Var && left_expr.obj.ct_type_var == .smartcast {
|
||||||
|
c.table.used_features.comptime_calls['${int(left_type)}.${node.name}'] = true
|
||||||
|
}
|
||||||
|
} else if left_type.has_flag(.generic) {
|
||||||
|
c.table.used_features.comptime_calls['${int(c.unwrap_generic(left_type))}.${node.name}'] = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn (mut c Checker) markused_string_inter_lit(mut node ast.StringInterLiteral, ftyp ast.Type) {
|
||||||
|
if c.is_builtin_mod {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if !c.table.sym(ftyp).has_method('str') {
|
||||||
|
c.table.used_features.auto_str = true
|
||||||
|
} else {
|
||||||
|
c.table.used_features.print_types[ftyp.idx()] = true
|
||||||
|
}
|
||||||
|
if ftyp.is_ptr() {
|
||||||
|
c.table.used_features.auto_str_ptr = true
|
||||||
|
}
|
||||||
|
c.table.used_features.interpolation = true
|
||||||
|
}
|
||||||
|
|
||||||
|
fn (mut c Checker) markused_infiexpr(check bool) {
|
||||||
|
if check {
|
||||||
|
c.table.used_features.index = true
|
||||||
|
c.table.used_features.arr_init = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn (mut c Checker) markused_array_method(check bool, method_name string) {
|
||||||
|
if !check {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
match method_name {
|
||||||
|
'' { // array init
|
||||||
|
c.table.used_features.arr_init = true
|
||||||
|
}
|
||||||
|
'first' {
|
||||||
|
c.table.used_features.arr_first = true
|
||||||
|
}
|
||||||
|
'last' {
|
||||||
|
c.table.used_features.arr_last = true
|
||||||
|
}
|
||||||
|
'pop' {
|
||||||
|
c.table.used_features.arr_pop = true
|
||||||
|
}
|
||||||
|
'delete' {
|
||||||
|
c.table.used_features.arr_delete = true
|
||||||
|
}
|
||||||
|
'map' {
|
||||||
|
c.table.used_features.arr_map = true
|
||||||
|
}
|
||||||
|
else {}
|
||||||
|
}
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user