Skip to content

Commit d44d9fa

Browse files
authored
checker,cgen: add T.key_type, typeof(expr).key_type, T.value_type, typeof(expr).value_type, T.element_type, typeof(expr).element_type for getting Map[K]V and []T types (fix #23914) (#23962)
1 parent a959501 commit d44d9fa

File tree

4 files changed

+48
-3
lines changed

4 files changed

+48
-3
lines changed

vlib/v/checker/checker.v

+2-1
Original file line numberDiff line numberDiff line change
@@ -1639,7 +1639,8 @@ fn (mut c Checker) selector_expr(mut node ast.SelectorExpr) ast.Type {
16391639
else {
16401640
if node.field_name == 'name' {
16411641
return ast.string_type
1642-
} else if node.field_name in ['idx', 'unaliased_typ'] {
1642+
} else if node.field_name in ['idx', 'unaliased_typ', 'key_type', 'value_type',
1643+
'element_type'] {
16431644
return ast.int_type
16441645
} else if node.field_name == 'indirections' {
16451646
return ast.int_type

vlib/v/gen/c/cgen.v

+8-1
Original file line numberDiff line numberDiff line change
@@ -3974,7 +3974,7 @@ fn (mut g Gen) selector_expr(node ast.SelectorExpr) {
39743974
g.type_name(name_type)
39753975
return
39763976
} else if node.field_name in ['idx', 'unaliased_typ'] {
3977-
// `typeof(expr).idx`, // `typeof(expr).unalised_typ`
3977+
// `T.idx`, `T.unaliased_typ`, `typeof(expr).idx`, `typeof(expr).unalised_typ`
39783978
mut name_type := node.name_type
39793979
if node.expr is ast.TypeOf {
39803980
name_type = g.type_resolver.typeof_field_type(g.type_resolver.typeof_type(node.expr.expr,
@@ -3984,6 +3984,13 @@ fn (mut g Gen) selector_expr(node ast.SelectorExpr) {
39843984
g.write(int(g.unwrap_generic(name_type)).str())
39853985
}
39863986
return
3987+
} else if node.field_name in ['key_type', 'value_type', 'element_type'] {
3988+
// `T.<field_name>`, `typeof(expr).<field_name>`
3989+
mut name_type := node.name_type
3990+
name_type = g.type_resolver.typeof_field_type(g.type_resolver.typeof_type(node.expr,
3991+
name_type), node.field_name)
3992+
g.write(int(name_type).str())
3993+
return
39873994
} else if node.field_name == 'indirections' {
39883995
mut name_type := node.name_type
39893996
if node.expr is ast.TypeOf {
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
fn t[T](a T) string {
2+
$if a is $map {
3+
mut s := ''
4+
s += '${typeof[T]().name}\n'
5+
s += '${T.key_type == typeof[u8]().idx} | ${typeof(T.key_type).name} | ${typeof[T]().key_type == typeof[u8]().idx} | ${typeof(typeof[T]().key_type).name}\n'
6+
s += '${T.value_type == typeof[string]().idx} | ${typeof(T.value_type).name} | ${typeof[T]().value_type == typeof[string]().idx} | ${typeof(typeof[T]().value_type).name}\n'
7+
s += '${T.idx == typeof[T]().idx} | ${typeof(T.idx).name} | ${typeof(typeof[T]().idx).name}'
8+
return s
9+
} $else $if a is $array {
10+
return '${typeof[T]().name} >> ${T.element_type == typeof[rune]().idx} | ${typeof(T.element_type).name} | ${typeof[T]().element_type == typeof[rune]().idx} | ${typeof(typeof[T]().element_type).name}'
11+
}
12+
return ''
13+
}
14+
15+
fn test_main() {
16+
assert t(map[u8]string{}) == 'map[u8]string\ntrue | u8 | true | u8\ntrue | string | true | string\ntrue | int | int'
17+
assert t([]rune{}) == '[]rune >> true | rune | true | rune'
18+
}

vlib/v/type_resolver/comptime_resolver.v

+20-1
Original file line numberDiff line numberDiff line change
@@ -79,11 +79,20 @@ pub fn (mut t TypeResolver) typeof_type(node ast.Expr, default_type ast.Type) as
7979
if f := t.table.find_field_with_embeds(sym, node.field_name) {
8080
return f.typ
8181
}
82+
} else if node is ast.SelectorExpr && node.name_type != 0 {
83+
if node.field_name in ['value_type', 'element_type'] {
84+
return t.table.value_type(t.resolver.unwrap_generic(node.name_type))
85+
} else if node.field_name == 'key_type' {
86+
sym := t.table.sym(t.resolver.unwrap_generic(node.name_type))
87+
if sym.info is ast.Map {
88+
return t.resolver.unwrap_generic(sym.info.key_type)
89+
}
90+
}
8291
}
8392
return default_type
8493
}
8594

86-
// typeof_field_type resolves the typeof[T]().<field_name> type
95+
// typeof_field_type resolves the T.<field_name> and typeof[T]().<field_name> type
8796
pub fn (mut t TypeResolver) typeof_field_type(typ ast.Type, field_name string) ast.Type {
8897
match field_name {
8998
'name' {
@@ -98,6 +107,16 @@ pub fn (mut t TypeResolver) typeof_field_type(typ ast.Type, field_name string) a
98107
'indirections' {
99108
return ast.int_type
100109
}
110+
'key_type' {
111+
sym := t.table.final_sym(t.resolver.unwrap_generic(typ))
112+
if sym.info is ast.Map {
113+
return t.resolver.unwrap_generic(sym.info.key_type)
114+
}
115+
return ast.no_type
116+
}
117+
'value_type', 'element_type' {
118+
return t.table.value_type(t.resolver.unwrap_generic(typ))
119+
}
101120
else {
102121
return typ
103122
}

0 commit comments

Comments
 (0)