diff --git a/vlib/v/checker/checker.v b/vlib/v/checker/checker.v index 81d7e30ba2a28a..18a7401c08cdb3 100644 --- a/vlib/v/checker/checker.v +++ b/vlib/v/checker/checker.v @@ -459,7 +459,9 @@ fn (mut c Checker) alias_type_decl(node ast.AliasTypeDecl) { if c.file.mod.name != 'builtin' { c.check_valid_pascal_case(node.name, 'type alias', node.pos) } - c.ensure_type_exists(node.parent_type, node.type_pos) or { return } + if !c.ensure_type_exists(node.parent_type, node.type_pos) { + return + } mut parent_typ_sym := c.table.sym(node.parent_type) if node.parent_type.has_flag(.result) { c.add_error_detail('Result types cannot be stored and have to be unwrapped immediately') @@ -551,13 +553,15 @@ fn (mut c Checker) fn_type_decl(node ast.FnTypeDecl) { typ_sym := c.table.sym(node.typ) fn_typ_info := typ_sym.info as ast.FnType fn_info := fn_typ_info.func - c.ensure_type_exists(fn_info.return_type, fn_info.return_type_pos) or {} + c.ensure_type_exists(fn_info.return_type, fn_info.return_type_pos) ret_sym := c.table.sym(fn_info.return_type) if ret_sym.kind == .placeholder { c.error('unknown type `${ret_sym.name}`', fn_info.return_type_pos) } for arg in fn_info.params { - c.ensure_type_exists(arg.typ, arg.type_pos) or { return } + if !c.ensure_type_exists(arg.typ, arg.type_pos) { + return + } arg_sym := c.table.sym(arg.typ) if arg_sym.kind == .placeholder { c.error('unknown type `${arg_sym.name}`', arg.type_pos) @@ -569,7 +573,7 @@ fn (mut c Checker) sum_type_decl(node ast.SumTypeDecl) { c.check_valid_pascal_case(node.name, 'sum type', node.pos) mut names_used := []string{} for variant in node.variants { - c.ensure_type_exists(variant.typ, variant.pos) or {} + c.ensure_type_exists(variant.typ, variant.pos) sym := c.table.sym(variant.typ) if variant.typ.is_ptr() { variant_name := sym.name.all_after_last('.') @@ -761,7 +765,9 @@ fn (mut c Checker) fail_if_immutable(mut expr ast.Expr) (string, token.Pos) { return '', expr.pos } // retrieve ast.Field - c.ensure_type_exists(expr.expr_type, expr.pos) or { return '', expr.pos } + if !c.ensure_type_exists(expr.expr_type, expr.pos) { + return '', expr.pos + } mut typ_sym := c.table.final_sym(c.unwrap_generic(expr.expr_type)) match typ_sym.kind { .struct_ { @@ -2492,14 +2498,14 @@ pub fn (mut c Checker) expr(mut node ast.Expr) ast.Type { expr_type_sym := c.table.sym(node.expr_type) type_sym := c.table.sym(node.typ) if expr_type_sym.kind == .sum_type { - c.ensure_type_exists(node.typ, node.pos) or {} + c.ensure_type_exists(node.typ, node.pos) if !c.table.sumtype_has_variant(node.expr_type, node.typ, true) { addr := '&'.repeat(node.typ.nr_muls()) c.error('cannot cast `${expr_type_sym.name}` to `${addr}${type_sym.name}`', node.pos) } } else if expr_type_sym.kind == .interface_ && type_sym.kind == .interface_ { - c.ensure_type_exists(node.typ, node.pos) or {} + c.ensure_type_exists(node.typ, node.pos) } else if node.expr_type.clear_flag(.option) != node.typ.clear_flag(.option) { mut s := 'cannot cast non-sum type `${expr_type_sym.name}` using `as`' if type_sym.kind == .sum_type { @@ -2865,7 +2871,7 @@ fn (mut c Checker) cast_expr(mut node ast.CastExpr) ast.Type { } if to_sym.language != .c { - c.ensure_type_exists(to_type, node.pos) or {} + c.ensure_type_exists(to_type, node.pos) if to_sym.info is ast.Alias && to_sym.info.parent_type.has_flag(.option) && !to_type.has_flag(.option) { @@ -4548,10 +4554,10 @@ fn (mut c Checker) trace(fbase string, message string) { } } -fn (mut c Checker) ensure_generic_type_specify_type_names(typ ast.Type, pos token.Pos) ? { +fn (mut c Checker) ensure_generic_type_specify_type_names(typ ast.Type, pos token.Pos) bool { if typ == 0 { c.error('unknown type', pos) - return none + return false } c.ensure_generic_type_level++ @@ -4561,7 +4567,7 @@ fn (mut c Checker) ensure_generic_type_specify_type_names(typ ast.Type, pos toke if c.ensure_generic_type_level > checker.expr_level_cutoff_limit { c.error('checker: too many levels of Checker.ensure_generic_type_specify_type_names calls: ${c.ensure_generic_type_level} ', pos) - return none + return false } sym := c.table.final_sym(typ) @@ -4574,29 +4580,42 @@ fn (mut c Checker) ensure_generic_type_specify_type_names(typ ast.Type, pos toke match sym.kind { .function { fn_info := sym.info as ast.FnType - c.ensure_generic_type_specify_type_names(fn_info.func.return_type, fn_info.func.return_type_pos)? + if !c.ensure_generic_type_specify_type_names(fn_info.func.return_type, fn_info.func.return_type_pos) { + return false + } for param in fn_info.func.params { - c.ensure_generic_type_specify_type_names(param.typ, param.type_pos)? + if !c.ensure_generic_type_specify_type_names(param.typ, param.type_pos) { + return false + } } } .array { - c.ensure_generic_type_specify_type_names((sym.info as ast.Array).elem_type, - pos)? + if !c.ensure_generic_type_specify_type_names((sym.info as ast.Array).elem_type, + pos) { + return false + } } .array_fixed { - c.ensure_generic_type_specify_type_names((sym.info as ast.ArrayFixed).elem_type, - pos)? + if !c.ensure_generic_type_specify_type_names((sym.info as ast.ArrayFixed).elem_type, + pos) { + return false + } } .map { info := sym.info as ast.Map - c.ensure_generic_type_specify_type_names(info.key_type, pos)? - c.ensure_generic_type_specify_type_names(info.value_type, pos)? + if !c.ensure_generic_type_specify_type_names(info.key_type, pos) { + return false + } + if !c.ensure_generic_type_specify_type_names(info.value_type, pos) { + return false + } } .sum_type { info := sym.info as ast.SumType if info.generic_types.len > 0 && !typ.has_flag(.generic) && info.concrete_types.len == 0 { c.error('`${sym.name}` type is generic sumtype, must specify the generic type names, e.g. ${sym.name}[T], ${sym.name}[int]', pos) + return false } } .struct_ { @@ -4604,6 +4623,7 @@ fn (mut c Checker) ensure_generic_type_specify_type_names(typ ast.Type, pos toke if info.generic_types.len > 0 && !typ.has_flag(.generic) && info.concrete_types.len == 0 { c.error('`${sym.name}` type is generic struct, must specify the generic type names, e.g. ${sym.name}[T], ${sym.name}[int]', pos) + return false } } .interface_ { @@ -4611,29 +4631,31 @@ fn (mut c Checker) ensure_generic_type_specify_type_names(typ ast.Type, pos toke if info.generic_types.len > 0 && !typ.has_flag(.generic) && info.concrete_types.len == 0 { c.error('`${sym.name}` type is generic interface, must specify the generic type names, e.g. ${sym.name}[T], ${sym.name}[int]', pos) + return false } } else {} } + return true } -fn (mut c Checker) ensure_type_exists(typ ast.Type, pos token.Pos) ? { +fn (mut c Checker) ensure_type_exists(typ ast.Type, pos token.Pos) bool { if typ == 0 { c.error('unknown type', pos) - return + return false } sym := c.table.sym(typ) if !c.is_builtin_mod && sym.kind == .struct_ && !sym.is_pub && sym.mod != c.mod { c.error('struct `${sym.name}` was declared as private to module `${sym.mod}`, so it can not be used inside module `${c.mod}`', pos) - return + return false } match sym.kind { .placeholder { if sym.language == .v && !sym.name.starts_with('C.') { c.error(util.new_suggestion(sym.name, c.table.known_type_names()).say('unknown type `${sym.name}`'), pos) - return + return false } } .int_literal, .float_literal { @@ -4646,35 +4668,50 @@ fn (mut c Checker) ensure_type_exists(typ ast.Type, pos token.Pos) ? { 'unknown type `${sym.name}`.\nDid you mean `f64`?' } c.error(msg, pos) - return + return false } } .function { fn_info := sym.info as ast.FnType - c.ensure_type_exists(fn_info.func.return_type, fn_info.func.return_type_pos)? + if !c.ensure_type_exists(fn_info.func.return_type, fn_info.func.return_type_pos) { + return false + } for param in fn_info.func.params { - c.ensure_type_exists(param.typ, param.type_pos)? + if !c.ensure_type_exists(param.typ, param.type_pos) { + return false + } } } .array { - c.ensure_type_exists((sym.info as ast.Array).elem_type, pos)? + if !c.ensure_type_exists((sym.info as ast.Array).elem_type, pos) { + return false + } } .array_fixed { - c.ensure_type_exists((sym.info as ast.ArrayFixed).elem_type, pos)? + if !c.ensure_type_exists((sym.info as ast.ArrayFixed).elem_type, pos) { + return false + } } .map { info := sym.info as ast.Map - c.ensure_type_exists(info.key_type, pos)? - c.ensure_type_exists(info.value_type, pos)? + if !c.ensure_type_exists(info.key_type, pos) { + return false + } + if !c.ensure_type_exists(info.value_type, pos) { + return false + } } .sum_type { info := sym.info as ast.SumType for concrete_typ in info.concrete_types { - c.ensure_type_exists(concrete_typ, pos)? + if !c.ensure_type_exists(concrete_typ, pos) { + return false + } } } else {} } + return true } // return true if a violation of a shared variable access rule is detected diff --git a/vlib/v/checker/containers.v b/vlib/v/checker/containers.v index b87913b7cd165c..117ffe1035de3c 100644 --- a/vlib/v/checker/containers.v +++ b/vlib/v/checker/containers.v @@ -92,7 +92,7 @@ fn (mut c Checker) array_init(mut node ast.ArrayInit) ast.Type { c.error('cannot use unwrapped Option as capacity', node.cap_expr.pos()) } } - c.ensure_type_exists(node.elem_type, node.elem_type_pos) or {} + c.ensure_type_exists(node.elem_type, node.elem_type_pos) if node.typ.has_flag(.generic) && c.table.cur_fn != unsafe { nil } && c.table.cur_fn.generic_names.len == 0 { c.error('generic struct cannot be used in non-generic function', node.pos) @@ -108,7 +108,7 @@ fn (mut c Checker) array_init(mut node ast.ArrayInit) ast.Type { if node.is_fixed { c.ensure_sumtype_array_has_default_value(node) - c.ensure_type_exists(node.elem_type, node.elem_type_pos) or {} + c.ensure_type_exists(node.elem_type, node.elem_type_pos) if node.elem_type.is_any_kind_of_pointer() && !c.inside_unsafe && !c.is_builtin_mod { c.warn('fixed arrays of references need to be initialized right away (unless inside `unsafe`)', node.pos) @@ -367,8 +367,8 @@ fn (mut c Checker) map_init(mut node ast.MapInit) ast.Type { } } } - c.ensure_type_exists(info.key_type, node.pos) or {} - c.ensure_type_exists(info.value_type, node.pos) or {} + c.ensure_type_exists(info.key_type, node.pos) + c.ensure_type_exists(info.value_type, node.pos) node.key_type = info.key_type node.value_type = info.value_type return node.typ diff --git a/vlib/v/checker/fn.v b/vlib/v/checker/fn.v index 1c1c729d327208..37ce829ea1e4ae 100644 --- a/vlib/v/checker/fn.v +++ b/vlib/v/checker/fn.v @@ -209,7 +209,9 @@ fn (mut c Checker) fn_decl(mut node ast.FnDecl) { if node.language == .v { // Make sure all types are valid for mut param in node.params { - c.ensure_type_exists(param.typ, param.type_pos) or { return } + if !c.ensure_type_exists(param.typ, param.type_pos) { + return + } if reserved_type_names_chk.matches(param.name) { c.error('invalid use of reserved type `${param.name}` as a parameter name', param.pos) @@ -277,7 +279,9 @@ fn (mut c Checker) fn_decl(mut node ast.FnDecl) { c.error('top level declaration cannot shadow builtin type', node.pos) } if node.return_type != ast.Type(0) { - c.ensure_type_exists(node.return_type, node.return_type_pos) or { return } + if !c.ensure_type_exists(node.return_type, node.return_type_pos) { + return + } if node.language == .v && node.is_method && node.name == 'str' { if node.return_type != ast.string_type { c.error('.str() methods should return `string`', node.pos) @@ -981,7 +985,7 @@ fn (mut c Checker) fn_call(mut node ast.CallExpr, mut continue_check &bool) ast. node.concrete_list_pos) } for concrete_type in node.concrete_types { - c.ensure_type_exists(concrete_type, node.concrete_list_pos) or {} + c.ensure_type_exists(concrete_type, node.concrete_list_pos) } if func.generic_names.len > 0 && node.args.len == 0 && node.concrete_types.len == 0 { c.error('no argument generic function must add concrete types, e.g. foo[int]()', @@ -1877,7 +1881,7 @@ fn (mut c Checker) method_call(mut node ast.CallExpr) ast.Type { node.concrete_list_pos) } for concrete_type in node.concrete_types { - c.ensure_type_exists(concrete_type, node.concrete_list_pos) or {} + c.ensure_type_exists(concrete_type, node.concrete_list_pos) } if method.return_type == ast.void_type && method.is_conditional && method.ctdefine_idx != ast.invalid_type_idx { diff --git a/vlib/v/checker/infix.v b/vlib/v/checker/infix.v index ff5ba245a87293..7a63782ec33b29 100644 --- a/vlib/v/checker/infix.v +++ b/vlib/v/checker/infix.v @@ -195,7 +195,7 @@ fn (mut c Checker) infix_expr(mut node ast.InfixExpr) ast.Type { } else { if mut node.right is ast.ArrayInit { for i, typ in node.right.expr_types { - c.ensure_type_exists(typ, node.right.exprs[i].pos()) or {} + c.ensure_type_exists(typ, node.right.exprs[i].pos()) } } } diff --git a/vlib/v/checker/interface.v b/vlib/v/checker/interface.v index 17303b4b1d3440..5a95bbfb8d497a 100644 --- a/vlib/v/checker/interface.v +++ b/vlib/v/checker/interface.v @@ -118,7 +118,9 @@ fn (mut c Checker) interface_decl(mut node ast.InterfaceDecl) { if node.language == .v { c.check_valid_snake_case(method.name, 'method name', method.pos) } - c.ensure_type_exists(method.return_type, method.return_type_pos) or { return } + if !c.ensure_type_exists(method.return_type, method.return_type_pos) { + continue + } if is_js { mtyp := c.table.sym(method.return_type) if !mtyp.is_js_compatible() { @@ -147,7 +149,9 @@ fn (mut c Checker) interface_decl(mut node ast.InterfaceDecl) { if param.typ.has_flag(.generic) { has_generic_types = true } - c.ensure_type_exists(param.typ, param.pos) or { return } + if !c.ensure_type_exists(param.typ, param.pos) { + continue + } if reserved_type_names_chk.matches(param.name) { c.error('invalid use of reserved type `${param.name}` as a parameter name', param.pos) @@ -190,7 +194,9 @@ fn (mut c Checker) interface_decl(mut node ast.InterfaceDecl) { if node.language == .v { c.check_valid_snake_case(field.name, 'field name', field.pos) } - c.ensure_type_exists(field.typ, field.pos) or { return } + if !c.ensure_type_exists(field.typ, field.pos) { + continue + } if field.typ.has_flag(.generic) { has_generic_types = true } diff --git a/vlib/v/checker/match.v b/vlib/v/checker/match.v index 48404b0d1cf263..f02eef7f6ac8b0 100644 --- a/vlib/v/checker/match.v +++ b/vlib/v/checker/match.v @@ -26,7 +26,9 @@ fn (mut c Checker) match_expr(mut node ast.MatchExpr) ast.Type { || (node.cond is ast.SelectorExpr && node.cond.is_mut) { c.fail_if_immutable(mut node.cond) } - c.ensure_type_exists(node.cond_type, node.pos) or { return ast.void_type } + if !c.ensure_type_exists(node.cond_type, node.pos) { + return ast.void_type + } c.check_expr_opt_call(node.cond, cond_type) cond_type_sym := c.table.sym(cond_type) cond_is_option := cond_type.has_flag(.option) diff --git a/vlib/v/checker/orm.v b/vlib/v/checker/orm.v index 2cb8aee149d857..b7c8dbd473f29d 100644 --- a/vlib/v/checker/orm.v +++ b/vlib/v/checker/orm.v @@ -26,7 +26,9 @@ fn (mut c Checker) sql_expr(mut node ast.SqlExpr) ast.Type { // To avoid panics while working with `table_expr`, // it is necessary to check if its type exists. - c.ensure_type_exists(node.table_expr.typ, node.pos) or { return ast.void_type } + if !c.ensure_type_exists(node.table_expr.typ, node.pos) { + return ast.void_type + } table_sym := c.table.sym(node.table_expr.typ) if !c.check_orm_table_expr_type(node.table_expr) { @@ -175,7 +177,9 @@ fn (mut c Checker) sql_stmt_line(mut node ast.SqlStmtLine) ast.Type { // To avoid panics while working with `table_expr`, // it is necessary to check if its type exists. - c.ensure_type_exists(node.table_expr.typ, node.pos) or { return ast.void_type } + if !c.ensure_type_exists(node.table_expr.typ, node.pos) { + return ast.void_type + } table_sym := c.table.sym(node.table_expr.typ) if !c.check_orm_table_expr_type(node.table_expr) { diff --git a/vlib/v/checker/struct.v b/vlib/v/checker/struct.v index 1dff78a2f99351..a9acd2d3db8086 100644 --- a/vlib/v/checker/struct.v +++ b/vlib/v/checker/struct.v @@ -88,8 +88,12 @@ fn (mut c Checker) struct_decl(mut node ast.StructDecl) { if field.typ.has_flag(.result) { c.error('struct field does not support storing Result', field.option_pos) } - c.ensure_type_exists(field.typ, field.type_pos) or { return } - c.ensure_generic_type_specify_type_names(field.typ, field.type_pos) or { return } + if !c.ensure_type_exists(field.typ, field.type_pos) { + continue + } + if !c.ensure_generic_type_specify_type_names(field.typ, field.type_pos) { + continue + } if field.typ.has_flag(.generic) { has_generic_types = true } @@ -366,7 +370,7 @@ fn (mut c Checker) struct_init(mut node ast.StructInit, is_field_zero_struct_ini c.table.unwrap_generic_type(node.typ, c.table.cur_fn.generic_names, c.table.cur_concrete_types) } if !is_field_zero_struct_init { - c.ensure_type_exists(node.typ, node.pos) or {} + c.ensure_type_exists(node.typ, node.pos) } type_sym := c.table.sym(node.typ) if !c.inside_unsafe && type_sym.kind == .sum_type { diff --git a/vlib/v/checker/tests/any_int_float_ban_err.out b/vlib/v/checker/tests/any_int_float_ban_err.out index 8b9eb5d3f51427..510ab1856a1c09 100644 --- a/vlib/v/checker/tests/any_int_float_ban_err.out +++ b/vlib/v/checker/tests/any_int_float_ban_err.out @@ -7,10 +7,10 @@ vlib/v/checker/tests/any_int_float_ban_err.vv:2:12: error: unknown type `int_lit 1 | type Foo = int_literal | float_literal 2 | type Fo2 = int_literal | ~~~~~~~~~~~ - 3 | + 3 | 4 | struct Int { vlib/v/checker/tests/any_int_float_ban_err.vv:5:7: error: unknown type `int_literal` - 3 | + 3 | 4 | struct Int { 5 | i int_literal | ~~~~~~~~~~~ @@ -25,21 +25,15 @@ vlib/v/checker/tests/any_int_float_ban_err.vv:6:7: error: unknown type `float_li 8 | vlib/v/checker/tests/any_int_float_ban_err.vv:9:10: error: unknown type `int_literal` 7 | } - 8 | + 8 | 9 | fn foo(i int_literal) int_literal { | ~~~~~~~~~~~ 10 | return i 11 | } vlib/v/checker/tests/any_int_float_ban_err.vv:13:11: error: unknown type `int_literal` 11 | } - 12 | + 12 | 13 | fn foo2() int_literal { | ~~~~~~~~~~~ 14 | return 1 15 | } -vlib/v/checker/tests/any_int_float_ban_err.vv:14:12: error: cannot use `int literal` as type `int_literal` in return argument - 12 | - 13 | fn foo2() int_literal { - 14 | return 1 - | ^ - 15 | } diff --git a/vlib/v/checker/tests/private_redeclaration_of_C_struct.out b/vlib/v/checker/tests/private_redeclaration_of_C_struct.out index af80feeec38e62..a270753fff663c 100644 --- a/vlib/v/checker/tests/private_redeclaration_of_C_struct.out +++ b/vlib/v/checker/tests/private_redeclaration_of_C_struct.out @@ -1,54 +1,26 @@ vlib/sokol/audio/audio.v:107:26: error: struct `C.saudio_desc` was declared as private to module `module_with_redeclaration`, so it can not be used inside module `sokol.audio` 105 | fn C.saudio_userdata() voidptr - 106 | + 106 | 107 | fn C.saudio_query_desc() C.saudio_desc | ~~~~~~~~~~~~~ - 108 | + 108 | 109 | fn C.saudio_sample_rate() int vlib/sokol/audio/audio.v:122:19: error: struct `C.saudio_desc` was declared as private to module `module_with_redeclaration`, so it can not be used inside module `sokol.audio` - 120 | + 120 | 121 | // setup - setup sokol-audio 122 | pub fn setup(desc &C.saudio_desc) { | ~~~~~~~~~~~~~~ 123 | if desc.allocator.alloc == unsafe { nil } && desc.allocator.free == unsafe { nil } { 124 | unsafe { -vlib/sokol/audio/audio.v:125:9: error: struct `C.saudio_desc` was declared as private to module `module_with_redeclaration`, so it can not be used inside module `sokol.audio` - 123 | if desc.allocator.alloc == unsafe { nil } && desc.allocator.free == unsafe { nil } { - 124 | unsafe { - 125 | desc.allocator.alloc = memory.salloc - | ~~~~~~~~~ - 126 | desc.allocator.free = memory.sfree - 127 | desc.allocator.user_data = voidptr(0x100a0d10) -vlib/sokol/audio/audio.v:126:9: error: struct `C.saudio_desc` was declared as private to module `module_with_redeclaration`, so it can not be used inside module `sokol.audio` - 124 | unsafe { - 125 | desc.allocator.alloc = memory.salloc - 126 | desc.allocator.free = memory.sfree - | ~~~~~~~~~ - 127 | desc.allocator.user_data = voidptr(0x100a0d10) - 128 | } -vlib/sokol/audio/audio.v:127:9: error: struct `C.saudio_desc` was declared as private to module `module_with_redeclaration`, so it can not be used inside module `sokol.audio` - 125 | desc.allocator.alloc = memory.salloc - 126 | desc.allocator.free = memory.sfree - 127 | desc.allocator.user_data = voidptr(0x100a0d10) - | ~~~~~~~~~ - 128 | } - 129 | } -vlib/sokol/audio/audio.v:132:9: error: struct `C.saudio_desc` was declared as private to module `module_with_redeclaration`, so it can not be used inside module `sokol.audio` - 130 | if desc.logger.log_cb == unsafe { nil } { - 131 | unsafe { - 132 | desc.logger.log_cb = memory.slog - | ~~~~~~ - 133 | } - 134 | } vlib/sokol/audio/audio.v:154:16: error: struct `C.saudio_desc` was declared as private to module `module_with_redeclaration`, so it can not be used inside module `sokol.audio` - 152 | + 152 | 153 | // query - return a copy of the original saudio_desc struct 154 | pub fn query() C.saudio_desc { | ~~~~~~~~~~~~~ 155 | return C.saudio_query_desc() 156 | } vlib/v/checker/tests/private_redeclaration_of_C_struct.vv:7:10: error: struct `C.saudio_desc` was declared as private to module `module_with_redeclaration`, so it can not be used inside module `main` - 5 | + 5 | 6 | fn main() { 7 | sd := C.saudio_desc{} | ~~~~~~~~~~~~~