From bc03ae6217562b35c956d289e78c1a0c14d3b190 Mon Sep 17 00:00:00 2001 From: Alexander Medvednikov Date: Wed, 15 Apr 2026 02:55:56 +0300 Subject: [PATCH] all: refactor typeof(expr) feature (fixes #20387) --- vlib/v/checker/checker.v | 2 +- vlib/v/gen/c/cgen.v | 5 +++-- vlib/v/gen/js/js.v | 2 +- vlib/v/tests/generics/generic_typeof_idx_test.v | 11 +++++++++++ vlib/v/tests/typeof_test.v | 9 +++++++++ vlib/v/type_resolver/comptime_resolver.v | 2 +- 6 files changed, 26 insertions(+), 5 deletions(-) diff --git a/vlib/v/checker/checker.v b/vlib/v/checker/checker.v index 10b8772b4..b2a638258 100644 --- a/vlib/v/checker/checker.v +++ b/vlib/v/checker/checker.v @@ -2711,7 +2711,7 @@ fn (mut c Checker) selector_expr(mut node ast.SelectorExpr) ast.Type { else { if node.field_name == 'name' { return ast.string_type - } else if node.field_name in ['idx', 'unaliased_typ', 'key_type', 'value_type', + } else if node.field_name in ['idx', 'typ', 'unaliased_typ', 'key_type', 'value_type', 'element_type'] { return ast.int_type } else if node.field_name == 'indirections' { diff --git a/vlib/v/gen/c/cgen.v b/vlib/v/gen/c/cgen.v index d1fb043b1..e99506e0f 100644 --- a/vlib/v/gen/c/cgen.v +++ b/vlib/v/gen/c/cgen.v @@ -5687,8 +5687,9 @@ fn (mut g Gen) selector_expr(node ast.SelectorExpr) { } g.type_name(name_type) return - } else if node.field_name in ['idx', 'unaliased_typ'] { - // `T.idx`, `T.unaliased_typ`, `typeof(expr).idx`, `typeof(expr).unalised_typ` + } else if node.field_name in ['idx', 'typ', 'unaliased_typ'] { + // `T.idx`, `T.typ`, `T.unaliased_typ`, `typeof(expr).idx`, `typeof(expr).typ`, + // `typeof(expr).unalised_typ` mut name_type := node.name_type if node.expr is ast.TypeOf { if g.cur_fn != unsafe { nil } && g.cur_concrete_types.len > 0 { diff --git a/vlib/v/gen/js/js.v b/vlib/v/gen/js/js.v index df8775aa7..fda63a852 100644 --- a/vlib/v/gen/js/js.v +++ b/vlib/v/gen/js/js.v @@ -3484,7 +3484,7 @@ fn (mut g JsGen) gen_selector_expr(it ast.SelectorExpr) { if node.field_name == 'name' { g.type_name(it.name_type) return - } else if node.field_name == 'idx' { + } else if node.field_name in ['idx', 'typ'] { g.write('new int(') g.write('${int(g.unwrap_generic(it.name_type))}') g.write(')') diff --git a/vlib/v/tests/generics/generic_typeof_idx_test.v b/vlib/v/tests/generics/generic_typeof_idx_test.v index 89c529f6d..01093202e 100644 --- a/vlib/v/tests/generics/generic_typeof_idx_test.v +++ b/vlib/v/tests/generics/generic_typeof_idx_test.v @@ -25,12 +25,23 @@ fn idx[T](a [][]T) int { return 0 } +fn typ[T](a [][]T) int { + $if typeof[T]().typ is $int { + return 1 + } $else $if typeof[T]().typ is $string { + return 2 + } + return 0 +} + fn test_main() { a := Foo{ a: [1, 2, 3] } assert idx([a.a]) == 1 assert idx([['']]) == 2 + assert typ([a.a]) == 1 + assert typ([['']]) == 2 assert unaliased_typ(1) == 1 assert unaliased_typ('') == 2 diff --git a/vlib/v/tests/typeof_test.v b/vlib/v/tests/typeof_test.v index fda9c1763..b3bd92670 100644 --- a/vlib/v/tests/typeof_test.v +++ b/vlib/v/tests/typeof_test.v @@ -202,3 +202,12 @@ fn test_variadic_type() { assert variadic_bool(true, false) == '...bool' assert variadic_f64(3.1, 3.2) == '...f64' } + +fn test_typeof_typ_field() { + a := 123 + b := &a + assert typeof(a).typ == typeof(a).idx + assert typeof(a).typ == typeof[int]().idx + assert typeof(b).typ == typeof(b).idx + assert typeof[FooBar]().typ == typeof[FooBar]().idx +} diff --git a/vlib/v/type_resolver/comptime_resolver.v b/vlib/v/type_resolver/comptime_resolver.v index 3fa4261ab..54e5f052e 100644 --- a/vlib/v/type_resolver/comptime_resolver.v +++ b/vlib/v/type_resolver/comptime_resolver.v @@ -138,7 +138,7 @@ pub fn (mut t TypeResolver) typeof_field_type(typ ast.Type, field_name string) a 'name' { return ast.string_type } - 'idx' { + 'idx', 'typ' { return t.resolver.unwrap_generic(typ) } 'unaliased_typ' { -- 2.39.5