1
0
mirror of https://github.com/vlang/v.git synced 2023-08-10 21:13:21 +03:00

checker: fix the type of ComptimeCall (fixes #14996) (#15013)

This commit is contained in:
shove 2022-07-12 01:08:01 +08:00 committed by GitHub
parent 398bd2280d
commit 032cb3f115
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 46 additions and 20 deletions

View File

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

View File

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

View File

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