From 8fe70a24a86f197fce595aa8d7ad86f43b57eef5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kr=C3=BCger?= <45282134+UweKrueger@users.noreply.github.com> Date: Fri, 26 Jun 2020 23:31:38 +0200 Subject: [PATCH] checker: forbid non-reference mut arg or receiver of go function --- vlib/v/checker/checker.v | 13 +++++++++++++ vlib/v/checker/tests/go_mut_arg.out | 6 ++++++ vlib/v/checker/tests/go_mut_arg.vv | 15 +++++++++++++++ vlib/v/checker/tests/go_mut_receiver.out | 6 ++++++ vlib/v/checker/tests/go_mut_receiver.vv | 15 +++++++++++++++ 5 files changed, 55 insertions(+) create mode 100644 vlib/v/checker/tests/go_mut_arg.out create mode 100644 vlib/v/checker/tests/go_mut_arg.vv create mode 100644 vlib/v/checker/tests/go_mut_receiver.out create mode 100644 vlib/v/checker/tests/go_mut_receiver.vv diff --git a/vlib/v/checker/checker.v b/vlib/v/checker/checker.v index 7f41800367..103beb43c8 100644 --- a/vlib/v/checker/checker.v +++ b/vlib/v/checker/checker.v @@ -1826,6 +1826,19 @@ fn (mut c Checker) stmt(node ast.Stmt) { c.error('expression in `go` must be a function call', it.call_expr.position()) } c.expr(it.call_expr) + if it.call_expr is ast.CallExpr { + call_expr := it.call_expr as ast.CallExpr + + // Make sure there are no mutable arguments + for arg in call_expr.args { + if arg.is_mut && !arg.typ.is_ptr() { + c.error('function in `go` statement cannot contain mutable non-reference arguments', arg.expr.position()) + } + } + if call_expr.is_method && call_expr.receiver_type.is_ptr() && !call_expr.left_type.is_ptr() { + c.error('method in `go` statement cannot have non-reference mutable receiver', call_expr.left.position()) + } + } } // ast.HashStmt {} ast.Import {} diff --git a/vlib/v/checker/tests/go_mut_arg.out b/vlib/v/checker/tests/go_mut_arg.out new file mode 100644 index 0000000000..3544f2cd87 --- /dev/null +++ b/vlib/v/checker/tests/go_mut_arg.out @@ -0,0 +1,6 @@ +vlib/v/checker/tests/go_mut_arg.v:14:16: error: function in `go` statement cannot contain mutable non-reference arguments + 12 | a: 0 + 13 | } + 14 | go change(mut x) + | ^ + 15 | } diff --git a/vlib/v/checker/tests/go_mut_arg.vv b/vlib/v/checker/tests/go_mut_arg.vv new file mode 100644 index 0000000000..af86f15d1c --- /dev/null +++ b/vlib/v/checker/tests/go_mut_arg.vv @@ -0,0 +1,15 @@ +struct St { +mut: + a int +} + +fn change(mut a St) { + a.a++ +} + +fn main() { + mut x := St{ + a: 0 + } + go change(mut x) +} diff --git a/vlib/v/checker/tests/go_mut_receiver.out b/vlib/v/checker/tests/go_mut_receiver.out new file mode 100644 index 0000000000..5033b5d2be --- /dev/null +++ b/vlib/v/checker/tests/go_mut_receiver.out @@ -0,0 +1,6 @@ +vlib/v/checker/tests/go_mut_receiver.v:14:5: error: method in `go` statement cannot have non-reference mutable receiver + 12 | a: 0 + 13 | } + 14 | go x.change() + | ^ + 15 | } diff --git a/vlib/v/checker/tests/go_mut_receiver.vv b/vlib/v/checker/tests/go_mut_receiver.vv new file mode 100644 index 0000000000..0b64d51c23 --- /dev/null +++ b/vlib/v/checker/tests/go_mut_receiver.vv @@ -0,0 +1,15 @@ +struct St { +mut: + a int +} + +fn (mut a St) change() { + a.a++ +} + +fn main() { + mut x := St{ + a: 0 + } + go x.change() +}