From 5c7ceb16dde968b329c53e122126da52a759d657 Mon Sep 17 00:00:00 2001 From: shove Date: Thu, 3 Nov 2022 18:18:30 +0800 Subject: [PATCH] checker: fix the check of types not implemented by interfaces in infix key_is and not_is (fix #16282 #16298) (#16284) --- vlib/v/checker/infix.v | 7 ++++- .../tests/generic_sumtype_invalid_variant.out | 8 +++--- ...x_is_notis_interface_unimplemented_err.out | 20 +++++++++++++ ...ix_is_notis_interface_unimplemented_err.vv | 28 +++++++++++++++++++ vlib/v/checker/tests/is_type_invalid.out | 8 +++--- vlib/v/tests/generics_array_typedef_test.v | 4 +-- ...ics_assign_reference_generic_struct_test.v | 4 +-- 7 files changed, 66 insertions(+), 13 deletions(-) create mode 100644 vlib/v/checker/tests/infix_is_notis_interface_unimplemented_err.out create mode 100644 vlib/v/checker/tests/infix_is_notis_interface_unimplemented_err.vv diff --git a/vlib/v/checker/infix.v b/vlib/v/checker/infix.v index 528d191be..b22cffc74 100644 --- a/vlib/v/checker/infix.v +++ b/vlib/v/checker/infix.v @@ -554,7 +554,12 @@ pub fn (mut c Checker) infix_expr(mut node ast.InfixExpr) ast.Type { c.error('`$op` can only be used with interfaces and sum types', node.pos) } else if mut left_sym.info is ast.SumType { if typ !in left_sym.info.variants { - c.error('`$left_sym.name` has no variant `$right_sym.name`', node.pos) + c.error('`$left_sym.name` has no variant `$right_sym.name`', right_pos) + } + } else if left_sym.info is ast.Interface { + if typ_sym.kind != .interface_ && !c.type_implements(typ, left_type, right_pos) { + c.error("`$typ_sym.name` doesn't implement interface `$left_sym.name`", + right_pos) } } } diff --git a/vlib/v/checker/tests/generic_sumtype_invalid_variant.out b/vlib/v/checker/tests/generic_sumtype_invalid_variant.out index 72bd5932d..27ffaee2b 100644 --- a/vlib/v/checker/tests/generic_sumtype_invalid_variant.out +++ b/vlib/v/checker/tests/generic_sumtype_invalid_variant.out @@ -1,14 +1,14 @@ -vlib/v/checker/tests/generic_sumtype_invalid_variant.vv:5:7: error: `MultiGeneric` has no variant `u64` +vlib/v/checker/tests/generic_sumtype_invalid_variant.vv:5:10: error: `MultiGeneric` has no variant `u64` 3 | fn main() { 4 | mut m := MultiGeneric(true) 5 | if m is u64 { - | ~~ + | ~~~ 6 | println('hi') 7 | } -vlib/v/checker/tests/generic_sumtype_invalid_variant.vv:8:7: error: `MultiGeneric` has no variant `X` +vlib/v/checker/tests/generic_sumtype_invalid_variant.vv:8:10: error: `MultiGeneric` has no variant `X` 6 | println('hi') 7 | } 8 | if m is X { - | ~~ + | ^ 9 | println('hi again') 10 | } diff --git a/vlib/v/checker/tests/infix_is_notis_interface_unimplemented_err.out b/vlib/v/checker/tests/infix_is_notis_interface_unimplemented_err.out new file mode 100644 index 000000000..02ef679ca --- /dev/null +++ b/vlib/v/checker/tests/infix_is_notis_interface_unimplemented_err.out @@ -0,0 +1,20 @@ +vlib/v/checker/tests/infix_is_notis_interface_unimplemented_err.vv:8:14: error: `int` doesn't implement interface `IError` + 6 | if _ := f() { + 7 | } else { + 8 | _ = err is int + | ~~~ + 9 | } + 10 | +vlib/v/checker/tests/infix_is_notis_interface_unimplemented_err.vv:12:14: error: `int` doesn't implement interface `IError` + 10 | + 11 | _ = f() or { + 12 | _ = err is int + | ~~~ + 13 | 0 + 14 | } +vlib/v/checker/tests/infix_is_notis_interface_unimplemented_err.vv:27:17: error: `int` doesn't implement method `some_method` of interface `IAbc` + 25 | fn type_unimplemented_interface() { + 26 | ivalue := IAbc(Struct{}) + 27 | _ := ivalue is int + | ~~~ + 28 | } diff --git a/vlib/v/checker/tests/infix_is_notis_interface_unimplemented_err.vv b/vlib/v/checker/tests/infix_is_notis_interface_unimplemented_err.vv new file mode 100644 index 000000000..7102e70bd --- /dev/null +++ b/vlib/v/checker/tests/infix_is_notis_interface_unimplemented_err.vv @@ -0,0 +1,28 @@ +fn f() ?int { + return none +} + +fn type_unimplemented_ierror() { + if _ := f() { + } else { + _ = err is int + } + + _ = f() or { + _ = err is int + 0 + } +} + +interface IAbc { + some_method() +} + +struct Struct {} + +fn (s Struct) some_method() {} + +fn type_unimplemented_interface() { + ivalue := IAbc(Struct{}) + _ := ivalue is int +} diff --git a/vlib/v/checker/tests/is_type_invalid.out b/vlib/v/checker/tests/is_type_invalid.out index 2b7a4de64..b41020563 100644 --- a/vlib/v/checker/tests/is_type_invalid.out +++ b/vlib/v/checker/tests/is_type_invalid.out @@ -1,14 +1,14 @@ -vlib/v/checker/tests/is_type_invalid.vv:14:12: error: `IoS` has no variant `u8` +vlib/v/checker/tests/is_type_invalid.vv:14:15: error: `IoS` has no variant `u8` 12 | 13 | fn main() { 14 | if IoS(1) is u8 { - | ~~ + | ~~ 15 | println('not cool') 16 | } -vlib/v/checker/tests/is_type_invalid.vv:18:7: error: `Cat` doesn't implement method `speak` of interface `Animal` +vlib/v/checker/tests/is_type_invalid.vv:18:10: error: `Cat` doesn't implement method `speak` of interface `Animal` 16 | } 17 | a := Animal(Dog{}) 18 | if a is Cat { - | ~~ + | ~~~ 19 | println('not cool either') 20 | } diff --git a/vlib/v/tests/generics_array_typedef_test.v b/vlib/v/tests/generics_array_typedef_test.v index 24b204989..a6d183b2c 100644 --- a/vlib/v/tests/generics_array_typedef_test.v +++ b/vlib/v/tests/generics_array_typedef_test.v @@ -1,12 +1,12 @@ struct Node { mut: data T - next &Node = 0 + next &Node = unsafe { nil } } struct SinglyLinkedList { mut: - first_node &Node = 0 + first_node &Node = unsafe { nil } } fn init_singlylinkedlist(nodes []Node) SinglyLinkedList { diff --git a/vlib/v/tests/generics_assign_reference_generic_struct_test.v b/vlib/v/tests/generics_assign_reference_generic_struct_test.v index 2e5513fb9..bef0f0949 100644 --- a/vlib/v/tests/generics_assign_reference_generic_struct_test.v +++ b/vlib/v/tests/generics_assign_reference_generic_struct_test.v @@ -1,12 +1,12 @@ pub struct List { pub mut: - head &ListNode = 0 + head &ListNode = unsafe { nil } } pub struct ListNode { pub mut: value T - next &ListNode = 0 + next &ListNode = unsafe { nil } } pub fn list_new() List { -- 2.39.5