diff --git a/vlib/v/gen/c/assign.v b/vlib/v/gen/c/assign.v index 2c7c4047ddfa91..6508f6a034ec63 100644 --- a/vlib/v/gen/c/assign.v +++ b/vlib/v/gen/c/assign.v @@ -376,7 +376,9 @@ fn (mut g Gen) assign_stmt(node_ ast.AssignStmt) { } } else if val is ast.InfixExpr && val.op in [.plus, .minus, .mul, .div, .mod] && val.left_ct_expr { - ctyp := g.unwrap_generic(g.type_resolver.get_type(val.left)) + ctyp := g.type_resolver.promote_type(g.unwrap_generic(g.type_resolver.get_type(val.left)), + g.unwrap_generic(g.type_resolver.get_type_or_default(val.right, + val.right_type))) if ctyp != ast.void_type { ct_type_var := g.comptime.get_ct_type_var(val.left) if ct_type_var in [.key_var, .value_var] { diff --git a/vlib/v/tests/generics/generic_selector_infix_test.v b/vlib/v/tests/generics/generic_selector_infix_test.v new file mode 100644 index 00000000000000..b95d0e56cf391c --- /dev/null +++ b/vlib/v/tests/generics/generic_selector_infix_test.v @@ -0,0 +1,19 @@ +fn lerp[T](x T) T { + return x +} + +struct Foo[T] { +mut: + value T +} + +fn (mut t Foo[T]) r[T](dt f64) { + mut value := t.value + dt + lerp(value) +} + +fn test_main() { + mut t2 := Foo[f32]{} + t2.r(2.1) + assert true +} diff --git a/vlib/v/type_resolver/type_resolver.v b/vlib/v/type_resolver/type_resolver.v index edcd34b40832e7..bc8c3f84b089e7 100644 --- a/vlib/v/type_resolver/type_resolver.v +++ b/vlib/v/type_resolver/type_resolver.v @@ -89,6 +89,14 @@ fn (t &TypeResolver) error(s string, pos token.Pos) { exit(1) } +// promote_type resolves the final type of different generic/comptime operand types +pub fn (t &TypeResolver) promote_type(left_type ast.Type, right_type ast.Type) ast.Type { + if left_type == ast.f32_type && right_type == ast.f64_type { + return right_type + } + return left_type +} + // get_type_or_default retries the comptime value if the AST node is related to comptime otherwise default_typ is returned @[inline] pub fn (mut t TypeResolver) get_type_or_default(node ast.Expr, default_typ ast.Type) ast.Type {