From bd3c9e888d734c570eccd5a1b1b749b0779e9061 Mon Sep 17 00:00:00 2001 From: shove Date: Sun, 18 Sep 2022 01:59:52 +0800 Subject: [PATCH] checker: fix missing checker error for fn abc() u64 { return -1 } (fix #15789) (#15795) --- vlib/v/checker/return.v | 45 +++++++++++++------ .../tests/fn_return_unsign_type_mismatch.out | 13 ++++++ .../tests/fn_return_unsign_type_mismatch.vv | 12 +++++ vlib/v/pref/pref.v | 2 +- 4 files changed, 57 insertions(+), 15 deletions(-) create mode 100644 vlib/v/checker/tests/fn_return_unsign_type_mismatch.out create mode 100644 vlib/v/checker/tests/fn_return_unsign_type_mismatch.vv diff --git a/vlib/v/checker/return.v b/vlib/v/checker/return.v index 1711bbab2..16c0d8999 100644 --- a/vlib/v/checker/return.v +++ b/vlib/v/checker/return.v @@ -110,26 +110,43 @@ pub fn (mut c Checker) return_stmt(mut node ast.Return) { c.error('cannot use `${c.table.type_to_str(got_typ)}` as type `${c.table.type_to_str(exp_type)}` in return argument', pos) } - if node.exprs[expr_idxs[i]] !is ast.ComptimeCall && !c.check_types(got_typ, exp_type) { + if node.exprs[expr_idxs[i]] !is ast.ComptimeCall { got_typ_sym := c.table.sym(got_typ) - mut exp_typ_sym := c.table.sym(exp_type) - if exp_typ_sym.kind == .interface_ { - if c.type_implements(got_typ, exp_type, node.pos) { - if !got_typ.is_ptr() && !got_typ.is_pointer() && got_typ_sym.kind != .interface_ - && !c.inside_unsafe { - c.mark_as_referenced(mut &node.exprs[expr_idxs[i]], true) + exp_typ_sym := c.table.sym(exp_type) + pos := node.exprs[expr_idxs[i]].pos() + if c.check_types(got_typ, exp_type) { + if exp_type.is_unsigned() && got_typ.is_int_literal() { + if node.exprs[expr_idxs[i]] is ast.IntegerLiteral { + var := (node.exprs[expr_idxs[i]] as ast.IntegerLiteral).val + if var[0] == `-` { + c.note('cannot use a negative value as value of type `${c.table.type_to_str(exp_type)}` in return argument', + pos) + } + } else { + if node.exprs[expr_idxs[i]] !is ast.Ident { + c.note('use signed type `${c.table.type_to_str(got_typ)}` as unsigned type `${c.table.type_to_str(exp_type)}` in return argument may cause unexpected', + pos) + } } } - continue - } - if got_typ_sym.kind == .function && exp_typ_sym.kind == .function { - if (got_typ_sym.info as ast.FnType).is_anon { + } else { + if exp_typ_sym.kind == .interface_ { + if c.type_implements(got_typ, exp_type, node.pos) { + if !got_typ.is_ptr() && !got_typ.is_pointer() + && got_typ_sym.kind != .interface_ && !c.inside_unsafe { + c.mark_as_referenced(mut &node.exprs[expr_idxs[i]], true) + } + } continue } + if got_typ_sym.kind == .function && exp_typ_sym.kind == .function { + if (got_typ_sym.info as ast.FnType).is_anon { + continue + } + } + c.error('cannot use `$got_typ_sym.name` as type `${c.table.type_to_str(exp_type)}` in return argument', + pos) } - pos := node.exprs[expr_idxs[i]].pos() - c.error('cannot use `$got_typ_sym.name` as type `${c.table.type_to_str(exp_type)}` in return argument', - pos) } if (got_typ.is_ptr() || got_typ.is_pointer()) && (!exp_type.is_ptr() && !exp_type.is_pointer()) { diff --git a/vlib/v/checker/tests/fn_return_unsign_type_mismatch.out b/vlib/v/checker/tests/fn_return_unsign_type_mismatch.out new file mode 100644 index 000000000..dd2014753 --- /dev/null +++ b/vlib/v/checker/tests/fn_return_unsign_type_mismatch.out @@ -0,0 +1,13 @@ +vlib/v/checker/tests/fn_return_unsign_type_mismatch.vv:2:9: notice: use signed type `int literal` as unsigned type `u64` in return argument may cause unexpected + 1 | fn foo() u64 { + 2 | return -(3 - 1) + | ^ + 3 | } + 4 | +vlib/v/checker/tests/fn_return_unsign_type_mismatch.vv:6:9: notice: cannot use a negative value as value of type `u64` in return argument + 4 | + 5 | fn bar() u64 { + 6 | return -1 + | ~~ + 7 | } + 8 | diff --git a/vlib/v/checker/tests/fn_return_unsign_type_mismatch.vv b/vlib/v/checker/tests/fn_return_unsign_type_mismatch.vv new file mode 100644 index 000000000..1069052f1 --- /dev/null +++ b/vlib/v/checker/tests/fn_return_unsign_type_mismatch.vv @@ -0,0 +1,12 @@ +fn foo() u64 { + return -(3 - 1) +} + +fn bar() u64 { + return -1 +} + +fn main() { + dump(foo()) + dump(bar()) +} diff --git a/vlib/v/pref/pref.v b/vlib/v/pref/pref.v index b881ddf71..d756a3fec 100644 --- a/vlib/v/pref/pref.v +++ b/vlib/v/pref/pref.v @@ -209,7 +209,7 @@ pub mut: cache_manager vcache.CacheManager gc_mode GarbageCollectionMode = .unknown // .no_gc, .boehm, .boehm_leak, ... assert_failure_mode AssertFailureMode // whether to call abort() or print_backtrace() after an assertion failure - message_limit int = 100 // the maximum amount of warnings/errors/notices that will be accumulated + message_limit int = 150 // the maximum amount of warnings/errors/notices that will be accumulated nofloat bool // for low level code, like kernels: replaces f32 with u32 and f64 with u64 // checker settings: checker_match_exhaustive_cutoff_limit int = 12 -- 2.39.5