Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

checker, cgen: fix comptime issues with generic type #22751

Merged
merged 8 commits into from
Nov 5, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 4 additions & 3 deletions vlib/v/checker/assign.v
Original file line number Diff line number Diff line change
Expand Up @@ -399,7 +399,7 @@ fn (mut c Checker) assign_stmt(mut node ast.AssignStmt) {
&& right.or_expr.kind == .absent {
right_obj_var := right.obj as ast.Var
if right_obj_var.ct_type_var != .no_comptime {
ctyp := c.comptime.get_comptime_var_type(right)
ctyp := c.comptime.get_type(right)
if ctyp != ast.void_type {
left.obj.ct_type_var = right_obj_var.ct_type_var
left.obj.typ = ctyp
Expand All @@ -421,11 +421,12 @@ fn (mut c Checker) assign_stmt(mut node ast.AssignStmt) {
fn_ret_type := c.resolve_return_type(right)
if fn_ret_type != ast.void_type
&& c.table.final_sym(fn_ret_type).kind != .multi_return {
c.comptime.type_map['g.${left.name}.${left.obj.pos.pos}'] = if right.or_block.kind == .absent {
felipensp marked this conversation as resolved.
Show resolved Hide resolved
var_type := if right.or_block.kind == .absent {
fn_ret_type
} else {
fn_ret_type.clear_option_and_result()
}
c.comptime.type_map['g.${left.name}.${left.obj.pos.pos}'] = var_type
}
}
}
Expand Down Expand Up @@ -505,7 +506,7 @@ fn (mut c Checker) assign_stmt(mut node ast.AssignStmt) {
}

if right is ast.Ident && c.comptime.is_comptime_var(right) {
right_type = c.comptime.get_comptime_var_type(right)
right_type = c.comptime.get_type(right)
}
}
if mut left is ast.InfixExpr {
Expand Down
4 changes: 2 additions & 2 deletions vlib/v/checker/checker.v
Original file line number Diff line number Diff line change
Expand Up @@ -2928,7 +2928,7 @@ pub fn (mut c Checker) expr(mut node ast.Expr) ast.Type {

if c.comptime.inside_comptime_for && node.expr is ast.Ident {
if c.comptime.is_comptime_var(node.expr) {
node.expr_type = c.comptime.get_comptime_var_type(node.expr as ast.Ident)
node.expr_type = c.comptime.get_type(node.expr as ast.Ident)
} else if (node.expr as ast.Ident).name in c.comptime.type_map {
node.expr_type = c.comptime.type_map[(node.expr as ast.Ident).name]
}
Expand Down Expand Up @@ -3805,7 +3805,7 @@ fn (mut c Checker) ident(mut node ast.Ident) ast.Type {
if node.kind in [.constant, .global, .variable] {
info := node.info as ast.IdentVar
typ := if c.comptime.is_comptime_var(node) {
ctype := c.comptime.get_comptime_var_type(node)
ctype := c.comptime.get_type(node)
if ctype != ast.void_type {
ctype
} else {
Expand Down
4 changes: 2 additions & 2 deletions vlib/v/checker/comptime.v
Original file line number Diff line number Diff line change
Expand Up @@ -134,7 +134,7 @@ fn (mut c Checker) comptime_call(mut node ast.ComptimeCall) ast.Type {
node.args[i].typ = c.expr(mut arg.expr)
}
c.stmts_ending_with_expression(mut node.or_block.stmts, c.expected_or_type)
return c.comptime.get_comptime_var_type(node)
return c.comptime.get_type(node)
}
if node.method_name == 'res' {
if !c.inside_defer {
Expand Down Expand Up @@ -790,7 +790,7 @@ fn (mut c Checker) comptime_if_cond(mut cond ast.Expr, pos token.Pos) ComptimeBr
if mut cond.left is ast.SelectorExpr && cond.right is ast.ComptimeType {
comptime_type := cond.right as ast.ComptimeType
if c.comptime.is_comptime_selector_type(cond.left) {
checked_type := c.comptime.get_comptime_var_type(cond.left)
checked_type := c.comptime.get_type(cond.left)
return if c.comptime.is_comptime_type(checked_type, comptime_type) {
.eval
} else {
Expand Down
15 changes: 9 additions & 6 deletions vlib/v/checker/fn.v
Original file line number Diff line number Diff line change
Expand Up @@ -1807,7 +1807,7 @@ fn (mut c Checker) resolve_comptime_args(func &ast.Fn, node_ ast.CallExpr, concr
if call_arg.expr is ast.Ident {
if call_arg.expr.obj is ast.Var {
if call_arg.expr.obj.ct_type_var !in [.generic_var, .generic_param, .no_comptime] {
mut ctyp := c.comptime.get_comptime_var_type(call_arg.expr)
mut ctyp := c.comptime.get_type(call_arg.expr)
if ctyp != ast.void_type {
arg_sym := c.table.sym(ctyp)
param_sym := c.table.final_sym(param_typ)
Expand All @@ -1830,7 +1830,7 @@ 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_param {
mut ctyp := c.comptime.get_comptime_var_type(call_arg.expr)
mut ctyp := c.comptime.get_type(call_arg.expr)
if ctyp != ast.void_type {
arg_sym := c.table.final_sym(call_arg.typ)
param_typ_sym := c.table.sym(param_typ)
Expand Down Expand Up @@ -1893,7 +1893,10 @@ fn (mut c Checker) resolve_comptime_args(func &ast.Fn, node_ ast.CallExpr, concr
}
}
} else if call_arg.expr.obj.ct_type_var == .generic_var {
mut ctyp := c.comptime.get_comptime_var_type(call_arg.expr)
mut ctyp := c.comptime.get_type(call_arg.expr)
if node_.args[i].expr.is_auto_deref_var() {
ctyp = ctyp.deref()
}
if ctyp.nr_muls() > 0 && param_typ.nr_muls() > 0 {
ctyp = ctyp.set_nr_muls(0)
}
Expand All @@ -1902,14 +1905,14 @@ fn (mut c Checker) resolve_comptime_args(func &ast.Fn, node_ ast.CallExpr, concr
}
} else if call_arg.expr is ast.PrefixExpr {
if call_arg.expr.right is ast.ComptimeSelector {
comptime_args[k] = c.comptime.get_comptime_var_type(call_arg.expr.right)
comptime_args[k] = c.comptime.get_type(call_arg.expr.right)
comptime_args[k] = comptime_args[k].deref()
if comptime_args[k].nr_muls() > 0 && param_typ.nr_muls() > 0 {
comptime_args[k] = comptime_args[k].set_nr_muls(0)
}
}
} else if call_arg.expr is ast.ComptimeSelector {
ct_value := c.comptime.get_comptime_var_type(call_arg.expr)
ct_value := c.comptime.get_type(call_arg.expr)
param_typ_sym := c.table.sym(param_typ)
if ct_value != ast.void_type {
arg_sym := c.table.final_sym(call_arg.typ)
Expand All @@ -1934,7 +1937,7 @@ fn (mut c Checker) resolve_comptime_args(func &ast.Fn, node_ ast.CallExpr, concr
}
}
} else if call_arg.expr is ast.ComptimeCall {
comptime_args[k] = c.comptime.get_comptime_var_type(call_arg.expr)
comptime_args[k] = c.comptime.get_type(call_arg.expr)
}
}
}
Expand Down
2 changes: 1 addition & 1 deletion vlib/v/checker/for.v
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ fn (mut c Checker) for_in_stmt(mut node ast.ForInStmt) {
mut is_comptime := false
if (node.cond is ast.Ident && c.comptime.is_comptime_var(node.cond))
|| node.cond is ast.ComptimeSelector {
ctyp := c.comptime.get_comptime_var_type(node.cond)
ctyp := c.comptime.get_type(node.cond)
if ctyp != ast.void_type {
is_comptime = true
typ = ctyp
Expand Down
6 changes: 3 additions & 3 deletions vlib/v/checker/if.v
Original file line number Diff line number Diff line change
Expand Up @@ -557,7 +557,7 @@ fn (mut c Checker) smartcast_if_conds(mut node ast.Expr, mut scope ast.Scope, co
c.smartcast_if_conds(mut node.right, mut scope, control_expr)
} else if node.left is ast.Ident && node.op == .ne && node.right is ast.None {
if node.left is ast.Ident && c.comptime.get_ct_type_var(node.left) == .smartcast {
node.left_type = c.comptime.get_comptime_var_type(node.left)
node.left_type = c.comptime.get_type(node.left)
c.smartcast(mut node.left, node.left_type, node.left_type.clear_flag(.option), mut
scope, true)
} else {
Expand All @@ -566,7 +566,7 @@ fn (mut c Checker) smartcast_if_conds(mut node ast.Expr, mut scope ast.Scope, co
}
} else if node.op == .key_is {
if node.left is ast.Ident && c.comptime.is_comptime_var(node.left) {
node.left_type = c.comptime.get_comptime_var_type(node.left)
node.left_type = c.comptime.get_type(node.left)
} else {
node.left_type = c.expr(mut node.left)
}
Expand Down Expand Up @@ -650,7 +650,7 @@ fn (mut c Checker) smartcast_if_conds(mut node ast.Expr, mut scope ast.Scope, co
if first_cond.left is ast.Ident && first_cond.op == .eq && first_cond.right is ast.None {
if first_cond.left is ast.Ident
&& c.comptime.get_ct_type_var(first_cond.left) == .smartcast {
first_cond.left_type = c.comptime.get_comptime_var_type(first_cond.left)
first_cond.left_type = c.comptime.get_type(first_cond.left)
c.smartcast(mut first_cond.left, first_cond.left_type, first_cond.left_type.clear_flag(.option), mut
scope, true)
} else {
Expand Down
2 changes: 1 addition & 1 deletion vlib/v/checker/postfix.v
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ fn (mut c Checker) postfix_expr(mut node ast.PostfixExpr) ast.Type {
if !(typ_sym.is_number() || ((c.inside_unsafe || c.pref.translated) && is_non_void_pointer)) {
if c.comptime.comptime_for_field_var != '' {
if c.comptime.is_comptime_var(node.expr) || node.expr is ast.ComptimeSelector {
node.typ = c.unwrap_generic(c.comptime.get_comptime_var_type(node.expr))
node.typ = c.unwrap_generic(c.comptime.get_type(node.expr))
if node.op == .question {
node.typ = node.typ.clear_flag(.option)
}
Expand Down
5 changes: 2 additions & 3 deletions vlib/v/checker/str.v
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ fn (mut c Checker) string_inter_lit(mut node ast.StringInterLiteral) ast.Type {
mut ftyp := c.expr(mut expr)
ftyp = c.check_expr_option_or_result_call(expr, ftyp)
if c.comptime.is_comptime_var(expr) {
ctyp := c.comptime.get_comptime_var_type(expr)
ctyp := c.comptime.get_type(expr)
if ctyp != ast.void_type {
ftyp = ctyp
}
Expand Down Expand Up @@ -79,8 +79,7 @@ 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_var(expr)
&& c.comptime.get_comptime_var_type(expr) != ast.void_type {
} else if c.comptime.is_comptime_var(expr) && c.comptime.get_type(expr) != ast.void_type {
// still `_` placeholder for comptime variable without specifier
node.need_fmts[i] = false
} else {
Expand Down
36 changes: 31 additions & 5 deletions vlib/v/comptime/comptimeinfo.v
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,14 @@ pub fn (mut ct ComptimeInfo) get_comptime_selector_key_type(val ast.ComptimeSele
return ''
}

// is_comptime_expr checks if the node is related to a comptime expr
@[inline]
pub fn (mut ct ComptimeInfo) is_comptime_expr(node ast.Expr) bool {
return (node is ast.Ident && ct.get_ct_type_var(node) != .no_comptime)
|| (node is ast.IndexExpr && ct.is_comptime_expr(node.left))
|| node is ast.ComptimeSelector
}

// is_comptime_var checks if the node is related to a comptime variable
@[inline]
pub fn (mut ct ComptimeInfo) is_comptime_var(node ast.Expr) bool {
Expand All @@ -45,6 +53,8 @@ pub fn (mut ct ComptimeInfo) is_comptime_variant_var(node ast.Ident) bool {
pub fn (mut ct ComptimeInfo) get_ct_type_var(node ast.Expr) ast.ComptimeVarKind {
return if node is ast.Ident && node.obj is ast.Var {
(node.obj as ast.Var).ct_type_var
} else if node is ast.IndexExpr {
return ct.get_ct_type_var(node.left)
} else {
.no_comptime
}
Expand All @@ -56,9 +66,23 @@ pub fn (mut ct ComptimeInfo) is_generic_param_var(node ast.Expr) bool {
&& (node.obj as ast.Var).ct_type_var == .generic_param
}

// get_comptime_var_type retrieves the actual type from a comptime related ast node
// get_expr_type computes the ast node type regarding its or_expr
pub fn (mut ct ComptimeInfo) get_expr_type(node ast.Expr) ast.Type {
ctyp := ct.get_type(node)
match node {
ast.Ident {
if ctyp.has_flag(.option) && node.or_expr.kind != .absent {
return ctyp.clear_flag(.option)
}
}
else {}
}
return ctyp
}

// get_type retrieves the actual type from a comptime related ast node
@[inline]
pub fn (mut ct ComptimeInfo) get_comptime_var_type(node ast.Expr) ast.Type {
pub fn (mut ct ComptimeInfo) get_type(node ast.Expr) ast.Type {
felipensp marked this conversation as resolved.
Show resolved Hide resolved
if node is ast.Ident {
if node.obj is ast.Var {
return match node.obj.ct_type_var {
Expand Down Expand Up @@ -109,6 +133,8 @@ pub fn (mut ct ComptimeInfo) get_comptime_var_type(node ast.Expr) ast.Type {
return ast.void_type
}
return f.return_type
} else if node is ast.IndexExpr && ct.is_comptime_var(node.left) {
return ct.table.value_type(ct.resolver.unwrap_generic(ct.get_type(node.left)))
}
return ast.void_type
}
Expand Down Expand Up @@ -304,16 +330,16 @@ pub fn (mut ct ComptimeInfo) unwrap_generic_expr(expr ast.Expr, default_typ ast.
}
ast.InfixExpr {
if ct.is_comptime_var(expr.left) {
return ct.resolver.unwrap_generic(ct.get_comptime_var_type(expr.left))
return ct.resolver.unwrap_generic(ct.get_type(expr.left))
}
if ct.is_comptime_var(expr.right) {
return ct.resolver.unwrap_generic(ct.get_comptime_var_type(expr.right))
return ct.resolver.unwrap_generic(ct.get_type(expr.right))
}
return default_typ
}
ast.Ident {
return if ct.is_comptime_var(expr) {
ct.resolver.unwrap_generic(ct.get_comptime_var_type(expr))
ct.resolver.unwrap_generic(ct.get_type(expr))
} else {
default_typ
}
Expand Down
2 changes: 1 addition & 1 deletion vlib/v/gen/c/array.v
Original file line number Diff line number Diff line change
Expand Up @@ -564,7 +564,7 @@ fn (mut g Gen) gen_array_map(node ast.CallExpr) {
// value.map(Type(it)) when `value` is a comptime var
if expr.expr is ast.Ident && node.left is ast.Ident
&& g.comptime.is_comptime_var(node.left) {
ctyp := g.comptime.get_comptime_var_type(node.left)
ctyp := g.comptime.get_type(node.left)
if ctyp != ast.void_type {
expr.expr_type = g.table.value_type(ctyp)
}
Expand Down
16 changes: 14 additions & 2 deletions vlib/v/gen/c/assert.v
Original file line number Diff line number Diff line change
Expand Up @@ -151,12 +151,22 @@ fn (mut g Gen) gen_assert_metainfo(node ast.AssertStmt, kind AssertMetainfoKind)
g.writeln('\t${metaname}.op = ${expr_op_str};')
g.writeln('\t${metaname}.llabel = ${expr_left_str};')
g.writeln('\t${metaname}.rlabel = ${expr_right_str};')
left_type := if g.comptime.is_comptime_expr(node.expr.left) {
g.comptime.get_type(node.expr.left)
} else {
node.expr.left_type
}
right_type := if g.comptime.is_comptime_expr(node.expr.right) {
g.comptime.get_type(node.expr.right)
} else {
node.expr.right_type
}
spytheman marked this conversation as resolved.
Show resolved Hide resolved
if kind != .pass {
g.write('\t${metaname}.lvalue = ')
g.gen_assert_single_expr(node.expr.left, node.expr.left_type)
g.gen_assert_single_expr(node.expr.left, left_type)
g.writeln(';')
g.write('\t${metaname}.rvalue = ')
g.gen_assert_single_expr(node.expr.right, node.expr.right_type)
g.gen_assert_single_expr(node.expr.right, right_type)
g.writeln(';')
}
}
Expand Down Expand Up @@ -204,6 +214,8 @@ fn (mut g Gen) gen_assert_single_expr(expr ast.Expr, typ ast.Type) {
// vlib/builtin/map_test.v (a map of &int, set to &int(0)) fails
// without special casing ast.CastExpr here
g.write(ctoslit(expr_str))
} else if expr.right is ast.Ident {
g.write(ctoslit(expr_str))
} else {
g.gen_expr_to_string(expr, typ)
}
Expand Down
2 changes: 1 addition & 1 deletion vlib/v/gen/c/assign.v
Original file line number Diff line number Diff line change
Expand Up @@ -259,7 +259,7 @@ fn (mut g Gen) assign_stmt(node_ ast.AssignStmt) {
}
if mut left.obj is ast.Var {
if val is ast.Ident && g.comptime.is_comptime_var(val) {
ctyp := g.unwrap_generic(g.comptime.get_comptime_var_type(val))
ctyp := g.unwrap_generic(g.comptime.get_type(val))
if ctyp != ast.void_type {
var_type = ctyp
val_type = var_type
Expand Down
Loading
Loading