Skip to content

Commit

Permalink
v: allow checking of method comptime signature with is operator (fix
Browse files Browse the repository at this point in the history
  • Loading branch information
felipensp authored Oct 17, 2024
1 parent 5e253e7 commit ae04167
Show file tree
Hide file tree
Showing 4 changed files with 65 additions and 3 deletions.
2 changes: 1 addition & 1 deletion vlib/v/ast/types.v
Original file line number Diff line number Diff line change
Expand Up @@ -1604,7 +1604,7 @@ pub fn (t &Table) fn_signature_using_aliases(func &Fn, import_aliases map[string
sb.write_string(func.name)
}
sb.write_string('(')
start := int(opts.skip_receiver)
start := int(func.is_method && opts.skip_receiver)
for i in start .. func.params.len {
if i != start {
sb.write_string(', ')
Expand Down
17 changes: 16 additions & 1 deletion vlib/v/checker/if.v
Original file line number Diff line number Diff line change
Expand Up @@ -191,7 +191,22 @@ fn (mut c Checker) if_expr(mut node ast.IfExpr) ast.Type {
checked_type = c.unwrap_generic(var.smartcasts.last())
}
}
skip_state = c.check_compatible_types(checked_type, right as ast.TypeNode)
if sym.info is ast.FnType
&& c.comptime.comptime_for_method_var == left.name {
skip_state = if c.table.fn_signature(sym.info.func,
skip_receiver: true
type_only: true
) == c.table.fn_signature(c.comptime.comptime_for_method,
skip_receiver: true
type_only: true
) {
.eval
} else {
.skip
}
} else {
skip_state = c.check_compatible_types(checked_type, right as ast.TypeNode)
}
}
}
if branch.cond.op == .not_is && skip_state != .unknown {
Expand Down
18 changes: 17 additions & 1 deletion vlib/v/gen/c/comptime.v
Original file line number Diff line number Diff line change
Expand Up @@ -574,7 +574,23 @@ fn (mut g Gen) comptime_if_cond(cond ast.Expr, pkg_exist bool) (bool, bool) {
return !is_true, true
}
}
if cond.op == .key_is {
if got_sym.info is ast.FnType && cond.left is ast.Ident
&& g.comptime.comptime_for_method_var == cond.left.name {
is_compatible := g.table.fn_signature(got_sym.info.func,
skip_receiver: true
type_only: true
) == g.table.fn_signature(g.comptime.comptime_for_method,
skip_receiver: true
type_only: true
)
if cond.op == .key_is {
g.write(int(is_compatible).str())
return is_compatible, true
} else {
g.write(int(!is_compatible).str())
return !is_compatible, true
}
} else if cond.op == .key_is {
g.write('${exp_type.idx()} == ${got_type.idx()} && ${exp_type.has_flag(.option)} == ${got_type.has_flag(.option)}')
return exp_type == got_type, true
} else {
Expand Down
31 changes: 31 additions & 0 deletions vlib/v/tests/comptime/comptime_call_is_check_test.v
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
module main

struct Struct1 {
num f64
}

pub type DoThingFunc = fn (f32) bool

fn (mut s Struct1) do_thing(a f32) bool {
return false
}

fn register[T]() {
obj := T{}
mut called := false
$for method in T.methods {
$if method !is DoThingFunc {
println('method ${method.name} is not do thing')
assert false
} $else {
println('method ${method.name} is do thing')
assert obj.$method(1.23) == false
called = true
}
}
assert called
}

fn test_main() {
register[Struct1]()
}

0 comments on commit ae04167

Please sign in to comment.