mirror of
https://github.com/vlang/v.git
synced 2023-08-10 21:13:21 +03:00
checker: make sure that the operator check is made on the concrete type (#13360)
This commit is contained in:
parent
a054f868a0
commit
b9fce4ef09
@ -541,10 +541,10 @@ pub fn (mut c Checker) infix_expr(mut node ast.InfixExpr) ast.Type {
|
||||
defer {
|
||||
c.expected_type = former_expected_type
|
||||
}
|
||||
left_type := c.expr(node.left)
|
||||
mut left_type := c.expr(node.left)
|
||||
node.left_type = left_type
|
||||
c.expected_type = left_type
|
||||
right_type := c.expr(node.right)
|
||||
mut right_type := c.expr(node.right)
|
||||
node.right_type = right_type
|
||||
if left_type.is_number() && !left_type.is_ptr()
|
||||
&& right_type in [ast.int_literal_type, ast.float_literal_type] {
|
||||
@ -796,6 +796,18 @@ pub fn (mut c Checker) infix_expr(mut node ast.InfixExpr) ast.Type {
|
||||
} else if !left_sym.has_method('<') && node.op == .gt {
|
||||
c.error('cannot use `>` as `<=` operator method is not defined', left_right_pos)
|
||||
}
|
||||
} else if left_type.has_flag(.generic) && right_type.has_flag(.generic) {
|
||||
// Try to unwrap the generic type to make sure that
|
||||
// the below check works as expected
|
||||
left_gen_type := c.unwrap_generic(left_type)
|
||||
gen_sym := c.table.sym(left_gen_type)
|
||||
need_overload := gen_sym.kind in [.struct_, .interface_]
|
||||
if need_overload && !gen_sym.has_method('<') && node.op in [.ge, .le] {
|
||||
c.error('cannot use `$node.op` as `<` operator method is not defined',
|
||||
left_right_pos)
|
||||
} else if need_overload && !gen_sym.has_method('<') && node.op == .gt {
|
||||
c.error('cannot use `>` as `<=` operator method is not defined', left_right_pos)
|
||||
}
|
||||
}
|
||||
}
|
||||
.left_shift {
|
||||
|
21
vlib/v/checker/tests/cmp_between_struct.out
Normal file
21
vlib/v/checker/tests/cmp_between_struct.out
Normal file
@ -0,0 +1,21 @@
|
||||
vlib/datatypes/heap.v:16:15: error: cannot use `>` as `<=` operator method is not defined
|
||||
14 | mut child := heap.data.len - 1
|
||||
15 | mut parent := heap.parent(child)
|
||||
16 | for heap.data[parent] > heap.data[child] {
|
||||
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
17 | heap.data[parent], heap.data[child] = heap.data[child], heap.data[parent]
|
||||
18 | child = parent
|
||||
vlib/datatypes/heap.v:37:15: error: cannot use `>` as `<=` operator method is not defined
|
||||
35 | mut left := heap.left_child(parent) or { return item }
|
||||
36 | mut right := heap.right_child(parent) or { left }
|
||||
37 | for heap.data[parent] > heap.data[left] || heap.data[parent] > heap.data[right] {
|
||||
| ~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
38 | // choose min for min heap
|
||||
39 | swap := if heap.data[left] <= heap.data[right] { left } else { right }
|
||||
vlib/datatypes/heap.v:39:23: error: cannot use `<=` as `<` operator method is not defined
|
||||
37 | for heap.data[parent] > heap.data[left] || heap.data[parent] > heap.data[right] {
|
||||
38 | // choose min for min heap
|
||||
39 | swap := if heap.data[left] <= heap.data[right] { left } else { right }
|
||||
| ~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
40 | heap.data[parent], heap.data[swap] = heap.data[swap], heap.data[parent]
|
||||
41 | parent = swap
|
31
vlib/v/checker/tests/cmp_between_struct.vv
Normal file
31
vlib/v/checker/tests/cmp_between_struct.vv
Normal file
@ -0,0 +1,31 @@
|
||||
module main
|
||||
|
||||
import datatypes
|
||||
|
||||
struct Item {
|
||||
priority int
|
||||
}
|
||||
|
||||
// Issue https://github.com/vlang/v/issues/13318
|
||||
|
||||
/*
|
||||
fn (a Item) < (b Item) bool {
|
||||
return a.priority < b.priority
|
||||
}
|
||||
|
||||
fn (a Item) == (b Item) bool {
|
||||
return a.priority == b.priority
|
||||
}
|
||||
*/
|
||||
|
||||
fn main() {
|
||||
min_heap()
|
||||
}
|
||||
|
||||
fn min_heap() {
|
||||
mut heap := datatypes.MinHeap<Item>{}
|
||||
|
||||
heap.insert(Item{10})
|
||||
|
||||
println(heap)
|
||||
}
|
Loading…
Reference in New Issue
Block a user