From 726a6821417698218b17d3e37ced80eb551a0581 Mon Sep 17 00:00:00 2001 From: Felipe Pena Date: Mon, 21 Oct 2024 06:33:19 -0300 Subject: [PATCH] checker: fix `T.unaliased_typ` if branch evaluation (fix #22587) (#22598) --- vlib/v/checker/comptime.v | 28 ++++++--- .../comptime/comptime_unaliased_typ_test.v | 63 +++++++++++++++++++ 2 files changed, 83 insertions(+), 8 deletions(-) create mode 100644 vlib/v/tests/comptime/comptime_unaliased_typ_test.v diff --git a/vlib/v/checker/comptime.v b/vlib/v/checker/comptime.v index fdd9cc772..cbbccb886 100644 --- a/vlib/v/checker/comptime.v +++ b/vlib/v/checker/comptime.v @@ -787,14 +787,26 @@ fn (mut c Checker) comptime_if_cond(mut cond ast.Expr, pos token.Pos) ComptimeBr } else if cond.left in [ast.Ident, ast.SelectorExpr, ast.TypeNode] { // `$if method.type is string` c.expr(mut cond.left) - if cond.left is ast.SelectorExpr - && c.comptime.is_comptime_selector_type(cond.left) - && mut cond.right is ast.ComptimeType { - checked_type := c.comptime.get_comptime_var_type(cond.left) - return if c.comptime.is_comptime_type(checked_type, cond.right) { - .eval - } else { - .skip + if mut cond.left is ast.SelectorExpr && cond.right is ast.ComptimeType { + comptime_type := cond.right as ast.ComptimeType + if c.comptime.is_comptime_selector_type(cond.left) { + checked_type := c.comptime.get_comptime_var_type(cond.left) + return if c.comptime.is_comptime_type(checked_type, comptime_type) { + .eval + } else { + .skip + } + } else if cond.left.gkind_field == .unaliased_typ + && cond.left.name_type != 0 { + // T.unaliased_typ + checked_type := c.unwrap_generic(cond.left.name_type) + return if c.comptime.is_comptime_type(c.table.unaliased_type(checked_type), + comptime_type) + { + .eval + } else { + .skip + } } } return .unknown diff --git a/vlib/v/tests/comptime/comptime_unaliased_typ_test.v b/vlib/v/tests/comptime/comptime_unaliased_typ_test.v new file mode 100644 index 000000000..c91c7414b --- /dev/null +++ b/vlib/v/tests/comptime/comptime_unaliased_typ_test.v @@ -0,0 +1,63 @@ +type StringAlias = string +type BoolAlias = bool +type IntAlias = int + +struct Decoder { + json string +} + +pub fn decode[T](val string) !T { + mut decoder := Decoder{ + json: val + } + + mut result := T{} + decoder.decode_value(mut result)! + return result +} + +fn (mut decoder Decoder) decode_value[T](mut val T) ! { + $if T.unaliased_typ is string { + } $else $if T.unaliased_typ in [$int, $float, $enum] { + bytes := unsafe { decoder.json.str.vbytes(decoder.json.len) } + unsafe { + string_buffer_to_generic_number(mut val, bytes) + } + } $else { + return error('cannot encode value with ${typeof(val).name} type') + } +} + +@[direct_array_access; unsafe] +pub fn string_buffer_to_generic_number[T](mut result T, data []u8) { + $if T is $option { + } $else $if T.unaliased_typ is string { + panic('should not happens') + } $else $if T.unaliased_typ is $int { + mut is_negative := false + for ch in data { + if ch == `-` { + is_negative = true + continue + } + digit := T(ch - `0`) + result = T(*result * 10 + digit) + } + if is_negative { + result *= -1 + } + } $else { + panic('unsupported type ${typeof[T]().name}') + } +} + +fn test_main() { + value := '1234567890123456789' + _ := decode[int](value)! + _ := decode[IntAlias](value)! + _ := decode[StringAlias]('"abcd"')! + _ := decode[int](value)! + _ := decode[string]('"abcd"')! + + assert true +} -- 2.39.5