1
0
mirror of https://github.com/vlang/v.git synced 2023-08-10 21:13:21 +03:00

checker: fix missing checker error for fn abc() u64 { return -1 } (fix #15789) (#15795)

This commit is contained in:
shove 2022-09-18 01:59:52 +08:00 committed by GitHub
parent 085a09ebdb
commit bd3c9e888d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 57 additions and 15 deletions

View File

@ -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()) {

View File

@ -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 |

View File

@ -0,0 +1,12 @@
fn foo() u64 {
return -(3 - 1)
}
fn bar() u64 {
return -1
}
fn main() {
dump(foo())
dump(bar())
}

View File

@ -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