From 2e9c4691583d6fbb8402b2219aad605e47986d8f Mon Sep 17 00:00:00 2001 From: Felipe Pena Date: Sun, 11 Jun 2023 13:08:45 -0300 Subject: [PATCH] checker: fix external enum value resolution, i.e. `enum { enum_value = C.VALUE }` (#18401) --- vlib/v/ast/table.v | 8 ++++++-- vlib/v/checker/comptime.v | 4 +++- vlib/v/checker/containers.v | 5 ++++- vlib/v/tests/const_resolution_test.v | 10 ++++++++++ 4 files changed, 23 insertions(+), 4 deletions(-) create mode 100644 vlib/v/tests/const_resolution_test.v diff --git a/vlib/v/ast/table.v b/vlib/v/ast/table.v index cd3a392785..12da99eb7c 100644 --- a/vlib/v/ast/table.v +++ b/vlib/v/ast/table.v @@ -372,8 +372,9 @@ pub fn (t &Table) find_method_with_embeds(sym &TypeSymbol, method_name string) ! } } -// find_enum_field_val finds the int value from the enum name and enum field -pub fn (t &Table) find_enum_field_val(name string, field_ string) i64 { +// find_enum_field_val finds the possible int value from the enum name and enum field +// (returns `none` if the value cannot be resolved at compile time) +pub fn (t &Table) find_enum_field_val(name string, field_ string) ?i64 { mut val := i64(0) enum_decl := t.enum_decls[name] mut enum_vals := []i64{} @@ -384,6 +385,7 @@ pub fn (t &Table) find_enum_field_val(name string, field_ string) i64 { val = field.expr.val.i64() break } + return none } else { if enum_vals.len > 0 { val = enum_vals.last() + 1 @@ -396,6 +398,8 @@ pub fn (t &Table) find_enum_field_val(name string, field_ string) i64 { if field.has_expr { if field.expr is IntegerLiteral { enum_vals << field.expr.val.i64() + } else { + return none } } else { if enum_vals.len > 0 { diff --git a/vlib/v/checker/comptime.v b/vlib/v/checker/comptime.v index 53938a6411..9e2068adbb 100644 --- a/vlib/v/checker/comptime.v +++ b/vlib/v/checker/comptime.v @@ -270,7 +270,9 @@ fn (mut c Checker) eval_comptime_const_expr(expr ast.Expr, nlevel int) ?ast.Comp return c.eval_comptime_const_expr(expr.expr, nlevel + 1) } ast.EnumVal { - return c.table.find_enum_field_val(expr.enum_name, expr.val) + if val := c.table.find_enum_field_val(expr.enum_name, expr.val) { + return val + } } ast.SizeOf { s, _ := c.table.type_size(expr.typ) diff --git a/vlib/v/checker/containers.v b/vlib/v/checker/containers.v index 404da53783..f91a0bd523 100644 --- a/vlib/v/checker/containers.v +++ b/vlib/v/checker/containers.v @@ -250,8 +250,11 @@ fn (mut c Checker) array_init(mut node ast.ArrayInit) ast.Type { fixed_size = init_expr.expr.val.int() } ast.EnumVal { - fixed_size = c.table.find_enum_field_val(init_expr.expr.enum_name, + if val := c.table.find_enum_field_val(init_expr.expr.enum_name, init_expr.expr.val) + { + fixed_size = val + } } else {} } diff --git a/vlib/v/tests/const_resolution_test.v b/vlib/v/tests/const_resolution_test.v new file mode 100644 index 0000000000..599546c052 --- /dev/null +++ b/vlib/v/tests/const_resolution_test.v @@ -0,0 +1,10 @@ +import gx + +const left = gx.align_left + +fn test_main() { + align := left + assert dump(align.str()) == 'left' + assert dump(gx.align_left) == gx.align_left + assert gx.align_left.str() == 'left' +}