From aba5919766355f3fb8c2131f8989577adc508594 Mon Sep 17 00:00:00 2001 From: Delyan Angelov Date: Mon, 29 Dec 2025 09:46:21 +0200 Subject: [PATCH] tests: add an enum_self_reference.vv/.out pair to check the new error messages from PR #26173 --- vlib/v/checker/checker.v | 34 +++-- vlib/v/checker/tests/enum_self_reference.out | 132 +++++++++++++++++++ vlib/v/checker/tests/enum_self_reference.vv | 52 ++++++++ 3 files changed, 210 insertions(+), 8 deletions(-) create mode 100644 vlib/v/checker/tests/enum_self_reference.out create mode 100644 vlib/v/checker/tests/enum_self_reference.vv diff --git a/vlib/v/checker/checker.v b/vlib/v/checker/checker.v index 7ed7b1e71..2d2bc4533 100644 --- a/vlib/v/checker/checker.v +++ b/vlib/v/checker/checker.v @@ -2278,12 +2278,21 @@ fn (mut c Checker) enum_decl(mut node ast.EnumDecl) { ref_idx := seen_enum_field_names[field.expr.val] // Use the value from the previously seen values and transform to IntegerLiteral if signed { - ref_val := iseen[ref_idx] + mut was_seen := true + ref_val := iseen[ref_idx] or { + was_seen = false + -1 + } if !c.pref.translated && !c.file.is_translated && !node.is_multi_allowed && ref_val 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 `${ref_val}` already exists', - field.expr.pos) + c.add_error_detail('use `@[_allow_multiple_values]` attribute to allow multiple enum values. Use only when needed') + if was_seen { + c.error('enum value `${ref_val}` already exists', + field.expr.pos) + } else { + c.error('enum value `${field.expr.val}` is not allowed to reference itself', + field.expr.pos) + } } iseen << ref_val // Transform to IntegerLiteral for code generation @@ -2292,12 +2301,21 @@ fn (mut c Checker) enum_decl(mut node ast.EnumDecl) { pos: field.expr.pos } } else { - ref_val := useen[ref_idx] + mut was_seen := true + ref_val := useen[ref_idx] or { + was_seen = false + -1 + } if !c.pref.translated && !c.file.is_translated && !node.is_multi_allowed && ref_val 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 `${ref_val}` already exists', - field.expr.pos) + c.add_error_detail('use `@[_allow_multiple_values]` attribute to allow multiple enum values. Use only when needed') + if was_seen { + c.error('enum value `${ref_val}` already exists', + field.expr.pos) + } else { + c.error('enum value `${field.expr.val}` is not allowed to reference itself', + field.expr.pos) + } } useen << ref_val // Transform to IntegerLiteral for code generation diff --git a/vlib/v/checker/tests/enum_self_reference.out b/vlib/v/checker/tests/enum_self_reference.out new file mode 100644 index 000000000..d8f306007 --- /dev/null +++ b/vlib/v/checker/tests/enum_self_reference.out @@ -0,0 +1,132 @@ +vlib/v/checker/tests/enum_self_reference.vv:6:6: error: enum value `10` already exists + 4 | enum ExampleSigned as i8 { + 5 | a = a + 6 | b = a + | ^ + 7 | c = .a + 8 | c = .c +Details: use `@[_allow_multiple_values]` attribute to allow multiple enum values. Use only when it is needed +vlib/v/checker/tests/enum_self_reference.vv:7:6: error: enum value `10` already exists + 5 | a = a + 6 | b = a + 7 | c = .a + | ~~ + 8 | c = .c + 9 | d = .d +Details: use `@[_allow_multiple_values]` attribute to allow multiple enum values. Use only when needed +vlib/v/checker/tests/enum_self_reference.vv:8:2: error: duplicate enum field name `c` + 6 | b = a + 7 | c = .a + 8 | c = .c + | ^ + 9 | d = .d + 10 | } +vlib/v/checker/tests/enum_self_reference.vv:9:6: error: enum value `d` is not allowed to reference itself + 7 | c = .a + 8 | c = .c + 9 | d = .d + | ~~ + 10 | } + 11 | +Details: use `@[_allow_multiple_values]` attribute to allow multiple enum values. Use only when needed +vlib/v/checker/tests/enum_self_reference.vv:14:6: error: enum value `10` already exists + 12 | enum ExampleUnSigned as u8 { + 13 | a = a + 14 | b = a + | ^ + 15 | c = .a + 16 | c = .c +Details: use `@[_allow_multiple_values]` attribute to allow multiple enum values. Use only when it is needed +vlib/v/checker/tests/enum_self_reference.vv:15:6: error: enum value `10` already exists + 13 | a = a + 14 | b = a + 15 | c = .a + | ~~ + 16 | c = .c + 17 | d = .d +Details: use `@[_allow_multiple_values]` attribute to allow multiple enum values. Use only when needed +vlib/v/checker/tests/enum_self_reference.vv:16:2: error: duplicate enum field name `c` + 14 | b = a + 15 | c = .a + 16 | c = .c + | ^ + 17 | d = .d + 18 | } +vlib/v/checker/tests/enum_self_reference.vv:17:6: error: enum value `d` is not allowed to reference itself + 15 | c = .a + 16 | c = .c + 17 | d = .d + | ~~ + 18 | } + 19 | +Details: use `@[_allow_multiple_values]` attribute to allow multiple enum values. Use only when needed +vlib/v/checker/tests/enum_self_reference.vv:24:10: error: `AllowedExampleSigned.z` should be declared before using it + 22 | a = a + 23 | b = a + 24 | c = .z + | ~~ + 25 | c = .a + 26 | c = .c +vlib/v/checker/tests/enum_self_reference.vv:25:2: error: duplicate enum field name `c` + 23 | b = a + 24 | c = .z + 25 | c = .a + | ^ + 26 | c = .c + 27 | d = .d +vlib/v/checker/tests/enum_self_reference.vv:26:2: error: duplicate enum field name `c` + 24 | c = .z + 25 | c = .a + 26 | c = .c + | ^ + 27 | d = .d + 28 | prev1 = .a +vlib/v/checker/tests/enum_self_reference.vv:30:10: error: `AllowedExampleSigned.rec2` should be declared before using it + 28 | prev1 = .a + 29 | prev2 = .c + 30 | rec1 = .rec2 + | ~~~~~ + 31 | rec2 = .rec1 + 32 | a = 2 +vlib/v/checker/tests/enum_self_reference.vv:32:2: error: duplicate enum field name `a` + 30 | rec1 = .rec2 + 31 | rec2 = .rec1 + 32 | a = 2 + | ^ + 33 | z = 5 + 34 | w = .w +vlib/v/checker/tests/enum_self_reference.vv:41:10: error: `AllowedExampleUnSigned.z` should be declared before using it + 39 | a = a + 40 | b = a + 41 | c = .z + | ~~ + 42 | c = .a + 43 | c = .c +vlib/v/checker/tests/enum_self_reference.vv:42:2: error: duplicate enum field name `c` + 40 | b = a + 41 | c = .z + 42 | c = .a + | ^ + 43 | c = .c + 44 | d = .d +vlib/v/checker/tests/enum_self_reference.vv:43:2: error: duplicate enum field name `c` + 41 | c = .z + 42 | c = .a + 43 | c = .c + | ^ + 44 | d = .d + 45 | prev1 = .a +vlib/v/checker/tests/enum_self_reference.vv:47:10: error: `AllowedExampleUnSigned.rec2` should be declared before using it + 45 | prev1 = .a + 46 | prev2 = .c + 47 | rec1 = .rec2 + | ~~~~~ + 48 | rec2 = .rec1 + 49 | a = 2 +vlib/v/checker/tests/enum_self_reference.vv:49:2: error: duplicate enum field name `a` + 47 | rec1 = .rec2 + 48 | rec2 = .rec1 + 49 | a = 2 + | ^ + 50 | z = 5 + 51 | w = .w diff --git a/vlib/v/checker/tests/enum_self_reference.vv b/vlib/v/checker/tests/enum_self_reference.vv new file mode 100644 index 000000000..1ce7483fb --- /dev/null +++ b/vlib/v/checker/tests/enum_self_reference.vv @@ -0,0 +1,52 @@ +const a = 10 +const b = 20 + +enum ExampleSigned as i8 { + a = a + b = a + c = .a + c = .c + d = .d +} + +enum ExampleUnSigned as u8 { + a = a + b = a + c = .a + c = .c + d = .d +} + +@[_allow_multiple_values] +enum AllowedExampleSigned as i8 { + a = a + b = a + c = .z + c = .a + c = .c + d = .d + prev1 = .a + prev2 = .c + rec1 = .rec2 + rec2 = .rec1 + a = 2 + z = 5 + w = .w +} + +@[_allow_multiple_values] +enum AllowedExampleUnSigned as u8 { + a = a + b = a + c = .z + c = .a + c = .c + d = .d + prev1 = .a + prev2 = .c + rec1 = .rec2 + rec2 = .rec1 + a = 2 + z = 5 + w = .w +} -- 2.39.5