Skip to content

Commit

Permalink
cgen, comptime: fix codegen for generic selector (fix #23274) (#23285)
Browse files Browse the repository at this point in the history
  • Loading branch information
felipensp authored Dec 27, 2024
1 parent 6025893 commit 83742f9
Show file tree
Hide file tree
Showing 6 changed files with 52 additions and 6 deletions.
3 changes: 2 additions & 1 deletion vlib/v/checker/str.v
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,8 @@ fn (mut c Checker) string_inter_lit(mut node ast.StringInterLiteral) ast.Type {
c.error('no known default format for type `${c.table.get_type_name(ftyp)}`',
node.fmt_poss[i])
}
} else if c.comptime.is_comptime(expr) && c.comptime.get_type(expr) != ast.void_type {
} else if c.comptime.is_comptime(expr)
&& c.comptime.get_type_or_default(expr, ast.void_type) != ast.void_type {
// still `_` placeholder for comptime variable without specifier
node.need_fmts[i] = false
} else {
Expand Down
29 changes: 29 additions & 0 deletions vlib/v/comptime/comptimeinfo.v
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,15 @@ pub fn (mut ct ComptimeInfo) is_comptime(node ast.Expr) bool {
false
}
}
ast.SelectorExpr {
return node.expr is ast.Ident && node.expr.ct_expr
}
ast.InfixExpr {
return ct.is_comptime(node.left) || ct.is_comptime(node.right)
}
ast.ParExpr {
return ct.is_comptime(node.expr)
}
else {
false
}
Expand Down Expand Up @@ -120,6 +129,26 @@ pub fn (mut ct ComptimeInfo) get_type_or_default(node ast.Expr, default_typ ast.
return if ctyp != ast.void_type { ctyp } else { default_typ }
}
}
ast.SelectorExpr {
if node.expr is ast.Ident && node.expr.ct_expr {
struct_typ := ct.resolver.unwrap_generic(ct.get_type(node.expr))
struct_sym := ct.table.final_sym(struct_typ)
// Struct[T] can have field with generic type
if struct_sym.info is ast.Struct && struct_sym.info.generic_types.len > 0 {
if field := ct.table.find_field(struct_sym, node.field_name) {
return field.typ
}
}
}
}
ast.ParExpr {
return ct.get_type_or_default(node.expr, default_typ)
}
ast.InfixExpr {
if node.op in [.plus, .minus, .mul, .div, .mod] {
return ct.get_type_or_default(node.left, default_typ)
}
}
else {
return default_typ
}
Expand Down
10 changes: 7 additions & 3 deletions vlib/v/gen/c/infix.v
Original file line number Diff line number Diff line change
Expand Up @@ -925,8 +925,8 @@ fn (mut g Gen) gen_interface_is_op(node ast.InfixExpr) {
// infix_expr_arithmetic_op generates code for `+`, `-`, `*`, `/`, and `%`
// It handles operator overloading when necessary
fn (mut g Gen) infix_expr_arithmetic_op(node ast.InfixExpr) {
left := g.unwrap(node.left_type)
right := g.unwrap(node.right_type)
left := g.unwrap(g.comptime.get_type_or_default(node.left, node.left_type))
right := g.unwrap(g.comptime.get_type_or_default(node.right, node.right_type))
if left.sym.info is ast.Struct && left.sym.info.generic_types.len > 0 {
mut method_name := left.sym.cname + '_' + util.replace_op(node.op.str())
method_name = g.generic_fn_name(left.sym.info.concrete_types, method_name)
Expand Down Expand Up @@ -1188,7 +1188,11 @@ fn (mut g Gen) gen_plain_infix_expr(node ast.InfixExpr) {
&& node.op in [.plus, .minus, .mul, .div, .mod] && !(g.pref.translated
|| g.file.is_translated)
if needs_cast {
typ_str := g.styp(node.promoted_type)
typ_str := if g.comptime.is_comptime(node.left) {
g.styp(g.comptime.get_type_or_default(node.left, node.promoted_type))
} else {
g.styp(node.promoted_type)
}
g.write('(${typ_str})(')
}
if node.left_type.is_ptr() && node.left.is_auto_deref_var() && !node.right_type.is_pointer() {
Expand Down
2 changes: 1 addition & 1 deletion vlib/v/gen/c/str_intp.v
Original file line number Diff line number Diff line change
Expand Up @@ -241,7 +241,7 @@ fn (mut g Gen) string_inter_literal(node ast.StringInterLiteral) {
mut fmts := node_.fmts.clone()
for i, mut expr in node_.exprs {
if g.comptime.is_comptime(expr) {
ctyp := g.comptime.get_type(expr)
ctyp := g.comptime.get_type_or_default(expr, node_.expr_types[i])
if ctyp != ast.void_type {
node_.expr_types[i] = ctyp
if node_.fmts[i] == `_` {
Expand Down
2 changes: 1 addition & 1 deletion vlib/v/parser/fn.v
Original file line number Diff line number Diff line change
Expand Up @@ -512,7 +512,7 @@ run them via `v file.v` instead',
pos: param.pos
is_used: is_pub || no_body || (is_method && k == 0) || p.builtin_mod
is_arg: true
ct_type_var: if (!is_method || k > 0) && param.typ.has_flag(.generic)
ct_type_var: if (!is_method || k >= 0) && param.typ.has_flag(.generic)
&& !param.typ.has_flag(.variadic) {
.generic_param
} else {
Expand Down
12 changes: 12 additions & 0 deletions vlib/v/tests/generics/generic_selector_type_test.v
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import math.vec

type UnusedType = vec.Vec3[f32]

fn (n UnusedType) unused_function() f32 {
return n.mul_scalar(2).magnitude()
}

fn test_main() {
assert vec.Vec3[f32]{0.5, 0.5, 0.5}.magnitude() == f32(0.8660254)
assert vec.Vec3[f32]{1.5, 1.5, 1.5}.magnitude() == f32(2.598076)
}

0 comments on commit 83742f9

Please sign in to comment.