From 470a1087eb9a340fc5c76f5a9428b29e17e6b23b Mon Sep 17 00:00:00 2001 From: lochana-chathura <39232462+lochana-chathura@users.noreply.github.com> Date: Thu, 4 Apr 2024 23:10:45 +0530 Subject: [PATCH 1/4] Fix error:NoMessage for worker-on-fail --- .../semantics/analyzer/CodeAnalyzer.java | 18 ++--- .../test/worker/WorkerOnFailTest.java | 40 +++++++++- .../workers/worker-on-fail-negative.bal | 74 +++++++++++++++++++ .../test-src/workers/worker-on-fail.bal | 30 ++++++++ 4 files changed, 152 insertions(+), 10 deletions(-) create mode 100644 tests/jballerina-unit-test/src/test/resources/test-src/workers/worker-on-fail-negative.bal diff --git a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/analyzer/CodeAnalyzer.java b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/analyzer/CodeAnalyzer.java index c5c5eb759a53..41bd8ed84f1d 100644 --- a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/analyzer/CodeAnalyzer.java +++ b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/analyzer/CodeAnalyzer.java @@ -1990,17 +1990,17 @@ private boolean isCommunicationAllowedContext(BLangFunctionBody enclInvokableBod return false; } - private boolean withinIf(BLangFunctionBody enclInvokableBody, BLangNode node) { + private boolean withinIfOrOnFail(BLangFunctionBody enclInvokableBody, BLangNode node) { if (enclInvokableBody == node) { return false; } BLangNode parentNode = node.parent; - if (parentNode.getKind() == NodeKind.IF) { + if (parentNode.getKind() == NodeKind.IF || parentNode.getKind() == NodeKind.ON_FAIL) { return true; } - return withinIf(enclInvokableBody, parentNode); + return withinIfOrOnFail(enclInvokableBody, parentNode); } private boolean isDefaultWorkerCommunication(String workerIdentifier) { @@ -2058,15 +2058,15 @@ public void visit(BLangWorkerAsyncSendExpr asyncSendExpr, AnalyzerData data) { was.hasErrors = true; } - boolean withinIf = !invalidSendPos && withinIf(data.env.enclInvokable.body, data.env.node); - setWorkerSendSendTypeDetails(asyncSendExpr, asyncSendExpr.expr.getBType(), withinIf, data); + boolean withinIfOrOnFail = !invalidSendPos && withinIfOrOnFail(data.env.enclInvokable.body, data.env.node); + setWorkerSendSendTypeDetails(asyncSendExpr, asyncSendExpr.expr.getBType(), withinIfOrOnFail, data); was.addWorkerAction(asyncSendExpr); analyzeExpr(asyncSendExpr.expr, data); validateActionParentNode(asyncSendExpr.pos, asyncSendExpr.expr); } private void setWorkerSendSendTypeDetails(BLangWorkerSendExpr workerSendExpr, BType exprType, - boolean withinIf, AnalyzerData data) { + boolean withinIfOrOnFail, AnalyzerData data) { Set returnTypesUpToNow = data.returnTypes.peek(); LinkedHashSet returnTypeAndSendType = new LinkedHashSet<>() { { @@ -2091,7 +2091,7 @@ private void setWorkerSendSendTypeDetails(BLangWorkerSendExpr workerSendExpr, BT } BType sendType; - boolean noMessagePossible = withinIf || hasNonErrorReturn; + boolean noMessagePossible = withinIfOrOnFail || hasNonErrorReturn; if (noMessagePossible) { // There is a possibility that the send action may not be executed, thus adding NoMessageError type. BSymbol noMsgErrSymbol = symTable.langErrorModuleSymbol.scope. @@ -2144,8 +2144,8 @@ public void visit(BLangWorkerSyncSendExpr syncSendExpr, AnalyzerData data) { } syncSendExpr.setBType(BUnionType.create(null, symTable.nilType, symTable.errorType)); - boolean withinIf = !invalidSendPos && withinIf(data.env.enclInvokable.body, data.env.node); - setWorkerSendSendTypeDetails(syncSendExpr, syncSendExpr.expr.getBType(), withinIf, data); + boolean withinIfOrOnFail = !invalidSendPos && withinIfOrOnFail(data.env.enclInvokable.body, data.env.node); + setWorkerSendSendTypeDetails(syncSendExpr, syncSendExpr.expr.getBType(), withinIfOrOnFail, data); was.addWorkerAction(syncSendExpr); analyzeExpr(syncSendExpr.expr, data); } diff --git a/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/worker/WorkerOnFailTest.java b/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/worker/WorkerOnFailTest.java index 487c2272ab99..0dad18412e8d 100644 --- a/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/worker/WorkerOnFailTest.java +++ b/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/worker/WorkerOnFailTest.java @@ -22,11 +22,14 @@ import org.ballerinalang.test.BRunUtil; import org.ballerinalang.test.CompileResult; import org.testng.Assert; +import org.testng.annotations.AfterClass; import org.testng.annotations.BeforeClass; import org.testng.annotations.Test; import java.util.Arrays; +import static org.ballerinalang.test.BAssertUtil.validateError; + /** * Tests the worker on fail clause. * @@ -35,11 +38,13 @@ public class WorkerOnFailTest { private CompileResult result; + private CompileResult resultNegative; @BeforeClass public void setup() { - this.result = BCompileUtil.compile("test-src/workers/worker-on-fail.bal"); + result = BCompileUtil.compile("test-src/workers/worker-on-fail.bal"); Assert.assertEquals(result.getErrorCount(), 0, Arrays.asList(result.getDiagnostics()).toString()); + resultNegative = BCompileUtil.compile("test-src/workers/worker-on-fail-negative.bal"); } @Test @@ -77,4 +82,37 @@ public void workerOnFailWithSend() { Assert.assertEquals(ret, 1); } + @Test + public void asyncSendInsideWorkerOnFail() { + Object returns = BRunUtil.invoke(result, "testAsyncSendInsideWorkerOnFail"); + long ret = (long) returns; + Assert.assertEquals(ret, 17); + } + + @Test + public void syncSendInsideWorkerOnFail() { + Object returns = BRunUtil.invoke(result, "testSyncSendInsideWorkerOnFail"); + long ret = (long) returns; + Assert.assertEquals(ret, -8); + } + + @Test + public void onFailNegative() { + String errMsg = "incompatible types: expected 'int', found '(int|ballerina/lang.error:0.0.0:NoMessage)'"; + int index = 0; + validateError(resultNegative, index++, errMsg, 26, 17); + validateError(resultNegative, index++, errMsg, 41, 17); + validateError(resultNegative, index++, errMsg, 66, 17); + validateError(resultNegative, index++, errMsg, 67, 17); + validateError(resultNegative, index++, errMsg, 68, 17); + validateError(resultNegative, index++, errMsg, 69, 17); + validateError(resultNegative, index++, errMsg, 70, 17); + Assert.assertEquals(resultNegative.getErrorCount(), index); + } + + @AfterClass + public void afterClass() { + result = null; + resultNegative = null; + } } diff --git a/tests/jballerina-unit-test/src/test/resources/test-src/workers/worker-on-fail-negative.bal b/tests/jballerina-unit-test/src/test/resources/test-src/workers/worker-on-fail-negative.bal new file mode 100644 index 000000000000..3b37894c521f --- /dev/null +++ b/tests/jballerina-unit-test/src/test/resources/test-src/workers/worker-on-fail-negative.bal @@ -0,0 +1,74 @@ +// Copyright (c) 2024 WSO2 LLC. (http://www.wso2.com). +// +// WSO2 LLC. licenses this file to you under the Apache License, +// Version 2.0 (the "License"); you may not use this file except +// in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +public function testNoMessageErrorForOnFailAsyncSend() { + worker w1 { + 0 -> w2; + } on fail { + 1 -> w2; + } + + worker w2 { + int _ = <- w1; + int _ = <- w1; // found 'int|error:NoMessage' + } + + wait w2; +} + +public function testNoMessageErrorForOnFailSyncSend() { + worker w1 { + 0 ->> w2; + } on fail { + 1 ->> w2; + } + + worker w2 { + int _ = <- w1; + int _ = <- w1; // found 'int|error:NoMessage' + } + + wait w1; +} + +public function testNoMessageErrorWithWorkerOnFail() { + worker w1 { + boolean b = true; + check error("err"); + 0 -> w2; + if b { + 1 -> w2; + } + } on fail { + boolean c = true; + 2 -> w2; + if c { + 3 ->> w2; + } else { + 4 -> w2; + } + } + + worker w2 { + int _ = <- w1; // found 'int|error:NoMessage' + int _ = <- w1; // found 'int|error:NoMessage' + int _ = <- w1; // found 'int|error:NoMessage' + int _ = <- w1; // found 'int|error:NoMessage' + int _ = <- w1; // found 'int|error:NoMessage' + } + + wait w2; +} diff --git a/tests/jballerina-unit-test/src/test/resources/test-src/workers/worker-on-fail.bal b/tests/jballerina-unit-test/src/test/resources/test-src/workers/worker-on-fail.bal index 6029a48eda52..d9b60ba7ce1a 100644 --- a/tests/jballerina-unit-test/src/test/resources/test-src/workers/worker-on-fail.bal +++ b/tests/jballerina-unit-test/src/test/resources/test-src/workers/worker-on-fail.bal @@ -103,3 +103,33 @@ function testWorkerOnFailWithSend() returns int { function returnOne() returns int => 1; function returnIntArr() returns int[] => [2, 3, 4, 5]; + +public function testAsyncSendInsideWorkerOnFail() returns int|error { + worker w1 { + check error("err"); + } on fail { + 17 -> w2; + } + + worker w2 returns int|error { + int x = check <- w1; + return x; + } + + return wait w2; +} + +public function testSyncSendInsideWorkerOnFail() returns int|error { + worker w1 { + check error("err"); + } on fail { + -8 ->> w2; + } + + worker w2 returns int|error { + int x = check <- w1; + return x; + } + + return wait w2; +} From 8c0be5da334f57121b3f076f098e8d937f9ead3b Mon Sep 17 00:00:00 2001 From: lochana-chathura <39232462+lochana-chathura@users.noreply.github.com> Date: Fri, 5 Apr 2024 00:37:30 +0530 Subject: [PATCH 2/4] Give error for worker receive after a non-error return --- .../util/diagnostic/DiagnosticErrorCode.java | 1 + .../semantics/analyzer/CodeAnalyzer.java | 28 ++++++--- .../src/main/resources/compiler.properties | 2 +- .../test/worker/WorkerFailTest.java | 23 ++++++- .../invalid-receive-before-workers.bal | 7 --- .../workers/invalid-receive-with-workers.bal | 63 +++++++++++++++++++ .../workers/workers_conditional_send.bal | 34 +++++----- 7 files changed, 121 insertions(+), 37 deletions(-) delete mode 100644 tests/jballerina-unit-test/src/test/resources/test-src/workers/invalid-receive-before-workers.bal create mode 100644 tests/jballerina-unit-test/src/test/resources/test-src/workers/invalid-receive-with-workers.bal diff --git a/compiler/ballerina-lang/src/main/java/org/ballerinalang/util/diagnostic/DiagnosticErrorCode.java b/compiler/ballerina-lang/src/main/java/org/ballerinalang/util/diagnostic/DiagnosticErrorCode.java index 90a3a8f7196f..85d000657a83 100644 --- a/compiler/ballerina-lang/src/main/java/org/ballerinalang/util/diagnostic/DiagnosticErrorCode.java +++ b/compiler/ballerina-lang/src/main/java/org/ballerinalang/util/diagnostic/DiagnosticErrorCode.java @@ -591,6 +591,7 @@ public enum DiagnosticErrorCode implements DiagnosticCode { INVALID_USE_OF_EXPERIMENTAL_FEATURE("BCE3843", "invalid.use.of.experimental.feature"), MULTIPLE_RECEIVE_COMPATIBLE_TYPE_NOT_FOUND("BCE3844", "multiple.receive.compatible.type.not.found"), DUPLICATE_KEY_IN_MULTIPLE_RECEIVE("BCE3845", "duplicate.key.in.multiple.receive"), + WORKER_RECEIVE_AFTER_NON_ERROR_RETURN("BCE3846", "worker.receive.after.non.error.return"), // LangLib related error codes. TYPE_PARAM_OUTSIDE_LANG_MODULE("BCE3900", "type.param.outside.lang.module"), diff --git a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/analyzer/CodeAnalyzer.java b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/analyzer/CodeAnalyzer.java index 41bd8ed84f1d..ffb58a3b8aad 100644 --- a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/analyzer/CodeAnalyzer.java +++ b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/analyzer/CodeAnalyzer.java @@ -2168,18 +2168,19 @@ public void visit(BLangMultipleWorkerReceive multipleWorkerReceive, AnalyzerData @Override public void visit(BLangWorkerReceive workerReceiveNode, AnalyzerData data) { // Validate worker receive - validateActionParentNode(workerReceiveNode.pos, workerReceiveNode); + Location workerReceivePos = workerReceiveNode.pos; + validateActionParentNode(workerReceivePos, workerReceiveNode); BSymbol sender = symResolver.lookupSymbolInMainSpace(data.env, names.fromIdNode(workerReceiveNode.workerIdentifier)); if ((sender.tag & SymTag.VARIABLE) != SymTag.VARIABLE) { sender = symTable.notFoundSymbol; } - verifyPeerCommunication(workerReceiveNode.pos, sender, workerReceiveNode.workerIdentifier.value, data.env); + verifyPeerCommunication(workerReceivePos, sender, workerReceiveNode.workerIdentifier.value, data.env); WorkerActionSystem was = data.workerActionSystemStack.peek(); if (data.withinLockBlock) { - this.dlog.error(workerReceiveNode.pos, + this.dlog.error(workerReceivePos, DiagnosticErrorCode.WORKER_RECEIVE_ACTION_NOT_ALLOWED_IN_LOCK_STATEMENT); was.hasErrors = true; } @@ -2187,16 +2188,16 @@ public void visit(BLangWorkerReceive workerReceiveNode, AnalyzerData data) { String workerName = workerReceiveNode.workerIdentifier.getValue(); if (data.withinQuery || (!isReceiveAllowedLocation(data.env.enclInvokable.body, data.env.node) && !data.inInternallyDefinedBlockStmt)) { - this.dlog.error(workerReceiveNode.pos, DiagnosticErrorCode.INVALID_WORKER_RECEIVE_POSITION); + this.dlog.error(workerReceivePos, DiagnosticErrorCode.INVALID_WORKER_RECEIVE_POSITION); was.hasErrors = true; } if (!this.workerExists(workerReceiveNode.workerType, workerName, data.env)) { - this.dlog.error(workerReceiveNode.pos, DiagnosticErrorCode.UNDEFINED_WORKER, workerName); + this.dlog.error(workerReceivePos, DiagnosticErrorCode.UNDEFINED_WORKER, workerName); was.hasErrors = true; } - workerReceiveNode.matchingSendsError = createAccumulatedErrorTypeForMatchingSyncSend(data); + workerReceiveNode.matchingSendsError = createAccumulatedErrorTypeForMatchingSyncSend(data, workerReceivePos); was.addWorkerAction(workerReceiveNode); } @@ -2234,12 +2235,23 @@ private void verifyPeerCommunication(Location pos, BSymbol otherWorker, String o } } - public BType createAccumulatedErrorTypeForMatchingSyncSend(AnalyzerData data) { + public BType createAccumulatedErrorTypeForMatchingSyncSend(AnalyzerData data, Location workerReceivePos) { LinkedHashSet returnTypesUpToNow = data.returnTypes.peek(); LinkedHashSet returnTypeAndSendType = new LinkedHashSet<>(); + + boolean hasNonErrorReturn = false; for (BType returnType : returnTypesUpToNow) { - addErrorTypesToSet(returnType, returnTypeAndSendType); + if (hasNonErrorType(returnType)) { + hasNonErrorReturn = true; + } else { + returnTypeAndSendType.add(returnType); + } + } + + if (hasNonErrorReturn) { + dlog.error(workerReceivePos, DiagnosticErrorCode.WORKER_RECEIVE_AFTER_NON_ERROR_RETURN); } + returnTypeAndSendType.add(symTable.nilType); if (returnTypeAndSendType.size() > 1) { return BUnionType.create(null, returnTypeAndSendType); diff --git a/compiler/ballerina-lang/src/main/resources/compiler.properties b/compiler/ballerina-lang/src/main/resources/compiler.properties index 4b48c5d2dec4..c99d84501fdc 100644 --- a/compiler/ballerina-lang/src/main/resources/compiler.properties +++ b/compiler/ballerina-lang/src/main/resources/compiler.properties @@ -393,7 +393,7 @@ error.self.reference.var=\ error.worker.send.after.return=\ invalid worker send statement position, can not be used after a non-error return -error.worker.receive.after.return=\ +error.worker.receive.after.non.error.return=\ invalid worker receive statement position, can not be used after a non-error return error.unsupported.worker.send.position=\ diff --git a/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/worker/WorkerFailTest.java b/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/worker/WorkerFailTest.java index 990243a46c7f..6d2cc3de5251 100644 --- a/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/worker/WorkerFailTest.java +++ b/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/worker/WorkerFailTest.java @@ -95,9 +95,16 @@ public void invalidWorkReceiveWithoutWorker() { @Test public void invalidReceiveBeforeWorkers() { - CompileResult result = BCompileUtil.compile("test-src/workers/invalid-receive-before-workers.bal"); - Assert.assertEquals(result.getErrorCount(), 1); - validateError(result, 0, "undefined worker 'w1'", 2, 11); + CompileResult result = BCompileUtil.compile("test-src/workers/invalid-receive-with-workers.bal"); + int index = 0; + validateError(result, index++, "undefined worker 'w1'", 18, 11); + validateError(result, index++, "invalid worker receive statement position, can not be used after a non-error " + + "return", 40, 17); + validateError(result, index++, "invalid worker receive statement position, can not be used after a non-error " + + "return", 59, 20); + validateError(result, index++, "invalid worker receive statement position, can not be used after a non-error " + + "return", 59, 23); + Assert.assertEquals(result.getErrorCount(), index); } @Test @@ -128,6 +135,16 @@ public void testSendReceiveFailureType() { validateError(result, index++, "incompatible types: expected 'int', found '(ErrorA|ErrorB|int)'", 71, 15); validateError(result, index++, "incompatible types: expected 'int', " + "found '(ErrorA|ErrorB|int|ballerina/lang.error:0.0.0:NoMessage)'", 86, 15); + validateError(result, index++, "invalid worker receive statement position, can not be used after a non-error " + + "return", 99, 14); + validateError(result, index++, "invalid worker receive statement position, can not be used after a non-error " + + "return", 104, 14); + validateError(result, index++, "invalid worker receive statement position, can not be used after a non-error " + + "return", 109, 14); + validateError(result, index++, "invalid worker receive statement position, can not be used after a non-error " + + "return", 110, 14); + validateError(result, index++, "invalid worker receive statement position, can not be used after a non-error " + + "return", 111, 14); validateError(result, index++, "incompatible types: expected '()', found 'ErrorA?'", 119, 14); validateError(result, index++, "incompatible types: expected '()', found '(ErrorA|ErrorB)?'", 120, 14); Assert.assertEquals(result.getErrorCount(), index); diff --git a/tests/jballerina-unit-test/src/test/resources/test-src/workers/invalid-receive-before-workers.bal b/tests/jballerina-unit-test/src/test/resources/test-src/workers/invalid-receive-before-workers.bal deleted file mode 100644 index a4e91db1aa96..000000000000 --- a/tests/jballerina-unit-test/src/test/resources/test-src/workers/invalid-receive-before-workers.bal +++ /dev/null @@ -1,7 +0,0 @@ -function invalidWorkReceiveBeforeWorker() { - int _ = <- w1; - worker w1 { - int i = 1; - i -> function; - } -} diff --git a/tests/jballerina-unit-test/src/test/resources/test-src/workers/invalid-receive-with-workers.bal b/tests/jballerina-unit-test/src/test/resources/test-src/workers/invalid-receive-with-workers.bal new file mode 100644 index 000000000000..bd4817a6e1fb --- /dev/null +++ b/tests/jballerina-unit-test/src/test/resources/test-src/workers/invalid-receive-with-workers.bal @@ -0,0 +1,63 @@ +// Copyright (c) 2024 WSO2 LLC. (http://www.wso2.com). +// +// WSO2 LLC. licenses this file to you under the Apache License, +// Version 2.0 (the "License"); you may not use this file except +// in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +function invalidWorkReceiveBeforeWorker() { + int _ = <- w1; + worker w1 { + int i = 1; + i -> function; + } +} + +function workerReceiveAfterNonErrorReturn1() { + worker w1 { + 1 ->> w2; + 2 ->> w2; + } + + worker w2 { + boolean b = true; + + int _ = <- w1; + + if b { + return; + } + + int _ = <- w1; + } + + wait w1; +} + +function workerReceiveAfterNonErrorReturn2() { + worker w1 { + 1 ->> w2; + 2 ->> w2; + } + + worker w2 { + boolean b = true; + + if b { + return; + } + + int _ = <- w1|w1; + } + + wait w1; +} diff --git a/tests/jballerina-unit-test/src/test/resources/test-src/workers/workers_conditional_send.bal b/tests/jballerina-unit-test/src/test/resources/test-src/workers/workers_conditional_send.bal index 08051b73b216..34b59c11e8ee 100644 --- a/tests/jballerina-unit-test/src/test/resources/test-src/workers/workers_conditional_send.bal +++ b/tests/jballerina-unit-test/src/test/resources/test-src/workers/workers_conditional_send.bal @@ -45,7 +45,7 @@ function workerConditionalSendTest() { 2 -> w5; } } - + worker w5 returns int|errorLib:NoMessage { int|errorLib:NoMessage d = <- w4; return d; @@ -240,8 +240,8 @@ function sameWorkerSendMultiplePath1() { worker w1 { if foo { 1 -> w2; - } - 2 -> w2; + } + 2 -> w2; } worker w2 returns int|errorLib:NoMessage { @@ -259,8 +259,8 @@ function sameWorkerSendMultiplePath2() { worker w1 { if foo { 1 -> w2; - } - 2 -> w2; + } + 2 -> w2; } worker w2 returns int|errorLib:NoMessage { @@ -282,8 +282,8 @@ function sameWorkerSendMultiplePathError1() { return error("Error in worker 1"); } 1 -> w2; - } - 2 -> w2; + } + 2 -> w2; } worker w2 returns int|error? { @@ -303,11 +303,11 @@ function sameWorkerSendMultiplePathError2() { int value = 10; if foo { 1 -> w2; - } + } if value == 10 { return error("Error in worker 1"); } - 2 -> w2; + 2 -> w2; } worker w2 returns int|error { @@ -334,15 +334,15 @@ function sameWorkerSendMultiplePathError3() { return error("Error in worker 1"); } 1 -> w2; - } - 2 -> w2; + } + 2 -> w2; } worker w2 returns int|error? { int|error a = <- w1 | w1; return a; } - + map mapResult = wait { a : w1, b: w2}; test:assertTrue(mapResult["a"] is error, "Invalid error result"); test:assertTrue(mapResult["b"] is error, "Invalid error result"); @@ -359,11 +359,11 @@ function sameWorkerSendMultiplePathError4() { int value = 10; if foo { 1 -> w2; - } + } if value == 10 { return error("Error in worker 1"); } - 2 -> w2; + 2 -> w2; } worker w2 returns int|error { @@ -387,10 +387,9 @@ function multipleReceiveConditional() { } else { 2-> w3; } - int y = <- w3; - return y; + return 3; } - + worker w2 returns int|errorLib:NoMessage { int|errorLib:NoMessage y = <- w1; return y; @@ -398,7 +397,6 @@ function multipleReceiveConditional() { worker w3 returns int|errorLib:NoMessage { int|errorLib:NoMessage y = <- w1; - 3 -> w1; return y; } From ba610e5710b962cb2612a1a5d9054ec08aebd1b9 Mon Sep 17 00:00:00 2001 From: lochana-chathura <39232462+lochana-chathura@users.noreply.github.com> Date: Fri, 5 Apr 2024 00:55:39 +0530 Subject: [PATCH 3/4] Disallow worker receive inside on-fail-clause --- .../compiler/semantics/analyzer/CodeAnalyzer.java | 6 ++++-- .../java/org/ballerinalang/test/worker/WorkerFailTest.java | 3 +++ .../test-src/workers/send-receive-allowed-positions.bal | 7 ++++++- 3 files changed, 13 insertions(+), 3 deletions(-) diff --git a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/analyzer/CodeAnalyzer.java b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/analyzer/CodeAnalyzer.java index ffb58a3b8aad..cbcaace973ce 100644 --- a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/analyzer/CodeAnalyzer.java +++ b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/analyzer/CodeAnalyzer.java @@ -1966,12 +1966,14 @@ private boolean isReceiveAllowedLocation(BLangFunctionBody enclInvokableBody, BL } private boolean isSendAllowedContext(BLangNode bLangNode) { - return isReceiveAllowedContext(bLangNode) || bLangNode.getKind() == NodeKind.IF; + return isReceiveAllowedContext(bLangNode) || + bLangNode.getKind() == NodeKind.IF || + bLangNode.getKind() == NodeKind.ON_FAIL; } private boolean isReceiveAllowedContext(BLangNode bLangNode) { return switch (bLangNode.getKind()) { - case BLOCK_FUNCTION_BODY, BLOCK, ON_FAIL, DO_STMT -> true; + case BLOCK_FUNCTION_BODY, BLOCK, DO_STMT -> true; default -> false; }; } diff --git a/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/worker/WorkerFailTest.java b/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/worker/WorkerFailTest.java index 6d2cc3de5251..1442a0d1d61c 100644 --- a/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/worker/WorkerFailTest.java +++ b/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/worker/WorkerFailTest.java @@ -49,6 +49,9 @@ public void testSendReceiveAllowedSyntacticPositions() { "possible deadlocks", 74, 17); validateError(result, index++, receiveNotAllowedError, 79, 15); validateError(result, index++, receiveNotAllowedError, 81, 21); + validateError(result, index++, receiveNotAllowedError, 93, 13); + validateError(result, index++, receiveNotAllowedError, 94, 16); + validateError(result, index++, receiveNotAllowedError, 94, 19); Assert.assertEquals(result.getErrorCount(), index); } diff --git a/tests/jballerina-unit-test/src/test/resources/test-src/workers/send-receive-allowed-positions.bal b/tests/jballerina-unit-test/src/test/resources/test-src/workers/send-receive-allowed-positions.bal index c7806fe03161..a6ef9faa5582 100644 --- a/tests/jballerina-unit-test/src/test/resources/test-src/workers/send-receive-allowed-positions.bal +++ b/tests/jballerina-unit-test/src/test/resources/test-src/workers/send-receive-allowed-positions.bal @@ -90,7 +90,12 @@ public function testReceiveAllowedLocations(boolean b) returns error? { _ = <- function; // OK } } on fail { - _ = <- function; // OK + _ = <- function; // error: position not allowed + _ = <- w2|function; // error: position not allowed + } + + worker w2 { + 1 -> w1; } 1 -> w1; From e958607d0a42b052aba01e8eae5a757b8e24593b Mon Sep 17 00:00:00 2001 From: lochana-chathura <39232462+lochana-chathura@users.noreply.github.com> Date: Tue, 16 Apr 2024 13:49:53 +0530 Subject: [PATCH 4/4] Fix a typo in a test case --- .../resources/test-src/workers/invalid-receive-with-workers.bal | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/jballerina-unit-test/src/test/resources/test-src/workers/invalid-receive-with-workers.bal b/tests/jballerina-unit-test/src/test/resources/test-src/workers/invalid-receive-with-workers.bal index bd4817a6e1fb..8266c978b790 100644 --- a/tests/jballerina-unit-test/src/test/resources/test-src/workers/invalid-receive-with-workers.bal +++ b/tests/jballerina-unit-test/src/test/resources/test-src/workers/invalid-receive-with-workers.bal @@ -14,7 +14,7 @@ // specific language governing permissions and limitations // under the License. -function invalidWorkReceiveBeforeWorker() { +function invalidWorkerReceiveBeforeWorker() { int _ = <- w1; worker w1 { int i = 1;