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

checker: check undefined operation of the generic infix expr (#15987)

This commit is contained in:
yuyi 2022-10-08 17:09:32 +08:00 committed by GitHub
parent 4eeb45b94e
commit 272b3cf8c3
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 48 additions and 22 deletions

View File

@ -164,19 +164,24 @@ pub fn (mut c Checker) infix_expr(mut node ast.InfixExpr) ast.Type {
}
.plus, .minus, .mul, .div, .mod, .xor, .amp, .pipe {
// binary operators that expect matching types
unwrapped_left_type := c.unwrap_generic(left_type)
left_sym = c.table.sym(unwrapped_left_type)
unwrapped_right_type := c.unwrap_generic(right_type)
right_sym = c.table.sym(unwrapped_right_type)
if right_sym.info is ast.Alias && (right_sym.info as ast.Alias).language != .c
&& c.mod == c.table.type_to_str(right_type).split('.')[0]
&& c.mod == c.table.type_to_str(unwrapped_right_type).split('.')[0]
&& c.table.sym((right_sym.info as ast.Alias).parent_type).is_primitive() {
right_sym = c.table.sym((right_sym.info as ast.Alias).parent_type)
}
if left_sym.info is ast.Alias && (left_sym.info as ast.Alias).language != .c
&& c.mod == c.table.type_to_str(left_type).split('.')[0]
&& c.mod == c.table.type_to_str(unwrapped_left_type).split('.')[0]
&& c.table.sym((left_sym.info as ast.Alias).parent_type).is_primitive() {
left_sym = c.table.sym((left_sym.info as ast.Alias).parent_type)
}
if c.pref.translated && node.op in [.plus, .minus, .mul]
&& left_type.is_any_kind_of_pointer() && right_type.is_any_kind_of_pointer() {
&& unwrapped_left_type.is_any_kind_of_pointer()
&& unwrapped_right_type.is_any_kind_of_pointer() {
return_type = left_type
} else if !c.pref.translated && left_sym.kind == .alias && left_sym.info is ast.Alias
&& !(c.table.sym((left_sym.info as ast.Alias).parent_type).is_primitive()) {
@ -193,8 +198,8 @@ pub fn (mut c Checker) infix_expr(mut node ast.InfixExpr) ast.Type {
return_type = left_type
}
} else {
left_name := c.table.type_to_str(left_type)
right_name := c.table.type_to_str(right_type)
left_name := c.table.type_to_str(unwrapped_left_type)
right_name := c.table.type_to_str(unwrapped_right_type)
if left_name == right_name {
c.error('undefined operation `$left_name` $node.op.str() `$right_name`',
left_right_pos)
@ -217,8 +222,8 @@ pub fn (mut c Checker) infix_expr(mut node ast.InfixExpr) ast.Type {
return_type = right_type
}
} else {
left_name := c.table.type_to_str(left_type)
right_name := c.table.type_to_str(right_type)
left_name := c.table.type_to_str(unwrapped_left_type)
right_name := c.table.type_to_str(unwrapped_right_type)
if left_name == right_name {
c.error('undefined operation `$left_name` $node.op.str() `$right_name`',
left_right_pos)
@ -236,8 +241,8 @@ pub fn (mut c Checker) infix_expr(mut node ast.InfixExpr) ast.Type {
return_type = left_type
}
} else {
left_name := c.table.type_to_str(left_type)
right_name := c.table.type_to_str(right_type)
left_name := c.table.type_to_str(unwrapped_left_type)
right_name := c.table.type_to_str(unwrapped_right_type)
if left_name == right_name {
c.error('undefined operation `$left_name` $node.op.str() `$right_name`',
left_right_pos)
@ -253,8 +258,8 @@ pub fn (mut c Checker) infix_expr(mut node ast.InfixExpr) ast.Type {
return_type = right_type
}
} else {
left_name := c.table.type_to_str(left_type)
right_name := c.table.type_to_str(right_type)
left_name := c.table.type_to_str(unwrapped_left_type)
right_name := c.table.type_to_str(unwrapped_right_type)
if left_name == right_name {
c.error('undefined operation `$left_name` $node.op.str() `$right_name`',
left_right_pos)
@ -264,14 +269,14 @@ pub fn (mut c Checker) infix_expr(mut node ast.InfixExpr) ast.Type {
}
} else if node.left.is_auto_deref_var() || node.right.is_auto_deref_var() {
deref_left_type := if node.left.is_auto_deref_var() {
left_type.deref()
unwrapped_left_type.deref()
} else {
left_type
unwrapped_left_type
}
deref_right_type := if node.right.is_auto_deref_var() {
right_type.deref()
unwrapped_right_type.deref()
} else {
right_type
unwrapped_right_type
}
left_name := c.table.type_to_str(ast.mktyp(deref_left_type))
right_name := c.table.type_to_str(ast.mktyp(deref_right_type))
@ -279,8 +284,8 @@ pub fn (mut c Checker) infix_expr(mut node ast.InfixExpr) ast.Type {
c.error('mismatched types `$left_name` and `$right_name`', left_right_pos)
}
} else {
unaliased_left_type := c.table.unalias_num_type(left_type)
unalias_right_type := c.table.unalias_num_type(right_type)
unaliased_left_type := c.table.unalias_num_type(unwrapped_left_type)
unalias_right_type := c.table.unalias_num_type(unwrapped_right_type)
mut promoted_type := c.promote_keeping_aliases(unaliased_left_type, unalias_right_type,
left_sym.kind, right_sym.kind)
// substract pointers is allowed in unsafe block
@ -290,17 +295,21 @@ pub fn (mut c Checker) infix_expr(mut node ast.InfixExpr) ast.Type {
promoted_type = ast.int_type
}
if promoted_type.idx() == ast.void_type_idx {
left_name := c.table.type_to_str(left_type)
right_name := c.table.type_to_str(right_type)
left_name := c.table.type_to_str(unwrapped_left_type)
right_name := c.table.type_to_str(unwrapped_right_type)
c.error('mismatched types `$left_name` and `$right_name`', left_right_pos)
} else if promoted_type.has_flag(.optional) {
s := c.table.type_to_str(promoted_type)
c.error('`$node.op` cannot be used with `$s`', node.pos)
} else if promoted_type.is_float() {
if node.op in [.mod, .xor, .amp, .pipe] {
side := if left_type == promoted_type { 'left' } else { 'right' }
pos := if left_type == promoted_type { left_pos } else { right_pos }
name := if left_type == promoted_type {
side := if unwrapped_left_type == promoted_type { 'left' } else { 'right' }
pos := if unwrapped_left_type == promoted_type {
left_pos
} else {
right_pos
}
name := if unwrapped_left_type == promoted_type {
left_sym.name
} else {
right_sym.name

View File

@ -0,0 +1,6 @@
vlib/v/checker/tests/generic_infix_plus_err.vv:2:9: error: undefined operation `map[string]int` + `map[string]int`
1 | fn sum<T>(a T, b T) T {
2 | return a + b
| ~~~~~
3 | }
4 |

View File

@ -0,0 +1,11 @@
fn sum<T>(a T, b T) T {
return a + b
}
fn main() {
sum({
'id': 1
}, {
'id': 1
})
}