Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

parser, checker, pref: allow getting notified about unused function params #22879

Merged
merged 5 commits into from
Nov 17, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 7 additions & 1 deletion vlib/v/checker/checker.v
Original file line number Diff line number Diff line change
Expand Up @@ -289,7 +289,13 @@ pub fn (mut c Checker) check_scope_vars(sc &ast.Scope) {
ast.Var {
if !obj.is_used && obj.name[0] != `_` {
if !c.pref.translated && !c.file.is_translated {
c.warn('unused variable: `${obj.name}`', obj.pos)
if obj.is_arg {
if c.pref.show_unused_params {
c.note('unused parameter: `${obj.name}`', obj.pos)
}
} else {
c.warn('unused variable: `${obj.name}`', obj.pos)
}
}
}
if obj.is_mut && !obj.is_changed && !c.is_builtin_mod && obj.name != 'it' {
Expand Down
14 changes: 14 additions & 0 deletions vlib/v/checker/tests/unused_param.out
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
vlib/v/checker/tests/unused_param.vv:5:33: notice: unused parameter: `unused_param`
3 | struct Foo {}
4 |
5 | fn (unused_receiver Foo) method(unused_param int) {}
| ~~~~~~~~~~~~
6 |
7 | fn func(unused_param int) {}
vlib/v/checker/tests/unused_param.vv:7:9: notice: unused parameter: `unused_param`
5 | fn (unused_receiver Foo) method(unused_param int) {}
6 |
7 | fn func(unused_param int) {}
| ~~~~~~~~~~~~
8 |
9 | fn func2(_ int) {}
13 changes: 13 additions & 0 deletions vlib/v/checker/tests/unused_param.vv
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
#include <stdio.h>

struct Foo {}

fn (unused_receiver Foo) method(unused_param int) {}

fn func(unused_param int) {}

fn func2(_ int) {}

pub fn pub_func(unused_param int) {}

fn C.puts(unused_c_param &char) int
1 change: 1 addition & 0 deletions vlib/v/compiler_errors_test.v
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import benchmark

const skip_files = [
'non_existing.vv', // minimize commit diff churn, do not remove
'vlib/v/checker/tests/unused_param.vv',
spytheman marked this conversation as resolved.
Show resolved Hide resolved
]

const skip_on_cstrict = [
Expand Down
55 changes: 28 additions & 27 deletions vlib/v/parser/fn.v
Original file line number Diff line number Diff line change
Expand Up @@ -442,33 +442,6 @@ fn (mut p Parser) fn_decl() ast.FnDecl {
is_variadic = true
}
params << params_t
if !are_params_type_only {
for k, param in params {
if p.scope.known_var(param.name) {
p.error_with_pos('redefinition of parameter `${param.name}`', param.pos)
return ast.FnDecl{
scope: unsafe { nil }
}
}
is_stack_obj := !param.typ.has_flag(.shared_f) && (param.is_mut || param.typ.is_ptr())
p.scope.register(ast.Var{
name: param.name
typ: param.typ
is_mut: param.is_mut
is_auto_deref: param.is_mut
is_stack_obj: is_stack_obj
pos: param.pos
is_used: true
is_arg: true
ct_type_var: if (!is_method || k > 0) && param.typ.has_flag(.generic)
&& !param.typ.has_flag(.variadic) {
.generic_param
} else {
.no_comptime
}
})
}
}
// Return type
mut return_type_pos := p.tok.pos()
mut return_type := ast.void_type
Expand Down Expand Up @@ -515,6 +488,34 @@ run them via `v file.v` instead',
p.error_with_pos('cannot declare a static function as a receiver method', name_pos)
}
// Register
if !are_params_type_only {
for k, param in params {
if p.scope.known_var(param.name) {
p.error_with_pos('redefinition of parameter `${param.name}`', param.pos)
return ast.FnDecl{
scope: unsafe { nil }
}
}
is_stack_obj := !param.typ.has_flag(.shared_f) && (param.is_mut || param.typ.is_ptr())
p.scope.register(ast.Var{
name: param.name
typ: param.typ
is_mut: param.is_mut
is_auto_deref: param.is_mut
is_stack_obj: is_stack_obj
pos: param.pos
is_used: is_pub || no_body
|| (is_method && rec.type_pos == param.type_pos) || p.builtin_mod
is_arg: true
ct_type_var: if (!is_method || k > 0) && param.typ.has_flag(.generic)
&& !param.typ.has_flag(.variadic) {
.generic_param
} else {
.no_comptime
}
})
}
}
if is_method {
// Do not allow to modify / add methods to types from other modules
// arrays/maps dont belong to a module only their element types do
Expand Down
4 changes: 4 additions & 0 deletions vlib/v/pref/pref.v
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,7 @@ pub mut:
show_c_output bool // -show-c-output, print all cc output even if the code was compiled correctly
show_callgraph bool // -show-callgraph, print the program callgraph, in a Graphviz DOT format to stdout
show_depgraph bool // -show-depgraph, print the program module dependency graph, in a Graphviz DOT format to stdout
show_unused_params bool // NOTE: temporary until making it a default.
dump_c_flags string // `-dump-c-flags file.txt` - let V store all C flags, passed to the backend C compiler in `file.txt`, one C flag/value per line.
dump_modules string // `-dump-modules modules.txt` - let V store all V modules, that were used by the compiled program in `modules.txt`, one module per line.
dump_files string // `-dump-files files.txt` - let V store all V or .template file paths, that were used by the compiled program in `files.txt`, one path per line.
Expand Down Expand Up @@ -949,6 +950,9 @@ pub fn parse_args_and_show_errors(known_external_commands []string, args []strin
res.parse_line_info(res.line_info)
i++
}
'-check-unused-fn-args' {
res.show_unused_params = true
}
'-use-coroutines' {
res.use_coroutines = true
$if macos || linux {
Expand Down
Loading