cgen, comptime: fix codegen for generic selector (fix #23274) (#23285)

This commit is contained in:
Felipe Pena 2024-12-27 17:18:26 -03:00 committed by GitHub
parent 6025893768
commit 83742f99d3
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 52 additions and 6 deletions

View File

@ -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 {

View File

@ -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
}
@ -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
}

View File

@ -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)
@ -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() {

View File

@ -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] == `_` {

View File

@ -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 {

View File

@ -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)
}