mirror of
https://github.com/vlang/v.git
synced 2025-09-13 01:16:02 -04:00
This commit is contained in:
parent
2a3dc5c068
commit
ebfa7d86cf
@ -965,6 +965,8 @@ fn (mut c Checker) change_flags_if_comptime_expr(mut left ast.Ident, right ast.E
|
|||||||
if right_ct_var != .no_comptime {
|
if right_ct_var != .no_comptime {
|
||||||
left.obj.ct_type_var = right_ct_var
|
left.obj.ct_type_var = right_ct_var
|
||||||
}
|
}
|
||||||
|
} else if right is ast.StructInit && right.unresolved && right.typ.has_flag(.generic) {
|
||||||
|
left.obj.ct_type_var = .generic_param
|
||||||
} else if right is ast.IndexExpr && c.comptime.is_comptime(right) {
|
} else if right is ast.IndexExpr && c.comptime.is_comptime(right) {
|
||||||
right_ct_var := c.comptime.get_ct_type_var(right.left)
|
right_ct_var := c.comptime.get_ct_type_var(right.left)
|
||||||
if right_ct_var != .no_comptime {
|
if right_ct_var != .no_comptime {
|
||||||
|
@ -899,9 +899,7 @@ fn (mut c Checker) fail_if_immutable(mut expr ast.Expr) (string, token.Pos) {
|
|||||||
mut expr_left := expr.left
|
mut expr_left := expr.left
|
||||||
if mut expr.left is ast.Ident {
|
if mut expr.left is ast.Ident {
|
||||||
if mut expr.left.obj is ast.Var {
|
if mut expr.left.obj is ast.Var {
|
||||||
if expr.left.obj.ct_type_var != .generic_param {
|
c.fail_if_immutable(mut expr_left)
|
||||||
c.fail_if_immutable(mut expr_left)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return '', expr.pos
|
return '', expr.pos
|
||||||
|
@ -163,7 +163,7 @@ fn (mut g Gen) expr_with_opt(expr ast.Expr, expr_typ ast.Type, ret_typ ast.Type)
|
|||||||
}
|
}
|
||||||
g.expr(expr)
|
g.expr(expr)
|
||||||
if expr is ast.ComptimeSelector {
|
if expr is ast.ComptimeSelector {
|
||||||
return '${expr.left.str()}.${g.comptime.comptime_for_field_value.name}'
|
return g.gen_comptime_selector(expr)
|
||||||
} else {
|
} else {
|
||||||
return expr.str()
|
return expr.str()
|
||||||
}
|
}
|
||||||
|
@ -3728,7 +3728,7 @@ fn (mut g Gen) expr(node_ ast.Expr) {
|
|||||||
mut is_unwrapped := true
|
mut is_unwrapped := true
|
||||||
if mut node.expr is ast.ComptimeSelector && node.expr.left is ast.Ident {
|
if mut node.expr is ast.ComptimeSelector && node.expr.left is ast.Ident {
|
||||||
// val.$(field.name)?
|
// val.$(field.name)?
|
||||||
expr_str = '${node.expr.left.str()}.${g.comptime.comptime_for_field_value.name}'
|
expr_str = g.gen_comptime_selector(node.expr)
|
||||||
} else if mut node.expr is ast.Ident && node.expr.ct_expr {
|
} else if mut node.expr is ast.Ident && node.expr.ct_expr {
|
||||||
// val?
|
// val?
|
||||||
expr_str = node.expr.name
|
expr_str = node.expr.name
|
||||||
|
@ -39,6 +39,11 @@ fn (mut g Gen) comptime_selector(node ast.ComptimeSelector) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn (mut g Gen) gen_comptime_selector(expr ast.ComptimeSelector) string {
|
||||||
|
arrow_or_dot := if expr.left_type.is_ptr() { '->' } else { '.' }
|
||||||
|
return '${expr.left.str()}${arrow_or_dot}${g.comptime.comptime_for_field_value.name}'
|
||||||
|
}
|
||||||
|
|
||||||
fn (mut g Gen) comptime_call(mut node ast.ComptimeCall) {
|
fn (mut g Gen) comptime_call(mut node ast.ComptimeCall) {
|
||||||
if node.is_embed {
|
if node.is_embed {
|
||||||
// $embed_file('/path/to/file')
|
// $embed_file('/path/to/file')
|
||||||
|
37
vlib/v/tests/generics/generic_typeof_test.v
Normal file
37
vlib/v/tests/generics/generic_typeof_test.v
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
module main
|
||||||
|
|
||||||
|
fn decode_array[T](x []T) string {
|
||||||
|
return 'decode_array: x.typename = ${typeof(x).name}'
|
||||||
|
}
|
||||||
|
|
||||||
|
fn decode[T]() string {
|
||||||
|
x := T{0}
|
||||||
|
mut s := 'decode: x.typename = ${typeof(x).name}. '
|
||||||
|
s += decode_array(x)
|
||||||
|
return s
|
||||||
|
}
|
||||||
|
|
||||||
|
fn second[K, V](x map[K]V) string {
|
||||||
|
return 'second: x.typename = ${typeof(x).name}'
|
||||||
|
}
|
||||||
|
|
||||||
|
fn first[T]() string {
|
||||||
|
x := T{}
|
||||||
|
mut s := 'first: x.typename = ${typeof(x).name}. '
|
||||||
|
s += second(x)
|
||||||
|
return s
|
||||||
|
}
|
||||||
|
|
||||||
|
fn test_map() {
|
||||||
|
assert first[map[string]string]() == 'first: x.typename = map[string]string. second: x.typename = map[string]string'
|
||||||
|
assert first[map[string]int]() == 'first: x.typename = map[string]int. second: x.typename = map[string]int'
|
||||||
|
assert first[map[string]u8]() == 'first: x.typename = map[string]u8. second: x.typename = map[string]u8'
|
||||||
|
assert first[map[string]rune]() == 'first: x.typename = map[string]rune. second: x.typename = map[string]rune'
|
||||||
|
}
|
||||||
|
|
||||||
|
fn test_array() {
|
||||||
|
assert decode[[]u8]() == 'decode: x.typename = []u8. decode_array: x.typename = []u8'
|
||||||
|
assert decode[[]u16]() == 'decode: x.typename = []u16. decode_array: x.typename = []u16'
|
||||||
|
assert decode[[]int]() == 'decode: x.typename = []int. decode_array: x.typename = []int'
|
||||||
|
assert decode[[]rune]() == 'decode: x.typename = []rune. decode_array: x.typename = []rune'
|
||||||
|
}
|
@ -22,7 +22,7 @@ mut:
|
|||||||
|
|
||||||
struct Decoder {}
|
struct Decoder {}
|
||||||
|
|
||||||
fn (d &Decoder) decode[T](typ T) T {
|
fn (d &Decoder) decode[T](mut typ T) T {
|
||||||
$for field in T.fields {
|
$for field in T.fields {
|
||||||
$if field.is_option {
|
$if field.is_option {
|
||||||
if typ.$(field.name) != none {
|
if typ.$(field.name) != none {
|
||||||
@ -36,7 +36,7 @@ fn (d &Decoder) decode[T](typ T) T {
|
|||||||
|
|
||||||
fn test_comptime() {
|
fn test_comptime() {
|
||||||
d := Decoder{}
|
d := Decoder{}
|
||||||
result := d.decode(StructType{
|
result := d.decode(mut StructType{
|
||||||
a: 'foo'
|
a: 'foo'
|
||||||
b: 3
|
b: 3
|
||||||
})
|
})
|
||||||
|
Loading…
x
Reference in New Issue
Block a user