Skip to content

Commit ebfa7d8

Browse files
authored
checker: fix typeof evaluation for generic reference (fix #23951) (fix #23952) (#23958)
1 parent 2a3dc5c commit ebfa7d8

File tree

7 files changed

+49
-7
lines changed

7 files changed

+49
-7
lines changed

vlib/v/checker/assign.v

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -965,6 +965,8 @@ fn (mut c Checker) change_flags_if_comptime_expr(mut left ast.Ident, right ast.E
965965
if right_ct_var != .no_comptime {
966966
left.obj.ct_type_var = right_ct_var
967967
}
968+
} else if right is ast.StructInit && right.unresolved && right.typ.has_flag(.generic) {
969+
left.obj.ct_type_var = .generic_param
968970
} else if right is ast.IndexExpr && c.comptime.is_comptime(right) {
969971
right_ct_var := c.comptime.get_ct_type_var(right.left)
970972
if right_ct_var != .no_comptime {

vlib/v/checker/checker.v

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -899,9 +899,7 @@ fn (mut c Checker) fail_if_immutable(mut expr ast.Expr) (string, token.Pos) {
899899
mut expr_left := expr.left
900900
if mut expr.left is ast.Ident {
901901
if mut expr.left.obj is ast.Var {
902-
if expr.left.obj.ct_type_var != .generic_param {
903-
c.fail_if_immutable(mut expr_left)
904-
}
902+
c.fail_if_immutable(mut expr_left)
905903
}
906904
}
907905
return '', expr.pos

vlib/v/gen/c/assign.v

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -163,7 +163,7 @@ fn (mut g Gen) expr_with_opt(expr ast.Expr, expr_typ ast.Type, ret_typ ast.Type)
163163
}
164164
g.expr(expr)
165165
if expr is ast.ComptimeSelector {
166-
return '${expr.left.str()}.${g.comptime.comptime_for_field_value.name}'
166+
return g.gen_comptime_selector(expr)
167167
} else {
168168
return expr.str()
169169
}

vlib/v/gen/c/cgen.v

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3728,7 +3728,7 @@ fn (mut g Gen) expr(node_ ast.Expr) {
37283728
mut is_unwrapped := true
37293729
if mut node.expr is ast.ComptimeSelector && node.expr.left is ast.Ident {
37303730
// val.$(field.name)?
3731-
expr_str = '${node.expr.left.str()}.${g.comptime.comptime_for_field_value.name}'
3731+
expr_str = g.gen_comptime_selector(node.expr)
37323732
} else if mut node.expr is ast.Ident && node.expr.ct_expr {
37333733
// val?
37343734
expr_str = node.expr.name

vlib/v/gen/c/comptime.v

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,11 @@ fn (mut g Gen) comptime_selector(node ast.ComptimeSelector) {
3939
}
4040
}
4141

42+
fn (mut g Gen) gen_comptime_selector(expr ast.ComptimeSelector) string {
43+
arrow_or_dot := if expr.left_type.is_ptr() { '->' } else { '.' }
44+
return '${expr.left.str()}${arrow_or_dot}${g.comptime.comptime_for_field_value.name}'
45+
}
46+
4247
fn (mut g Gen) comptime_call(mut node ast.ComptimeCall) {
4348
if node.is_embed {
4449
// $embed_file('/path/to/file')
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
module main
2+
3+
fn decode_array[T](x []T) string {
4+
return 'decode_array: x.typename = ${typeof(x).name}'
5+
}
6+
7+
fn decode[T]() string {
8+
x := T{0}
9+
mut s := 'decode: x.typename = ${typeof(x).name}. '
10+
s += decode_array(x)
11+
return s
12+
}
13+
14+
fn second[K, V](x map[K]V) string {
15+
return 'second: x.typename = ${typeof(x).name}'
16+
}
17+
18+
fn first[T]() string {
19+
x := T{}
20+
mut s := 'first: x.typename = ${typeof(x).name}. '
21+
s += second(x)
22+
return s
23+
}
24+
25+
fn test_map() {
26+
assert first[map[string]string]() == 'first: x.typename = map[string]string. second: x.typename = map[string]string'
27+
assert first[map[string]int]() == 'first: x.typename = map[string]int. second: x.typename = map[string]int'
28+
assert first[map[string]u8]() == 'first: x.typename = map[string]u8. second: x.typename = map[string]u8'
29+
assert first[map[string]rune]() == 'first: x.typename = map[string]rune. second: x.typename = map[string]rune'
30+
}
31+
32+
fn test_array() {
33+
assert decode[[]u8]() == 'decode: x.typename = []u8. decode_array: x.typename = []u8'
34+
assert decode[[]u16]() == 'decode: x.typename = []u16. decode_array: x.typename = []u16'
35+
assert decode[[]int]() == 'decode: x.typename = []int. decode_array: x.typename = []int'
36+
assert decode[[]rune]() == 'decode: x.typename = []rune. decode_array: x.typename = []rune'
37+
}

vlib/v/tests/options/option_var_test.v

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ mut:
2222

2323
struct Decoder {}
2424

25-
fn (d &Decoder) decode[T](typ T) T {
25+
fn (d &Decoder) decode[T](mut typ T) T {
2626
$for field in T.fields {
2727
$if field.is_option {
2828
if typ.$(field.name) != none {
@@ -36,7 +36,7 @@ fn (d &Decoder) decode[T](typ T) T {
3636

3737
fn test_comptime() {
3838
d := Decoder{}
39-
result := d.decode(StructType{
39+
result := d.decode(mut StructType{
4040
a: 'foo'
4141
b: 3
4242
})

0 commit comments

Comments
 (0)