From b97fe6831feb50fd938e056376390d545e6925db Mon Sep 17 00:00:00 2001 From: Turiiya <34311583+ttytm@users.noreply.github.com> Date: Sat, 30 Mar 2024 12:07:11 +0100 Subject: [PATCH] parser, checker: move error handling for `any` type to the checker to resolve parsing issues (#21146) --- vlib/v/checker/checker.v | 13 ++++++- vlib/v/checker/struct.v | 4 ++- vlib/v/checker/tests/any_type_err.out | 34 +++++++++++++++++++ vlib/v/checker/tests/any_type_err.vv | 17 ++++++++++ .../tests/struct_field_with_any_type_err.out | 2 +- vlib/v/parser/parse_type.v | 3 -- vlib/v/parser/tests/cast_to_any_type_err.out | 6 ---- vlib/v/parser/tests/cast_to_any_type_err.vv | 4 --- 8 files changed, 67 insertions(+), 16 deletions(-) create mode 100644 vlib/v/checker/tests/any_type_err.out create mode 100644 vlib/v/checker/tests/any_type_err.vv delete mode 100644 vlib/v/parser/tests/cast_to_any_type_err.out delete mode 100644 vlib/v/parser/tests/cast_to_any_type_err.vv diff --git a/vlib/v/checker/checker.v b/vlib/v/checker/checker.v index 89de2c63d0..93d53c4949 100644 --- a/vlib/v/checker/checker.v +++ b/vlib/v/checker/checker.v @@ -579,7 +579,9 @@ fn (mut c Checker) alias_type_decl(node ast.AliasTypeDecl) { } // The rest of the parent symbol kinds are also allowed, since they are either primitive types, // that in turn do not allow recursion, or are abstract enough so that they can not be checked at comptime: - else {} + else { + c.check_any_type(node.parent_type, parent_typ_sym, node.type_pos) + } /* .voidptr, .byteptr, .charptr {} .char, .rune, .bool {} @@ -602,6 +604,13 @@ fn (mut c Checker) check_alias_vs_element_type_of_parent(node ast.AliasTypeDecl, node.type_pos) } +fn (mut c Checker) check_any_type(typ ast.Type, sym &ast.TypeSymbol, pos token.Pos) { + if sym.kind == .any && !typ.has_flag(.generic) && sym.language != .js + && c.file.mod.name != 'builtin' { + c.error('cannot use type `any` here', pos) + } +} + fn (mut c Checker) fn_type_decl(node ast.FnTypeDecl) { c.check_valid_pascal_case(node.name, 'fn type', node.pos) typ_sym := c.table.sym(node.typ) @@ -693,6 +702,7 @@ and use a reference to the sum type instead: `var := &${node.name}(${variant_nam } } } + c.check_any_type(variant.typ, sym, variant.pos) if sym.name.trim_string_left(sym.mod + '.') == node.name { c.error('sum type cannot hold itself', variant.pos) @@ -3039,6 +3049,7 @@ fn (mut c Checker) cast_expr(mut node ast.CastExpr) ast.Type { if to_type.has_flag(.result) { c.error('casting to Result type is forbidden', node.pos) } + c.check_any_type(to_type, to_sym, node.pos) if (to_sym.is_number() && from_sym.name == 'JS.Number') || (to_sym.is_number() && from_sym.name == 'JS.BigInt') diff --git a/vlib/v/checker/struct.v b/vlib/v/checker/struct.v index 4fb7343402..62bc01e742 100644 --- a/vlib/v/checker/struct.v +++ b/vlib/v/checker/struct.v @@ -182,7 +182,9 @@ fn (mut c Checker) struct_decl(mut node ast.StructDecl) { c.warn('byte is deprecated, use u8 instead', field.type_pos) } } - else {} + else { + c.check_any_type(field.typ, sym, field.type_pos) + } } if field.has_default_expr { diff --git a/vlib/v/checker/tests/any_type_err.out b/vlib/v/checker/tests/any_type_err.out new file mode 100644 index 0000000000..aec1077ba3 --- /dev/null +++ b/vlib/v/checker/tests/any_type_err.out @@ -0,0 +1,34 @@ +vlib/v/checker/tests/any_type_err.vv:3:16: error: cannot use type `any` here + 1 | // Any types should error, while parametrically polymorphic should not. + 2 | + 3 | type AnyType = any + | ~~~ + 4 | type AnySumType = any | string + 5 | type AnyPolySumType = T | any +vlib/v/checker/tests/any_type_err.vv:4:19: error: cannot use type `any` here + 2 | + 3 | type AnyType = any + 4 | type AnySumType = any | string + | ~~~ + 5 | type AnyPolySumType = T | any + 6 | +vlib/v/checker/tests/any_type_err.vv:5:27: error: cannot use type `any` here + 3 | type AnyType = any + 4 | type AnySumType = any | string + 5 | type AnyPolySumType = T | any + | ~~~ + 6 | + 7 | type PolyType = T +vlib/v/checker/tests/any_type_err.vv:11:6: error: cannot use type `any` here + 9 | + 10 | struct AnyStructField[T] { + 11 | foo any + | ~~~ + 12 | bar T + 13 | } +vlib/v/checker/tests/any_type_err.vv:16:7: error: cannot use type `any` here + 14 | + 15 | fn any_cast() { + 16 | _ := any('foo') + | ~~~~~~~~~~ + 17 | } diff --git a/vlib/v/checker/tests/any_type_err.vv b/vlib/v/checker/tests/any_type_err.vv new file mode 100644 index 0000000000..96100be458 --- /dev/null +++ b/vlib/v/checker/tests/any_type_err.vv @@ -0,0 +1,17 @@ +// Any types should error, while parametrically polymorphic should not. + +type AnyType = any +type AnySumType = any | string +type AnyPolySumType = T | any + +type PolyType = T +type PolySumType = T | string + +struct AnyStructField[T] { + foo any + bar T +} + +fn any_cast() { + _ := any('foo') +} diff --git a/vlib/v/checker/tests/struct_field_with_any_type_err.out b/vlib/v/checker/tests/struct_field_with_any_type_err.out index 8be74160ff..2c84814726 100644 --- a/vlib/v/checker/tests/struct_field_with_any_type_err.out +++ b/vlib/v/checker/tests/struct_field_with_any_type_err.out @@ -1,4 +1,4 @@ -vlib/v/checker/tests/struct_field_with_any_type_err.vv:2:6: error: cannot use `any` type here +vlib/v/checker/tests/struct_field_with_any_type_err.vv:2:6: error: cannot use type `any` here 1 | struct My_type { 2 | fld any | ~~~ diff --git a/vlib/v/parser/parse_type.v b/vlib/v/parser/parse_type.v index 4b65b0d729..af07051d65 100644 --- a/vlib/v/parser/parse_type.v +++ b/vlib/v/parser/parse_type.v @@ -723,9 +723,6 @@ fn (mut p Parser) parse_any_type(language ast.Language, is_ptr bool, check_dot b ret = ast.int_literal_type } 'any' { - if p.file_backend_mode != .js && p.mod != 'builtin' { - p.error('cannot use `any` type here') - } ret = ast.any_type } else { diff --git a/vlib/v/parser/tests/cast_to_any_type_err.out b/vlib/v/parser/tests/cast_to_any_type_err.out deleted file mode 100644 index 59371a24a9..0000000000 --- a/vlib/v/parser/tests/cast_to_any_type_err.out +++ /dev/null @@ -1,6 +0,0 @@ -vlib/v/parser/tests/cast_to_any_type_err.vv:2:7: error: cannot use `any` type here - 1 | fn main() { - 2 | a := any(22) - | ~~~ - 3 | println(a) - 4 | } diff --git a/vlib/v/parser/tests/cast_to_any_type_err.vv b/vlib/v/parser/tests/cast_to_any_type_err.vv deleted file mode 100644 index 7bd9aad2a6..0000000000 --- a/vlib/v/parser/tests/cast_to_any_type_err.vv +++ /dev/null @@ -1,4 +0,0 @@ -fn main() { - a := any(22) - println(a) -}