From 1e896c7020963ff4beeb94b77a4a74c59dcfb7eb Mon Sep 17 00:00:00 2001 From: yuyi Date: Wed, 30 Jun 2021 13:54:28 +0800 Subject: [PATCH] checker: check optional interface type mismatch (#10617) --- vlib/v/checker/check_types.v | 9 +++++++++ vlib/v/checker/checker.v | 1 - vlib/v/checker/tests/optional_interface_mismatch.out | 6 ++++++ vlib/v/checker/tests/optional_interface_mismatch.vv | 12 ++++++++++++ 4 files changed, 27 insertions(+), 1 deletion(-) create mode 100644 vlib/v/checker/tests/optional_interface_mismatch.out create mode 100644 vlib/v/checker/tests/optional_interface_mismatch.vv diff --git a/vlib/v/checker/check_types.v b/vlib/v/checker/check_types.v index be90167fde..622fca1954 100644 --- a/vlib/v/checker/check_types.v +++ b/vlib/v/checker/check_types.v @@ -304,6 +304,15 @@ pub fn (mut c Checker) check_types(got ast.Type, expected ast.Type) bool { if expected == ast.charptr_type && got == ast.char_type.to_ptr() { return true } + if expected.has_flag(.optional) { + sym := c.table.get_type_symbol(got) + if (sym.kind == .interface_ && sym.name == 'IError') + || got in [ast.none_type, ast.error_type] { + return true + } else if !c.check_basic(got, expected.clear_flag(.optional)) { + return false + } + } if !c.check_basic(got, expected) { // TODO: this should go away... return false } diff --git a/vlib/v/checker/checker.v b/vlib/v/checker/checker.v index f070c6fa42..92ad1f4453 100644 --- a/vlib/v/checker/checker.v +++ b/vlib/v/checker/checker.v @@ -6170,7 +6170,6 @@ pub fn (mut c Checker) if_expr(mut node ast.IfExpr) ast.Type { node.is_expr = true node.typ = c.expected_type } - continue } if c.expected_type.has_flag(.generic) { if node.typ == ast.void_type { diff --git a/vlib/v/checker/tests/optional_interface_mismatch.out b/vlib/v/checker/tests/optional_interface_mismatch.out new file mode 100644 index 0000000000..64fe585ba6 --- /dev/null +++ b/vlib/v/checker/tests/optional_interface_mismatch.out @@ -0,0 +1,6 @@ +vlib/v/checker/tests/optional_interface_mismatch.vv:11:9: error: mismatched types `?MObject` and `string` + 9 | + 10 | fn give_string(line string) ?MObject { + 11 | return if true { 'string' } else { 'string' } + | ~~ + 12 | } diff --git a/vlib/v/checker/tests/optional_interface_mismatch.vv b/vlib/v/checker/tests/optional_interface_mismatch.vv new file mode 100644 index 0000000000..1138fa3d23 --- /dev/null +++ b/vlib/v/checker/tests/optional_interface_mismatch.vv @@ -0,0 +1,12 @@ +fn main() { + le_string := give_string('string') or { return } + le_string.unimplemented() +} + +interface MObject { + unimplemented() string +} + +fn give_string(line string) ?MObject { + return if true { 'string' } else { 'string' } +}