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

checker: allow get_ref() or { unsafe{nil} }, as well as fn get_ref() ?&Type { return unsafe { nil } } (fix: #16062) (#16063)

This commit is contained in:
shove 2022-10-14 00:49:10 +08:00 committed by GitHub
parent 51a9e89c4a
commit aabda5a525
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 32 additions and 3 deletions

View File

@ -1030,6 +1030,10 @@ fn (mut c Checker) check_or_last_stmt(stmt ast.Stmt, ret_type ast.Type, expr_ret
c.error('`or` block must provide a default value of type `$expected_type_name`, or return/continue/break or call a [noreturn] function like panic(err) or exit(1)',
stmt.expr.pos())
} else {
if ret_type.is_ptr() && last_stmt_typ.is_pointer()
&& c.table.sym(last_stmt_typ).kind == .voidptr {
return
}
type_name := c.table.type_to_str(last_stmt_typ)
expected_type_name := c.table.type_to_str(ret_type.clear_flag(.optional).clear_flag(.result))
c.error('wrong return type `$type_name` in the `or {}` block, expected `$expected_type_name`',
@ -1070,7 +1074,9 @@ fn (mut c Checker) check_or_last_stmt(stmt ast.Stmt, ret_type ast.Type, expr_ret
return
}
if c.check_types(stmt.typ, expr_return_type) {
if stmt.typ.is_ptr() == expr_return_type.is_ptr() {
if stmt.typ.is_ptr() == expr_return_type.is_ptr()
|| (expr_return_type.is_ptr() && stmt.typ.is_pointer()
&& c.table.sym(stmt.typ).kind == .voidptr) {
return
}
}

View File

@ -382,11 +382,34 @@ fn test_return_or() {
}
// For issue #16058: cgen error: exists spaces in the name of the ?&C.struct
fn bar() ?&C.stat {
fn get_opt_pointer_to_c_struct() ?&C.stat {
return none
}
fn test_optional_ref_c_struct_gen() {
_ := bar() or { &C.stat{} }
_ := get_opt_pointer_to_c_struct() or { &C.stat{} }
}
// For issue #16062: checker disallow the return of voidptr(nil) in or block
struct Bar {}
fn get_bar(should_return_value bool) ?&Bar {
if should_return_value {
return unsafe { nil }
}
return none
}
fn test_() {
a := get_bar(true)?
assert a == unsafe { nil }
//
x := get_bar(false) or {
assert true
unsafe { nil }
}
assert x == unsafe { nil }
//
get_bar(false) or { unsafe { nil } }
assert true
}