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 30c2a4ed5760..7a419f07ed14 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 @@ -777,7 +777,9 @@ public enum DiagnosticErrorCode implements DiagnosticCode { "unsupported.computed.resource.access.path.segment.type"), UNSUPPORTED_RESOURCE_ACCESS_REST_SEGMENT_TYPE("BCE4032", "unsupported.resource.access.rest.segment.type"), INVALID_RESOURCE_METHOD_RETURN_TYPE("BCE4033", "invalid.resource.method.return.type"), - OUT_OF_RANGE("BCE4034", "numeric.literal.out.of.range") + OUT_OF_RANGE("BCE4034", "numeric.literal.out.of.range"), + ALTERNATIVE_WAIT_ACTION_NOT_SUPPORTED_IN_MULTIPLE_WAIT_EXPRESSION("BCE4035", + "unsupported.alternative.wait.action.in.multiple.wait.expr") ; private String diagnosticId; diff --git a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/analyzer/TypeChecker.java b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/analyzer/TypeChecker.java index f07668c01196..7f1144f6622e 100644 --- a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/analyzer/TypeChecker.java +++ b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/analyzer/TypeChecker.java @@ -4586,7 +4586,14 @@ private void checkTypesForRecords(BLangWaitForAllExpr waitExpr, AnalyzerData dat for (BLangWaitForAllExpr.BLangWaitKeyValue keyVal : rhsFields) { String key = keyVal.key.value; - if (!lhsFields.containsKey(key)) { + BLangExpression valueExpr = keyVal.valueExpr; + if (valueExpr instanceof BLangBinaryExpr + && ((BLangBinaryExpr) valueExpr).opKind == OperatorKind.BITWISE_OR) { + dlog.error(valueExpr.pos, + DiagnosticErrorCode.ALTERNATIVE_WAIT_ACTION_NOT_SUPPORTED_IN_MULTIPLE_WAIT_EXPRESSION); + data.resultType = symTable.semanticError; + } + else if (!lhsFields.containsKey(key)) { // Check if the field is sealed if so you cannot have dynamic fields if (((BRecordType) Types.getReferredType(data.expType)).sealed) { dlog.error(waitExpr.pos, DiagnosticErrorCode.INVALID_FIELD_NAME_RECORD_LITERAL, key, data.expType); diff --git a/compiler/ballerina-lang/src/main/resources/compiler.properties b/compiler/ballerina-lang/src/main/resources/compiler.properties index 57fda6a73c8a..a4b721cee925 100644 --- a/compiler/ballerina-lang/src/main/resources/compiler.properties +++ b/compiler/ballerina-lang/src/main/resources/compiler.properties @@ -1919,3 +1919,6 @@ error.unsupported.computed.resource.access.path.segment.type=\ error.unsupported.resource.access.rest.segment.type=\ unsupported resource access rest segment type: expected array of ''int'', ''string'', ''float'', ''boolean'',\ ''decimal'' but found ''{0}'' + +error.unsupported.alternative.wait.action.in.multiple.wait.expr=\ + alternative wait action not yet support inside multiple wait expressions diff --git a/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/worker/WaitActionsNegativeTest.java b/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/worker/WaitActionsNegativeTest.java index 17239a4cebe3..16eb93fc6da4 100644 --- a/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/worker/WaitActionsNegativeTest.java +++ b/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/worker/WaitActionsNegativeTest.java @@ -33,7 +33,6 @@ public class WaitActionsNegativeTest { public void testNegativeWorkerActions() { CompileResult resultNegative = BCompileUtil.compile("test-src/workers/wait-actions-negative.bal"); int index = 0; - Assert.assertEquals(resultNegative.getErrorCount(), 49, "Wait actions negative test error count"); BAssertUtil.validateError(resultNegative, index++, "incompatible types: expected 'future', found 'future'", 56, 22); BAssertUtil.validateError(resultNegative, index++, @@ -147,21 +146,32 @@ public void testNegativeWorkerActions() { "incompatible types: expected 'string', found eventual type '(string|error)' for wait future " + "expression 'f4'", 90, 54); BAssertUtil.validateError(resultNegative, index++, - "incompatible types: expected 'future<(any|error)>', found eventual type " + - "'(future<(boolean|error)>|future<(boolean|error)>)' for wait future expression " + - "'Producer1 | Producer2'", 123, 38); + "alternative wait action not yet support inside multiple wait expressions", + 123, 38); BAssertUtil.validateError(resultNegative, index++, - "incompatible types: expected 'future<(any|error)>', found eventual type " + - "'(future|future)' for wait future expression " + - "'Consumer1 | Consumer2'", 124, 48); + "alternative wait action not yet support inside multiple wait expressions", + 124, 48); BAssertUtil.validateError(resultNegative, index++, - "incompatible types: expected 'future<(any|error)>', found eventual type " + - "'(future<(boolean|error)>|future<(boolean|error)>)' for wait future expression " + - "'Producer1 | Producer2'", 125, 27); + "alternative wait action not yet support inside multiple wait expressions", + 125, 27); + BAssertUtil.validateError(resultNegative, index++, + "alternative wait action not yet support inside multiple wait expressions", + 125, 58); BAssertUtil.validateError(resultNegative, index++, "incompatible types: expected 'future<(any|error)>', found eventual type " + - "'(future|future)' for wait future expression " + - "'Consumer1 | Consumer2'", 125, 58); + "'(future<(boolean|error)>|future<(boolean|error)>)' for wait" + + " future expression 'x'", 141, 38); + BAssertUtil.validateError(resultNegative, index++, + "incompatible types: expected 'future<(any|error)>', found eventual type" + + " '(future|future)' for wait future expression 'y'", 142, 48); + BAssertUtil.validateError(resultNegative, index++, + "incompatible types: expected 'future<(any|error)>', found eventual type" + + " '(future<(boolean|error)>|future<(boolean|error)>)' for" + + " wait future expression 'x'", 143, 27); + BAssertUtil.validateError(resultNegative, index++, + "incompatible types: expected 'future<(any|error)>', found eventual type" + + " '(future|future)' for wait future expression 'y'", 143, 40 ); + Assert.assertEquals(resultNegative.getErrorCount(), index, "Wait actions negative test error count"); } @Test diff --git a/tests/jballerina-unit-test/src/test/resources/test-src/workers/wait-actions-negative.bal b/tests/jballerina-unit-test/src/test/resources/test-src/workers/wait-actions-negative.bal index 0959c92afe1a..83f49c1226a6 100644 --- a/tests/jballerina-unit-test/src/test/resources/test-src/workers/wait-actions-negative.bal +++ b/tests/jballerina-unit-test/src/test/resources/test-src/workers/wait-actions-negative.bal @@ -125,6 +125,24 @@ function waitForAllTest2() { res = wait {producer: Producer1|Producer2, consumer: Consumer1|Consumer2}; } +function waitActionWithInvalidType() { + worker Producer1 returns boolean|error { + return true; + } + + worker Consumer1 returns boolean { + int i = <- Producer; + return false; + } + + future|future x = Producer1; + future|future y = Consumer1; + + WaitResult res = wait {producer: x, consumer: Consumer1}; + res = wait {producer: Producer1, consumer: y}; + res = wait {producer: x, consumer: y}; +} + function print(string str) { string result = str.toUpperAscii(); }