diff --git a/vlib/v/checker/assign.v b/vlib/v/checker/assign.v index de762f7c9b..6e98bee645 100644 --- a/vlib/v/checker/assign.v +++ b/vlib/v/checker/assign.v @@ -410,7 +410,7 @@ fn (mut c Checker) assign_stmt(mut node ast.AssignStmt) { left.obj.ct_type_var = .field_var left.obj.typ = c.comptime.comptime_for_field_type } else if mut right is ast.CallExpr { - if left.obj.ct_type_var == .no_comptime + if left.obj.ct_type_var in [.generic_var, .no_comptime] && c.table.cur_fn != unsafe { nil } && c.table.cur_fn.generic_names.len != 0 && !right.comptime_ret_val @@ -503,6 +503,10 @@ fn (mut c Checker) assign_stmt(mut node ast.AssignStmt) { if (left.is_map || left.is_farray) && left.is_setter { left.recursive_mapset_is_setter(true) } + + if right is ast.Ident && c.comptime.is_comptime_var(right) { + right_type = c.comptime.get_comptime_var_type(right) + } } if mut left is ast.InfixExpr { c.error('cannot use infix expression on the left side of `${node.op}`', diff --git a/vlib/v/checker/fn.v b/vlib/v/checker/fn.v index 7e5e21db62..b5ca4cf5f5 100644 --- a/vlib/v/checker/fn.v +++ b/vlib/v/checker/fn.v @@ -1884,6 +1884,12 @@ fn (mut c Checker) resolve_comptime_args(func &ast.Fn, node_ ast.CallExpr, concr comptime_args[k] = ctyp } } + } else if call_arg.expr.obj.ct_type_var == .generic_var { + mut ctyp := c.comptime.get_comptime_var_type(call_arg.expr) + if ctyp.nr_muls() > 0 && param_typ.nr_muls() > 0 { + ctyp = ctyp.set_nr_muls(0) + } + comptime_args[k] = ctyp } } } else if call_arg.expr is ast.PrefixExpr { diff --git a/vlib/v/tests/comptime/comptime_generic_container_test.v b/vlib/v/tests/comptime/comptime_generic_container_test.v new file mode 100644 index 0000000000..1c9b7305ed --- /dev/null +++ b/vlib/v/tests/comptime/comptime_generic_container_test.v @@ -0,0 +1,50 @@ +module main + +struct Decoder { + json string +} + +pub fn decode[T](val string) !T { + mut decoder := Decoder{ + json: val + } + + mut result := T{} + decoder.decode_value(mut &result)! + return result +} + +fn (mut decoder Decoder) decode_value[T](mut val T) ! { + $if T is $array { + mut array_element := create_array_element(val) + + decoder.decode_value(mut array_element)! + + val << array_element + } $else $if T is $map { + mut map_value := create_map_value(val) + + decoder.decode_value(mut map_value)! + + val['key'] = map_value + } +} + +fn create_array_element[T](array []T) T { + return T{} +} + +fn create_map_value[K, V](map_ map[K]V) V { + return V{} +} + +fn test_main() { + assert decode[[]int]('[1, 2, 3]')! == [0] + assert decode[[]string]('["1", "2", "3"]')! == [''] + assert decode[map[string]string]('{"val": "2"}')! == { + 'key': '' + } + assert decode[map[string]int]('{"a": 1}')! == { + 'key': 0 + } +}