checker: make sure that the operator check is made on the concrete type (#13360)

pull/13362/head
Vincenzo Palazzo 2022-02-04 23:11:24 +01:00 committed by GitHub
parent a054f868a0
commit b9fce4ef09
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 66 additions and 2 deletions

View File

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

View 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

View 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)
}