From 2aced139420e7f8941b05c5676e0a07b614d711f Mon Sep 17 00:00:00 2001 From: Swastik Baranwal Date: Sat, 7 Jan 2023 15:23:20 +0530 Subject: [PATCH] checker: disallow all operations beside assignment, on multi return values (#16890) --- vlib/v/checker/for.v | 4 + vlib/v/checker/infix.v | 4 + .../invalid_multi_return_operations_err.out | 139 ++++++++++++++++++ .../invalid_multi_return_operations_err.vv | 26 ++++ 4 files changed, 173 insertions(+) create mode 100644 vlib/v/checker/tests/invalid_multi_return_operations_err.out create mode 100644 vlib/v/checker/tests/invalid_multi_return_operations_err.vv diff --git a/vlib/v/checker/for.v b/vlib/v/checker/for.v index a7fc29549..2145db736 100644 --- a/vlib/v/checker/for.v +++ b/vlib/v/checker/for.v @@ -62,6 +62,10 @@ fn (mut c Checker) for_in_stmt(mut node ast.ForInStmt) { c.error('range type can not be string', node.cond.pos()) } else if typ_idx == ast.none_type_idx || high_type_idx == ast.none_type_idx { c.error('range type can not be none', node.cond.pos()) + } else if c.table.final_sym(typ).kind == .multi_return + && c.table.final_sym(high_type).kind == .multi_return { + c.error('multi-returns cannot be used in ranges. A range is from a single value to a single higher value.', + node.cond.pos()) } if high_type in [ast.int_type, ast.int_literal_type] { node.val_type = typ diff --git a/vlib/v/checker/infix.v b/vlib/v/checker/infix.v index 7a7ff19c5..44846add7 100644 --- a/vlib/v/checker/infix.v +++ b/vlib/v/checker/infix.v @@ -65,6 +65,10 @@ fn (mut c Checker) infix_expr(mut node ast.InfixExpr) ast.Type { if left_sym.kind == .none_ && right_sym.kind == .none_ { c.invalid_operator_error(node.op, left_type, right_type, left_right_pos) } + if left_sym.kind == .multi_return && right_sym.kind == .multi_return { + c.error('invalid number of operand for `${node.op}`. Only one allowed on each side.', + left_right_pos) + } if left_type.is_any_kind_of_pointer() && node.op in [.plus, .minus, .mul, .div, .mod, .xor, .amp, .pipe] { if !c.pref.translated && ((right_type.is_any_kind_of_pointer() && node.op != .minus) diff --git a/vlib/v/checker/tests/invalid_multi_return_operations_err.out b/vlib/v/checker/tests/invalid_multi_return_operations_err.out new file mode 100644 index 000000000..240603237 --- /dev/null +++ b/vlib/v/checker/tests/invalid_multi_return_operations_err.out @@ -0,0 +1,139 @@ +vlib/v/checker/tests/invalid_multi_return_operations_err.vv:5:9: error: invalid number of operand for `+`. Only one allowed on each side. + 3 | } + 4 | + 5 | println(foo() + foo()) + | ~~~~~~~~~~~~~ + 6 | println(foo() - foo()) + 7 | println(foo() * foo()) +vlib/v/checker/tests/invalid_multi_return_operations_err.vv:6:9: error: invalid number of operand for `-`. Only one allowed on each side. + 4 | + 5 | println(foo() + foo()) + 6 | println(foo() - foo()) + | ~~~~~~~~~~~~~ + 7 | println(foo() * foo()) + 8 | println(foo() / foo()) +vlib/v/checker/tests/invalid_multi_return_operations_err.vv:7:9: error: invalid number of operand for `*`. Only one allowed on each side. + 5 | println(foo() + foo()) + 6 | println(foo() - foo()) + 7 | println(foo() * foo()) + | ~~~~~~~~~~~~~ + 8 | println(foo() / foo()) + 9 | println(foo() % foo()) +vlib/v/checker/tests/invalid_multi_return_operations_err.vv:8:9: error: invalid number of operand for `/`. Only one allowed on each side. + 6 | println(foo() - foo()) + 7 | println(foo() * foo()) + 8 | println(foo() / foo()) + | ~~~~~~~~~~~~~ + 9 | println(foo() % foo()) + 10 | println(foo() ^ foo()) +vlib/v/checker/tests/invalid_multi_return_operations_err.vv:9:9: error: invalid number of operand for `%`. Only one allowed on each side. + 7 | println(foo() * foo()) + 8 | println(foo() / foo()) + 9 | println(foo() % foo()) + | ~~~~~~~~~~~~~ + 10 | println(foo() ^ foo()) + 11 | println(foo() << foo()) +vlib/v/checker/tests/invalid_multi_return_operations_err.vv:10:9: error: invalid number of operand for `^`. Only one allowed on each side. + 8 | println(foo() / foo()) + 9 | println(foo() % foo()) + 10 | println(foo() ^ foo()) + | ~~~~~~~~~~~~~ + 11 | println(foo() << foo()) + 12 | println(foo() >> foo()) +vlib/v/checker/tests/invalid_multi_return_operations_err.vv:11:9: error: invalid number of operand for `<<`. Only one allowed on each side. + 9 | println(foo() % foo()) + 10 | println(foo() ^ foo()) + 11 | println(foo() << foo()) + | ~~~~~~~~~~~~~~ + 12 | println(foo() >> foo()) + 13 | println(foo() == foo()) +vlib/v/checker/tests/invalid_multi_return_operations_err.vv:12:9: error: invalid number of operand for `>>`. Only one allowed on each side. + 10 | println(foo() ^ foo()) + 11 | println(foo() << foo()) + 12 | println(foo() >> foo()) + | ~~~~~~~~~~~~~~ + 13 | println(foo() == foo()) + 14 | println(foo() != foo()) +vlib/v/checker/tests/invalid_multi_return_operations_err.vv:13:9: error: invalid number of operand for `==`. Only one allowed on each side. + 11 | println(foo() << foo()) + 12 | println(foo() >> foo()) + 13 | println(foo() == foo()) + | ~~~~~~~~~~~~~~ + 14 | println(foo() != foo()) + 15 | println(foo() > foo()) +vlib/v/checker/tests/invalid_multi_return_operations_err.vv:14:9: error: invalid number of operand for `!=`. Only one allowed on each side. + 12 | println(foo() >> foo()) + 13 | println(foo() == foo()) + 14 | println(foo() != foo()) + | ~~~~~~~~~~~~~~ + 15 | println(foo() > foo()) + 16 | println(foo() < foo()) +vlib/v/checker/tests/invalid_multi_return_operations_err.vv:15:9: error: invalid number of operand for `>`. Only one allowed on each side. + 13 | println(foo() == foo()) + 14 | println(foo() != foo()) + 15 | println(foo() > foo()) + | ~~~~~~~~~~~~~ + 16 | println(foo() < foo()) + 17 | println(foo() >= foo()) +vlib/v/checker/tests/invalid_multi_return_operations_err.vv:16:9: error: invalid number of operand for `<`. Only one allowed on each side. + 14 | println(foo() != foo()) + 15 | println(foo() > foo()) + 16 | println(foo() < foo()) + | ~~~~~~~~~~~~~ + 17 | println(foo() >= foo()) + 18 | println(foo() <= foo()) +vlib/v/checker/tests/invalid_multi_return_operations_err.vv:17:9: error: invalid number of operand for `>=`. Only one allowed on each side. + 15 | println(foo() > foo()) + 16 | println(foo() < foo()) + 17 | println(foo() >= foo()) + | ~~~~~~~~~~~~~~ + 18 | println(foo() <= foo()) + 19 | println(foo() && foo()) +vlib/v/checker/tests/invalid_multi_return_operations_err.vv:18:9: error: invalid number of operand for `<=`. Only one allowed on each side. + 16 | println(foo() < foo()) + 17 | println(foo() >= foo()) + 18 | println(foo() <= foo()) + | ~~~~~~~~~~~~~~ + 19 | println(foo() && foo()) + 20 | println(foo() || foo()) +vlib/v/checker/tests/invalid_multi_return_operations_err.vv:19:9: error: invalid number of operand for `&&`. Only one allowed on each side. + 17 | println(foo() >= foo()) + 18 | println(foo() <= foo()) + 19 | println(foo() && foo()) + | ~~~~~~~~~~~~~~ + 20 | println(foo() || foo()) + 21 | println(foo() in foo()) +vlib/v/checker/tests/invalid_multi_return_operations_err.vv:20:9: error: invalid number of operand for `||`. Only one allowed on each side. + 18 | println(foo() <= foo()) + 19 | println(foo() && foo()) + 20 | println(foo() || foo()) + | ~~~~~~~~~~~~~~ + 21 | println(foo() in foo()) + 22 | println(foo() !in foo()) +vlib/v/checker/tests/invalid_multi_return_operations_err.vv:21:9: error: invalid number of operand for `in`. Only one allowed on each side. + 19 | println(foo() && foo()) + 20 | println(foo() || foo()) + 21 | println(foo() in foo()) + | ~~~~~~~~~~~~~~ + 22 | println(foo() !in foo()) + 23 | println(foo() <- foo()) +vlib/v/checker/tests/invalid_multi_return_operations_err.vv:22:9: error: invalid number of operand for `!in`. Only one allowed on each side. + 20 | println(foo() || foo()) + 21 | println(foo() in foo()) + 22 | println(foo() !in foo()) + | ~~~~~~~~~~~~~~~ + 23 | println(foo() <- foo()) + 24 | +vlib/v/checker/tests/invalid_multi_return_operations_err.vv:23:9: error: invalid number of operand for `<-`. Only one allowed on each side. + 21 | println(foo() in foo()) + 22 | println(foo() !in foo()) + 23 | println(foo() <- foo()) + | ~~~~~~~~~~~~~~ + 24 | + 25 | for _ in foo() .. foo() { +vlib/v/checker/tests/invalid_multi_return_operations_err.vv:25:10: error: multi-returns cannot be used in ranges. A range is from a single value to a single higher value. + 23 | println(foo() <- foo()) + 24 | + 25 | for _ in foo() .. foo() { + | ~~~~~ + 26 | } diff --git a/vlib/v/checker/tests/invalid_multi_return_operations_err.vv b/vlib/v/checker/tests/invalid_multi_return_operations_err.vv new file mode 100644 index 000000000..434c975ab --- /dev/null +++ b/vlib/v/checker/tests/invalid_multi_return_operations_err.vv @@ -0,0 +1,26 @@ +fn foo() (int, int) { + return 1, 2 +} + +println(foo() + foo()) +println(foo() - foo()) +println(foo() * foo()) +println(foo() / foo()) +println(foo() % foo()) +println(foo() ^ foo()) +println(foo() << foo()) +println(foo() >> foo()) +println(foo() == foo()) +println(foo() != foo()) +println(foo() > foo()) +println(foo() < foo()) +println(foo() >= foo()) +println(foo() <= foo()) +println(foo() && foo()) +println(foo() || foo()) +println(foo() in foo()) +println(foo() !in foo()) +println(foo() <- foo()) + +for _ in foo() .. foo() { +} -- 2.39.5