mirror of
https://github.com/vlang/v.git
synced 2023-08-10 21:13:21 +03:00
all: clean up optional and result handling (#16034)
This commit is contained in:
parent
34d115d883
commit
dab1c8a71d
@ -565,7 +565,7 @@ pub mut:
|
||||
|
||||
// returns TypeSymbol kind only if there are no type modifiers
|
||||
pub fn (t &Table) type_kind(typ Type) Kind {
|
||||
if typ.nr_muls() > 0 || typ.has_flag(.optional) {
|
||||
if typ.nr_muls() > 0 || typ.has_flag(.optional) || typ.has_flag(.result) {
|
||||
return Kind.placeholder
|
||||
}
|
||||
return t.sym(typ).kind
|
||||
@ -862,7 +862,7 @@ pub fn (t &TypeSymbol) is_builtin() bool {
|
||||
|
||||
// type_size returns the size and alignment (in bytes) of `typ`, similarly to C's `sizeof()` and `alignof()`.
|
||||
pub fn (t &Table) type_size(typ Type) (int, int) {
|
||||
if typ.has_flag(.optional) {
|
||||
if typ.has_flag(.optional) || typ.has_flag(.result) {
|
||||
return t.type_size(ast.error_type_idx)
|
||||
}
|
||||
if typ.nr_muls() > 0 {
|
||||
|
@ -282,7 +282,7 @@ pub fn (mut c Checker) map_init(mut node ast.MapInit) ast.Type {
|
||||
sym := c.table.sym(c.expected_type)
|
||||
if sym.kind == .map {
|
||||
info := sym.map_info()
|
||||
node.typ = c.expected_type.clear_flag(.optional)
|
||||
node.typ = c.expected_type.clear_flag(.optional).clear_flag(.result)
|
||||
node.key_type = info.key_type
|
||||
node.value_type = info.value_type
|
||||
return node.typ
|
||||
|
@ -120,6 +120,9 @@ fn (mut c Checker) fn_decl(mut node ast.FnDecl) {
|
||||
} else if multi_type.has_flag(.optional) {
|
||||
c.error('option cannot be used in multi-return, return an option instead',
|
||||
node.return_type_pos)
|
||||
} else if multi_type.has_flag(.result) {
|
||||
c.error('result cannot be used in multi-return, return a result instead',
|
||||
node.return_type_pos)
|
||||
} else if multi_sym.kind == .array_fixed {
|
||||
c.error('fixed array cannot be used in multi-return', node.return_type_pos)
|
||||
}
|
||||
@ -208,8 +211,9 @@ fn (mut c Checker) fn_decl(mut node ast.FnDecl) {
|
||||
c.error('invalid use of reserved type `$param.name` as a parameter name',
|
||||
param.pos)
|
||||
}
|
||||
if param.typ.has_flag(.optional) {
|
||||
c.error('optional type argument is not supported currently', param.type_pos)
|
||||
if param.typ.has_flag(.optional) || param.typ.has_flag(.result) {
|
||||
c.error('optional or result type argument is not supported currently',
|
||||
param.type_pos)
|
||||
}
|
||||
if !param.typ.is_ptr() { // value parameter, i.e. on stack - check for `[heap]`
|
||||
arg_typ_sym := c.table.sym(param.typ)
|
||||
@ -450,7 +454,7 @@ pub fn (mut c Checker) call_expr(mut node ast.CallExpr) ast.Type {
|
||||
c.inside_fn_arg = old_inside_fn_arg
|
||||
// autofree: mark args that have to be freed (after saving them in tmp exprs)
|
||||
free_tmp_arg_vars := c.pref.autofree && !c.is_builtin_mod && node.args.len > 0
|
||||
&& !node.args[0].typ.has_flag(.optional)
|
||||
&& !node.args[0].typ.has_flag(.optional) && !node.args[0].typ.has_flag(.result)
|
||||
if free_tmp_arg_vars && !c.inside_const {
|
||||
for i, arg in node.args {
|
||||
if arg.typ != ast.string_type {
|
||||
@ -471,7 +475,7 @@ pub fn (mut c Checker) call_expr(mut node ast.CallExpr) ast.Type {
|
||||
node.free_receiver = true
|
||||
}
|
||||
}
|
||||
c.expected_or_type = node.return_type.clear_flag(.optional)
|
||||
c.expected_or_type = node.return_type.clear_flag(.optional).clear_flag(.result)
|
||||
c.stmts_ending_with_expression(node.or_block.stmts)
|
||||
c.expected_or_type = ast.void_type
|
||||
|
||||
@ -1982,8 +1986,9 @@ fn (mut c Checker) check_map_and_filter(is_map bool, elem_typ ast.Type, node ast
|
||||
if is_map && arg_expr.return_type in [ast.void_type, 0] {
|
||||
c.error('type mismatch, `$arg_expr.name` does not return anything', arg_expr.pos)
|
||||
} else if !is_map && arg_expr.return_type != ast.bool_type {
|
||||
if arg_expr.or_block.kind != .absent && arg_expr.return_type.has_flag(.optional)
|
||||
&& arg_expr.return_type.clear_flag(.optional) == ast.bool_type {
|
||||
if arg_expr.or_block.kind != .absent && (arg_expr.return_type.has_flag(.optional)
|
||||
|| arg_expr.return_type.has_flag(.result))
|
||||
&& arg_expr.return_type.clear_flag(.optional).clear_flag(.result) == ast.bool_type {
|
||||
return
|
||||
}
|
||||
c.error('type mismatch, `$arg_expr.name` must return a bool', arg_expr.pos)
|
||||
@ -2116,6 +2121,9 @@ fn (mut c Checker) array_builtin_method_call(mut node ast.CallExpr, left_type as
|
||||
if thread_ret_type.has_flag(.optional) {
|
||||
c.error('`.wait()` cannot be called for an array when thread functions return optionals. Iterate over the arrays elements instead and handle each returned optional with `or`.',
|
||||
node.pos)
|
||||
} else if thread_ret_type.has_flag(.result) {
|
||||
c.error('`.wait()` cannot be called for an array when thread functions return results. Iterate over the arrays elements instead and handle each returned result with `or`.',
|
||||
node.pos)
|
||||
}
|
||||
node.return_type = c.table.find_or_register_array(thread_ret_type)
|
||||
} else {
|
||||
|
@ -103,7 +103,7 @@ fn (mut c Checker) for_in_stmt(mut node ast.ForInStmt) {
|
||||
if next_fn.params.len != 1 {
|
||||
c.error('iterator method `next()` must have 0 parameters', node.cond.pos())
|
||||
}
|
||||
mut val_type := next_fn.return_type.clear_flag(.optional)
|
||||
mut val_type := next_fn.return_type.clear_flag(.optional).clear_flag(.result)
|
||||
if node.val_is_mut {
|
||||
val_type = val_type.ref()
|
||||
}
|
||||
@ -152,7 +152,7 @@ fn (mut c Checker) for_in_stmt(mut node ast.ForInStmt) {
|
||||
if sym.kind == .string {
|
||||
value_type = ast.u8_type
|
||||
}
|
||||
if value_type == ast.void_type || typ.has_flag(.optional) {
|
||||
if value_type == ast.void_type || typ.has_flag(.optional) || typ.has_flag(.result) {
|
||||
if typ != ast.void_type {
|
||||
c.error('for in: cannot index `${c.table.type_to_str(typ)}`', node.cond.pos())
|
||||
}
|
||||
|
@ -298,7 +298,7 @@ pub fn (mut c Checker) infix_expr(mut node ast.InfixExpr) ast.Type {
|
||||
left_name := c.table.type_to_str(unwrapped_left_type)
|
||||
right_name := c.table.type_to_str(unwrapped_right_type)
|
||||
c.error('mismatched types `$left_name` and `$right_name`', left_right_pos)
|
||||
} else if promoted_type.has_flag(.optional) {
|
||||
} else if promoted_type.has_flag(.optional) || promoted_type.has_flag(.result) {
|
||||
s := c.table.type_to_str(promoted_type)
|
||||
c.error('`$node.op` cannot be used with `$s`', node.pos)
|
||||
} else if promoted_type.is_float() {
|
||||
|
@ -270,6 +270,8 @@ fn (mut c Checker) resolve_generic_interface(typ ast.Type, interface_type ast.Ty
|
||||
mut ret_typ := method.return_type
|
||||
if imethod.return_type.has_flag(.optional) {
|
||||
ret_typ = ret_typ.clear_flag(.optional)
|
||||
} else if imethod.return_type.has_flag(.result) {
|
||||
ret_typ = ret_typ.clear_flag(.result)
|
||||
}
|
||||
inferred_type = ret_typ
|
||||
} else if imret_sym.info is ast.SumType && mret_sym.info is ast.SumType {
|
||||
|
@ -1,4 +1,4 @@
|
||||
vlib/v/checker/tests/fn_arg_of_optional_err.vv:1:19: error: optional type argument is not supported currently
|
||||
vlib/v/checker/tests/fn_arg_of_optional_err.vv:1:19: error: optional or result type argument is not supported currently
|
||||
1 | fn optional_arg(x ?int) {
|
||||
| ~~~~
|
||||
2 | println('int type: $x')
|
||||
|
@ -3017,7 +3017,7 @@ fn (mut g Gen) expr(node_ ast.Expr) {
|
||||
ret_type := if node.or_block.kind == .absent {
|
||||
node.return_type
|
||||
} else {
|
||||
node.return_type.clear_flag(.optional)
|
||||
node.return_type.clear_flag(.optional).clear_flag(.result)
|
||||
}
|
||||
mut shared_styp := ''
|
||||
if g.is_shared && !ret_type.has_flag(.shared_f) && !g.inside_or_block {
|
||||
@ -4429,7 +4429,7 @@ fn (mut g Gen) return_stmt(node ast.Return) {
|
||||
}
|
||||
}
|
||||
for i, expr in node.exprs {
|
||||
g.expr_with_cast(expr, node.types[i], g.fn_decl.return_type.clear_flag(.optional))
|
||||
g.expr_with_cast(expr, node.types[i], g.fn_decl.return_type.clear_flag(.optional).clear_flag(.result))
|
||||
if i < node.exprs.len - 1 {
|
||||
g.write(', ')
|
||||
}
|
||||
@ -5389,7 +5389,7 @@ fn (mut g Gen) or_block(var_name string, or_block ast.OrExpr, return_type ast.Ty
|
||||
}
|
||||
}
|
||||
if or_block.kind == .block {
|
||||
g.or_expr_return_type = return_type.clear_flag(.optional)
|
||||
g.or_expr_return_type = return_type.clear_flag(.optional).clear_flag(.result)
|
||||
if g.inside_or_block {
|
||||
g.writeln('\terr = ${cvar_name}.err;')
|
||||
} else {
|
||||
@ -5410,7 +5410,7 @@ fn (mut g Gen) or_block(var_name string, or_block ast.OrExpr, return_type ast.Ty
|
||||
g.write('*($mr_styp*) ${cvar_name}.data = ')
|
||||
old_inside_opt_data := g.inside_opt_data
|
||||
g.inside_opt_data = true
|
||||
g.expr_with_cast(expr_stmt.expr, expr_stmt.typ, return_type.clear_flag(.optional))
|
||||
g.expr_with_cast(expr_stmt.expr, expr_stmt.typ, return_type.clear_flag(.optional).clear_flag(.result))
|
||||
g.inside_opt_data = old_inside_opt_data
|
||||
g.writeln(';')
|
||||
g.stmt_path_pos.delete_last()
|
||||
|
@ -1358,7 +1358,7 @@ fn (mut g Gen) fn_call(node ast.CallExpr) {
|
||||
g.writeln('));')
|
||||
return
|
||||
}
|
||||
if g.is_autofree && !typ.has_flag(.optional) {
|
||||
if g.is_autofree && !typ.has_flag(.optional) && !typ.has_flag(.result) {
|
||||
// Create a temporary variable so that the value can be freed
|
||||
tmp := g.new_tmp_var()
|
||||
g.write('string $tmp = ')
|
||||
@ -1499,7 +1499,8 @@ fn (mut g Gen) autofree_call_pregen(node ast.CallExpr) {
|
||||
// Create a temporary var before fn call for each argument in order to free it (only if it's a complex expression,
|
||||
// like `foo(get_string())` or `foo(a + b)`
|
||||
mut free_tmp_arg_vars := g.is_autofree && !g.is_builtin_mod && node.args.len > 0
|
||||
&& !node.args[0].typ.has_flag(.optional) // TODO copy pasta checker.v
|
||||
&& !node.args[0].typ.has_flag(.optional)
|
||||
&& !node.args[0].typ.has_flag(.result) // TODO copy pasta checker.v
|
||||
if !free_tmp_arg_vars {
|
||||
return
|
||||
}
|
||||
@ -1600,6 +1601,11 @@ fn (mut g Gen) autofree_call_postgen(node_pos int) {
|
||||
// TODO: free optionals
|
||||
continue
|
||||
}
|
||||
is_result := obj.typ.has_flag(.result)
|
||||
if is_result {
|
||||
// TODO: free results
|
||||
continue
|
||||
}
|
||||
if !obj.is_autofree_tmp {
|
||||
continue
|
||||
}
|
||||
|
@ -65,7 +65,7 @@ fn (mut g Gen) need_tmp_var_in_expr(expr ast.Expr) bool {
|
||||
ast.ConcatExpr {
|
||||
for val in expr.vals {
|
||||
if val is ast.CallExpr {
|
||||
if val.return_type.has_flag(.optional) {
|
||||
if val.return_type.has_flag(.optional) || val.return_type.has_flag(.result) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
@ -181,7 +181,7 @@ fn (mut g Gen) struct_init(node ast.StructInit) {
|
||||
continue
|
||||
}
|
||||
field_name := c_name(field.name)
|
||||
if field.typ.has_flag(.optional) {
|
||||
if field.typ.has_flag(.optional) || field.typ.has_flag(.result) {
|
||||
g.write('.$field_name = {EMPTY_STRUCT_INITIALIZATION},')
|
||||
initialized = true
|
||||
continue
|
||||
|
Loading…
Reference in New Issue
Block a user