From b1ffa4ecf1067b6d5b2f78fa4c89d67c57e43694 Mon Sep 17 00:00:00 2001 From: yuyi Date: Mon, 16 Sep 2024 13:06:41 +0800 Subject: [PATCH 1/2] ast, parser, checker: check struct implements non interface type (fix #22200) (#22218) --- vlib/v/checker/struct.v | 2 ++ vlib/v/checker/tests/struct_implements_non_interface_err.out | 5 +++++ vlib/v/checker/tests/struct_implements_non_interface_err.vv | 5 +++++ 3 files changed, 12 insertions(+) create mode 100644 vlib/v/checker/tests/struct_implements_non_interface_err.out create mode 100644 vlib/v/checker/tests/struct_implements_non_interface_err.vv diff --git a/vlib/v/checker/struct.v b/vlib/v/checker/struct.v index d1ca514c0e2cfb..4c12e7816d6e54 100644 --- a/vlib/v/checker/struct.v +++ b/vlib/v/checker/struct.v @@ -350,6 +350,8 @@ fn (mut c Checker) struct_decl(mut node ast.StructDecl) { } } } + } else { + c.error('`${t_sym.name}` is not an interface type', t.pos) } c.type_implements(struct_type, t.typ, node.pos) } diff --git a/vlib/v/checker/tests/struct_implements_non_interface_err.out b/vlib/v/checker/tests/struct_implements_non_interface_err.out new file mode 100644 index 00000000000000..d0f5f88c590120 --- /dev/null +++ b/vlib/v/checker/tests/struct_implements_non_interface_err.out @@ -0,0 +1,5 @@ +vlib/v/checker/tests/struct_implements_non_interface_err.vv:1:26: error: `Abcde` is not an interface type + 1 | struct Walker implements Abcde { + | ~~~~~ + 2 | aaa string + 3 | } diff --git a/vlib/v/checker/tests/struct_implements_non_interface_err.vv b/vlib/v/checker/tests/struct_implements_non_interface_err.vv new file mode 100644 index 00000000000000..55d570d5e56608 --- /dev/null +++ b/vlib/v/checker/tests/struct_implements_non_interface_err.vv @@ -0,0 +1,5 @@ +struct Walker implements Abcde { + aaa string +} + +fn main() {} From 0fb95a8ff871033b5af6072ce374b85ba2a540ed Mon Sep 17 00:00:00 2001 From: Swastik Baranwal Date: Mon, 16 Sep 2024 10:46:39 +0530 Subject: [PATCH 2/2] checker: suggest using the `@[_allow_multiple_values]` attribute, when declaring enums that have duplicate values (#22224) --- doc/docs.md | 34 +++++++++++++++++++ vlib/v/checker/checker.v | 3 ++ .../tests/enum_field_value_duplicate_a.out | 2 ++ .../tests/enum_field_value_duplicate_b.out | 1 + .../tests/enum_field_value_duplicate_c.out | 1 + .../tests/enum_field_value_duplicate_d.out | 1 + .../tests/enum_field_value_duplicate_e.out | 1 + 7 files changed, 43 insertions(+) diff --git a/doc/docs.md b/doc/docs.md index 454735e36878ad..f98c800683af72 100644 --- a/doc/docs.md +++ b/doc/docs.md @@ -5632,6 +5632,40 @@ fn main() { } ``` +```v +// @[_allow_multiple_values] allows an enum to have multiple duplicate values. +// Use it carefully, only when you really need it. + +@[_allow_multiple_values] +enum ButtonStyle { + primary = 1 + secondary = 2 + success = 3 + + blurple = 1 + grey = 2 + gray = 2 + green = 3 +} + +fn main() { + assert int(ButtonStyle.primary) == 1 + assert int(ButtonStyle.blurple) == 1 + + assert int(ButtonStyle.secondary) == 2 + assert int(ButtonStyle.gray) == 2 + assert int(ButtonStyle.grey) == 2 + + assert int(ButtonStyle.success) == 3 + assert int(ButtonStyle.green) == 3 + + assert ButtonStyle.primary == ButtonStyle.blurple + assert ButtonStyle.secondary == ButtonStyle.grey + assert ButtonStyle.secondary == ButtonStyle.gray + assert ButtonStyle.success == ButtonStyle.green +} +``` + Struct field deprecations: ```v oksyntax diff --git a/vlib/v/checker/checker.v b/vlib/v/checker/checker.v index 854aa497be07fb..a15bfe35abfee5 100644 --- a/vlib/v/checker/checker.v +++ b/vlib/v/checker/checker.v @@ -1975,6 +1975,7 @@ fn (mut c Checker) enum_decl(mut node ast.EnumDecl) { field.pos) } else if !c.pref.translated && !c.file.is_translated && !node.is_multi_allowed && ilast + 1 in iseen { + c.add_error_detail('use `@[_allow_multiple_values]` attribute to allow multiple enum values. Use only when it is needed') c.error('enum value `${ilast + 1}` already exists', field.pos) } iseen << ilast + 1 @@ -1989,6 +1990,7 @@ fn (mut c Checker) enum_decl(mut node ast.EnumDecl) { field.pos) } else if !c.pref.translated && !c.file.is_translated && !node.is_multi_allowed && ulast + 1 in useen { + c.add_error_detail('use `@[_allow_multiple_values]` attribute to allow multiple enum values. Use only when it is needed') c.error('enum value `${ulast + 1}` already exists', field.pos) } useen << ulast + 1 @@ -2038,6 +2040,7 @@ fn (mut c Checker) check_enum_field_integer_literal(expr ast.IntegerLiteral, is_ } if !overflows && !c.pref.translated && !c.file.is_translated && !is_multi_allowed { if (is_signed && ival in iseen) || (!is_signed && uval in useen) { + c.add_error_detail('use `@[_allow_multiple_values]` attribute to allow multiple enum values. Use only when it is needed') c.error('enum value `${expr.val}` already exists', pos) } } diff --git a/vlib/v/checker/tests/enum_field_value_duplicate_a.out b/vlib/v/checker/tests/enum_field_value_duplicate_a.out index ce72e698673eb7..5d8651cede64da 100644 --- a/vlib/v/checker/tests/enum_field_value_duplicate_a.out +++ b/vlib/v/checker/tests/enum_field_value_duplicate_a.out @@ -5,9 +5,11 @@ vlib/v/checker/tests/enum_field_value_duplicate_a.vv:3:10: error: enum value `0` | ^ 4 | blue = 1 5 | alpha = 1 +Details: use `@[_allow_multiple_values]` attribute to allow multiple enum values. Use only when it is needed vlib/v/checker/tests/enum_field_value_duplicate_a.vv:5:10: error: enum value `1` already exists 3 | green = 0 4 | blue = 1 5 | alpha = 1 | ^ 6 | } +Details: use `@[_allow_multiple_values]` attribute to allow multiple enum values. Use only when it is needed diff --git a/vlib/v/checker/tests/enum_field_value_duplicate_b.out b/vlib/v/checker/tests/enum_field_value_duplicate_b.out index c1a9ae2ab8cb68..c9e20ab46b82cc 100644 --- a/vlib/v/checker/tests/enum_field_value_duplicate_b.out +++ b/vlib/v/checker/tests/enum_field_value_duplicate_b.out @@ -4,3 +4,4 @@ vlib/v/checker/tests/enum_field_value_duplicate_b.vv:4:2: error: enum value `0` 4 | blue // -1 + 1 = 0 | ~~~~ 5 | } +Details: use `@[_allow_multiple_values]` attribute to allow multiple enum values. Use only when it is needed diff --git a/vlib/v/checker/tests/enum_field_value_duplicate_c.out b/vlib/v/checker/tests/enum_field_value_duplicate_c.out index 65bbc0b2cf3a60..27b908dc0ca818 100644 --- a/vlib/v/checker/tests/enum_field_value_duplicate_c.out +++ b/vlib/v/checker/tests/enum_field_value_duplicate_c.out @@ -5,3 +5,4 @@ vlib/v/checker/tests/enum_field_value_duplicate_c.vv:6:12: error: enum value `1` | ~~~~~~~~ 7 | all = 0xFFFFFFFF 8 | } +Details: use `@[_allow_multiple_values]` attribute to allow multiple enum values. Use only when it is needed diff --git a/vlib/v/checker/tests/enum_field_value_duplicate_d.out b/vlib/v/checker/tests/enum_field_value_duplicate_d.out index b4350c326e08a8..b8b1071ce1770d 100644 --- a/vlib/v/checker/tests/enum_field_value_duplicate_d.out +++ b/vlib/v/checker/tests/enum_field_value_duplicate_d.out @@ -5,3 +5,4 @@ vlib/v/checker/tests/enum_field_value_duplicate_d.vv:6:6: error: enum value `1` | ~~~ 7 | } 8 | +Details: use `@[_allow_multiple_values]` attribute to allow multiple enum values. Use only when it is needed diff --git a/vlib/v/checker/tests/enum_field_value_duplicate_e.out b/vlib/v/checker/tests/enum_field_value_duplicate_e.out index 93314f28d6b647..4e9db5ec0918ac 100644 --- a/vlib/v/checker/tests/enum_field_value_duplicate_e.out +++ b/vlib/v/checker/tests/enum_field_value_duplicate_e.out @@ -5,3 +5,4 @@ vlib/v/checker/tests/enum_field_value_duplicate_e.vv:4:6: error: enum value `2` | ~~~ 5 | } 6 | +Details: use `@[_allow_multiple_values]` attribute to allow multiple enum values. Use only when it is needed