Skip to content

Commit

Permalink
Fix compiler crash when union in multiple wait
Browse files Browse the repository at this point in the history
  • Loading branch information
SasinduDilshara committed Oct 11, 2022
1 parent 00388bb commit 4050f89
Show file tree
Hide file tree
Showing 5 changed files with 101 additions and 4 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -4648,6 +4655,12 @@ private void setEventualTypeForExpression(BLangExpression expression,
if (isSimpleWorkerReference(expression, data)) {
return;
}
if (expression.expectedType.tag != TypeTags.FUTURE) {
dlog.error(expression.pos, DiagnosticErrorCode.INCOMPATIBLE_TYPE_WAIT_FUTURE_EXPR,
symTable.futureType, expression.expectedType, expression);
return;
}

BFutureType futureType = (BFutureType) expression.expectedType;
BType currentType = futureType.constraint;
if (types.containsErrorType(currentType)) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
Original file line number Diff line number Diff line change
Expand Up @@ -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(), 45, "Wait actions negative test error count");
BAssertUtil.validateError(resultNegative, index++,
"incompatible types: expected 'future<string>', found 'future<int>'", 56, 22);
BAssertUtil.validateError(resultNegative, index++,
Expand Down Expand Up @@ -143,9 +142,36 @@ public void testNegativeWorkerActions() {
"expression 'f2'", 90, 45);
BAssertUtil.validateError(resultNegative, index++,
"incompatible types: expected 'future<string>', found 'future<(int|error)>'", 90, 54);
BAssertUtil.validateError(resultNegative, index,
BAssertUtil.validateError(resultNegative, index++,
"incompatible types: expected 'string', found eventual type '(string|error)' for wait future " +
"expression 'f4'", 90, 54);
BAssertUtil.validateError(resultNegative, index++,
"alternative wait action not yet support inside multiple wait expressions",
123, 38);
BAssertUtil.validateError(resultNegative, index++,
"alternative wait action not yet support inside multiple wait expressions",
124, 48);
BAssertUtil.validateError(resultNegative, index++,
"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<(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<boolean>|future<boolean>)' 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<boolean>|future<boolean>)' for wait future expression 'y'", 143, 40 );
Assert.assertEquals(resultNegative.getErrorCount(), index, "Wait actions negative test error count");
}

@Test
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,59 @@ function waitForAllTest() {
restRec2 result16 = wait {id: f1, name: f2, age: f4};
}

type WaitResult record {|
boolean|error producer;
boolean consumer;
|};

function waitForAllTest2() {
worker Producer1 returns boolean|error {
int i = 100;
i -> Consumer;
error? unionResult = flush Consumer1;
return true;
}

worker Producer2 returns boolean|error {
int i = 100;
i -> Consumer;
error? unionResult = flush Consumer1;
return true;
}

worker Consumer1 returns boolean {
int i = <- Producer;
return false;
}

worker Consumer2 returns boolean {
int i = <- Producer;
return false;
}

WaitResult res = wait {producer: Producer1|Producer2, consumer: Consumer1};
res = wait {producer: Producer1, consumer: Consumer1|Consumer2};
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<boolean|error>|future<boolean|error> x = Producer1;
future<boolean>|future<boolean> 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();
}
Expand Down

0 comments on commit 4050f89

Please sign in to comment.