Skip to content

Commit

Permalink
cgen: fix $if typeof[T]().idx, $if typeof[T]().unaliased_typ chec…
Browse files Browse the repository at this point in the history
…king (#23665)
  • Loading branch information
felipensp authored Feb 7, 2025
1 parent 10f2fe1 commit c01855c
Show file tree
Hide file tree
Showing 4 changed files with 69 additions and 12 deletions.
19 changes: 7 additions & 12 deletions vlib/v/gen/c/cgen.v
Original file line number Diff line number Diff line change
Expand Up @@ -3908,21 +3908,16 @@ fn (mut g Gen) selector_expr(node ast.SelectorExpr) {
}
g.type_name(name_type)
return
} else if node.field_name == 'idx' {
} else if node.field_name in ['idx', 'unaliased_typ'] {
// `typeof(expr).idx`, // `typeof(expr).unalised_typ`
mut name_type := node.name_type
if node.expr is ast.TypeOf {
name_type = g.type_resolver.typeof_type(node.expr.expr, name_type)
}
// `typeof(expr).idx`
g.write(int(g.unwrap_generic(name_type)).str())
return
} else if node.field_name == 'unaliased_typ' {
mut name_type := node.name_type
if node.expr is ast.TypeOf {
name_type = g.type_resolver.typeof_type(node.expr.expr, name_type)
name_type = g.type_resolver.typeof_field_type(g.type_resolver.typeof_type(node.expr.expr,
name_type), node.field_name)
g.write(int(name_type).str())
} else {
g.write(int(g.unwrap_generic(name_type)).str())
}
// `typeof(expr).unaliased_typ`
g.write(int(g.table.unaliased_type(g.unwrap_generic(name_type))).str())
return
} else if node.field_name == 'indirections' {
mut name_type := node.name_type
Expand Down
4 changes: 4 additions & 0 deletions vlib/v/gen/c/comptime.v
Original file line number Diff line number Diff line change
Expand Up @@ -455,6 +455,10 @@ fn (mut g Gen) get_expr_type(cond ast.Expr) ast.Type {
} else if cond.gkind_field == .indirections {
return ast.int_type
} else {
if cond.expr is ast.TypeOf {
return g.type_resolver.typeof_field_type(g.type_resolver.typeof_type(cond.expr.expr,
cond.name_type), cond.field_name)
}
name := '${cond.expr}.${cond.field_name}'
if name in g.type_resolver.type_map {
return g.type_resolver.get_ct_type_or_default(name, ast.void_type)
Expand Down
37 changes: 37 additions & 0 deletions vlib/v/tests/generics/generic_typeof_idx_test.v
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
type MyInt = int
type MyString = string

struct Foo {
a []int
b MyInt
c MyString
}

fn unaliased_typ[T](a T) int {
$if typeof[T]().unaliased_typ is $int {
return 1
} $else $if typeof[T]().unaliased_typ is $string {
return 2
}
return 0
}

fn idx[T](a [][]T) int {
$if typeof[T]().idx is $int {
return 1
} $else $if typeof[T]().idx is $string {
return 2
}
return 0
}

fn test_main() {
a := Foo{
a: [1, 2, 3]
}
assert idx([a.a]) == 1
assert idx([['']]) == 2

assert unaliased_typ(1) == 1
assert unaliased_typ('') == 2
}
21 changes: 21 additions & 0 deletions vlib/v/type_resolver/comptime_resolver.v
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,27 @@ pub fn (mut t TypeResolver) typeof_type(node ast.Expr, default_type ast.Type) as
return default_type
}

// typeof_field_type resolves the typeof[T]().<field_name> type
pub fn (mut t TypeResolver) typeof_field_type(typ ast.Type, field_name string) ast.Type {
match field_name {
'name' {
return ast.string_type
}
'idx' {
return t.resolver.unwrap_generic(typ)
}
'unaliased_typ' {
return t.table.unaliased_type(t.resolver.unwrap_generic(typ))
}
'indirections' {
return ast.int_type
}
else {
return typ
}
}
}

// get_ct_type_var gets the comptime type of the variable (.generic_param, .key_var, etc)
@[inline]
pub fn (t &ResolverInfo) get_ct_type_var(node ast.Expr) ast.ComptimeVarKind {
Expand Down

0 comments on commit c01855c

Please sign in to comment.