diff --git a/vlib/v/checker/infix.v b/vlib/v/checker/infix.v index 4bd24346a9..08dbc74a53 100644 --- a/vlib/v/checker/infix.v +++ b/vlib/v/checker/infix.v @@ -598,26 +598,28 @@ pub fn (mut c Checker) infix_expr(mut node ast.InfixExpr) ast.Type { c.error('unwrapped optional cannot be used in an infix expression', opt_infix_pos) } // Dual sides check (compatibility check) - if !(c.symmetric_check(left_type, right_type) && c.symmetric_check(right_type, left_type)) - && !c.pref.translated && !c.file.is_translated && !node.left.is_auto_deref_var() - && !node.right.is_auto_deref_var() { - // for type-unresolved consts - if left_type == ast.void_type || right_type == ast.void_type { - return ast.void_type - } - if left_type.nr_muls() > 0 && right_type.is_int() { - // pointer arithmetic is fine, it is checked in other places - return return_type - } - c.error('infix expr: cannot use `$right_sym.name` (right expression) as `$left_sym.name`', - left_right_pos) - } else if left_type.is_ptr() { - for_ptr_op := c.table.type_is_for_pointer_arithmetic(left_type) - if left_sym.language == .v && !c.pref.translated && !c.inside_unsafe && !for_ptr_op - && right_type.is_int() { - sugg := ' (you can use it inside an `unsafe` block)' - c.error('infix expr: cannot use `$right_sym.name` (right expression) as `$left_sym.name` $sugg', + if node.left !is ast.ComptimeCall && node.right !is ast.ComptimeCall { + if !(c.symmetric_check(left_type, right_type) && c.symmetric_check(right_type, left_type)) + && !c.pref.translated && !c.file.is_translated && !node.left.is_auto_deref_var() + && !node.right.is_auto_deref_var() { + // for type-unresolved consts + if left_type == ast.void_type || right_type == ast.void_type { + return ast.void_type + } + if left_type.nr_muls() > 0 && right_type.is_int() { + // pointer arithmetic is fine, it is checked in other places + return return_type + } + c.error('infix expr: cannot use `$right_sym.name` (right expression) as `$left_sym.name`', left_right_pos) + } else if left_type.is_ptr() { + for_ptr_op := c.table.type_is_for_pointer_arithmetic(left_type) + if left_sym.language == .v && !c.pref.translated && !c.inside_unsafe && !for_ptr_op + && right_type.is_int() { + sugg := ' (you can use it inside an `unsafe` block)' + c.error('infix expr: cannot use `$right_sym.name` (right expression) as `$left_sym.name` $sugg', + left_right_pos) + } } } /* diff --git a/vlib/v/checker/return.v b/vlib/v/checker/return.v index 1f56108c72..550ee6fc1c 100644 --- a/vlib/v/checker/return.v +++ b/vlib/v/checker/return.v @@ -104,7 +104,7 @@ pub fn (mut c Checker) return_stmt(mut node ast.Return) { c.error('cannot use `${c.table.type_to_str(got_typ)}` as type `${c.table.type_to_str(exp_type)}` in return argument', pos) } - if !c.check_types(got_typ, exp_type) { + if node.exprs[expr_idxs[i]] !is ast.ComptimeCall && !c.check_types(got_typ, exp_type) { got_typ_sym := c.table.sym(got_typ) mut exp_typ_sym := c.table.sym(exp_type) if exp_typ_sym.kind == .interface_ { diff --git a/vlib/v/tests/comptime_call_type_test.v b/vlib/v/tests/comptime_call_type_test.v new file mode 100644 index 0000000000..9e07481aa3 --- /dev/null +++ b/vlib/v/tests/comptime_call_type_test.v @@ -0,0 +1,24 @@ +struct App {} + +fn (mut app App) method_one() int { + return 1 +} + +fn (mut app App) method_two() int { + return 2 +} + +fn reflect_call(method_name string) int { + a := App{} + $for method in App.methods { + if method.name == method_name { + return a.$method() + } + } + panic('Method not supported: $method_name') +} + +fn test_comptime_call_type() { + result := reflect_call('method_one') + assert result == 1 +}