diff --git a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/analyzer/SemanticAnalyzer.java b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/analyzer/SemanticAnalyzer.java index 67f01278ceb9..8d0def98b32d 100644 --- a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/analyzer/SemanticAnalyzer.java +++ b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/analyzer/SemanticAnalyzer.java @@ -2103,7 +2103,9 @@ void handleDeclaredVarInForeach(BLangVariable variable, BType rhsType, SymbolEnv BLangErrorVariable errorVariable = (BLangErrorVariable) variable; errorVariable.setBType(rhsType); if (TypeTags.ERROR != referredRhsType.tag) { - dlog.error(variable.pos, DiagnosticErrorCode.INVALID_TYPE_DEFINITION_FOR_ERROR_VAR, rhsType); + if (referredRhsType != symTable.semanticError) { + dlog.error(variable.pos, DiagnosticErrorCode.INVALID_TYPE_DEFINITION_FOR_ERROR_VAR, rhsType); + } recursivelyDefineVariables(errorVariable, blockEnv); return; } @@ -3883,9 +3885,12 @@ public void visit(BLangOnFailClause onFailClause, AnalyzerData data) { onFailEnv); BLangVariable onFailVarNode = (BLangVariable) onFailVarDefNode.getVariable(); - if (onFailVarNode.getBType() != null && !types.isAssignable(onFailVarNode.getBType(), symTable.errorType)) { + BType onFailVarNodeBType = onFailVarNode.getBType(); + if (onFailVarNodeBType != null && + onFailVarNodeBType != symTable.semanticError && + !types.isAssignable(onFailVarNodeBType, symTable.errorType)) { dlog.error(onFailVarNode.pos, DiagnosticErrorCode.INVALID_TYPE_DEFINITION_FOR_ERROR_VAR, - onFailVarNode.getBType()); + onFailVarNodeBType); } if (kind == NodeKind.ERROR_VARIABLE) { @@ -3975,9 +3980,12 @@ public void visit(BLangFail failNode, AnalyzerData data) { BType errorExpressionType = typeChecker.checkExpr(errorExpression, data.env, data.prevEnvs, data.commonAnalyzerData); if (!data.commonAnalyzerData.errorTypes.empty()) { - data.commonAnalyzerData.errorTypes.peek().add(types.getErrorTypes(failNode.expr.getBType())); + BType failExprType = failNode.expr.getBType(); + if (failExprType != symTable.semanticError) { + data.commonAnalyzerData.errorTypes.peek().add(types.getErrorTypes(failExprType)); + } } - if (errorExpressionType == symTable.semanticError || + if (errorExpressionType != symTable.semanticError && !types.isSubTypeOfBaseType(errorExpressionType, symTable.errorType.tag)) { dlog.error(errorExpression.pos, DiagnosticErrorCode.ERROR_TYPE_EXPECTED, errorExpressionType); } diff --git a/compiler/ballerina-lang/src/main/resources/compiler.properties b/compiler/ballerina-lang/src/main/resources/compiler.properties index 638a94c66457..76166a081ed6 100644 --- a/compiler/ballerina-lang/src/main/resources/compiler.properties +++ b/compiler/ballerina-lang/src/main/resources/compiler.properties @@ -1349,7 +1349,7 @@ error.order.by.not.supported=\ order by not supported for complex type fields, order key should belong to a basic type error.error.type.expected = \ - type ''{0}'' not allowed here; expected an ''error'' or a subtype of ''error''. + type ''{0}'' not allowed here; expected an ''error'' or a subtype of ''error'' error.invalid.table.constraint.subtype = \ invalid constraint type. expected subtype of ''map'' but found ''{0}'' diff --git a/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/statements/dostatement/DoStmtsTest.java b/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/statements/dostatement/DoStmtsTest.java index 44155d88cf67..1bba7419d44d 100644 --- a/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/statements/dostatement/DoStmtsTest.java +++ b/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/statements/dostatement/DoStmtsTest.java @@ -75,7 +75,7 @@ public void testNegativeUnreachable() { public void testNegative2() { int index = 0; BAssertUtil.validateError(negativeFile2, index++, "type 'string' not allowed here; " + - "expected an 'error' or a subtype of 'error'.", 6, 11); + "expected an 'error' or a subtype of 'error'", 6, 11); BAssertUtil.validateError(negativeFile2, index++, "incompatible types: expected " + "'other', found 'string'", 8, 12); BAssertUtil.validateError(negativeFile2, index++, "invalid error variable; expecting " + diff --git a/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/statements/fail/FailStmtTest.java b/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/statements/fail/FailStmtTest.java index 7fb94fec069d..bf7bb43d8bfd 100644 --- a/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/statements/fail/FailStmtTest.java +++ b/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/statements/fail/FailStmtTest.java @@ -60,7 +60,7 @@ public void testFailActionNegative() { int index = 0; validateError(negativeResult, index++, - "type '(error|int)' not allowed here; expected an 'error' or a subtype of 'error'.", + "type '(error|int)' not allowed here; expected an 'error' or a subtype of 'error'", 5, 10); } diff --git a/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/statements/onfail/OnFailClauseTest.java b/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/statements/onfail/OnFailClauseTest.java index e028fb8a99cc..c0cdea71cbe0 100644 --- a/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/statements/onfail/OnFailClauseTest.java +++ b/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/statements/onfail/OnFailClauseTest.java @@ -98,6 +98,13 @@ public void testOnFailClauseNegativeCaseV1() { "type but found '(SampleComplexError|SampleError)' in type definition", 117, 15); BAssertUtil.validateError(negativeResult, i++, "incompatible types: expected '(Error2|error)', found " + "'Error1'", 132, 15); + BAssertUtil.validateError(negativeResult, i++, "type 'int?' not allowed here; expected an 'error' or a " + + "subtype of 'error'", 141, 14); + BAssertUtil.validateError(negativeResult, i++, "type 'int?' not allowed here; expected an 'error' or a " + + "subtype of 'error'", 150, 14); + BAssertUtil.validateError(negativeResult, i++, "undefined symbol 'e'", 158, 14); + BAssertUtil.validateError(negativeResult, i++, "undefined symbol 'e'", 166, 14); + BAssertUtil.validateError(negativeResult, i++, "redeclared symbol 'm'", 176, 25); Assert.assertEquals(negativeResult.getErrorCount(), i); } diff --git a/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/types/stream/BStreamValueTest.java b/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/types/stream/BStreamValueTest.java index 7d4a90ced036..1e3b4897b8ca 100644 --- a/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/types/stream/BStreamValueTest.java +++ b/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/types/stream/BStreamValueTest.java @@ -254,7 +254,7 @@ public void testStreamTypeNegative() { "of 'object { public isolated function next() returns record {| int value; |}?; }', but found " + "'string'", 381, 31); BAssertUtil.validateError(negativeResult, i++, "type 'readonly' not allowed here; " + - "expected an 'error' or a subtype of 'error'.", 387, 31); + "expected an 'error' or a subtype of 'error'", 387, 31); BAssertUtil.validateError(negativeResult, i++, "no stream constructor provided. " + "expected a subtype of 'object { public isolated function next() " + "returns (record {| int value; |}|error); }'", 389, 28); diff --git a/tests/jballerina-unit-test/src/test/resources/test-src/statements/onfail/on-fail-clause-negative.bal b/tests/jballerina-unit-test/src/test/resources/test-src/statements/onfail/on-fail-clause-negative.bal index 384b74391ca3..44e25df50622 100644 --- a/tests/jballerina-unit-test/src/test/resources/test-src/statements/onfail/on-fail-clause-negative.bal +++ b/tests/jballerina-unit-test/src/test/resources/test-src/statements/onfail/on-fail-clause-negative.bal @@ -134,3 +134,46 @@ function functionWithCheckpanicInDoClauseNegative() { } function fn() returns int|Error1 => 1; + +function f1() { + int? e = 10; + do { + fail e; + } on fail var m { + + } +} + +function f2() { + int? e = 10; + do { + fail e; + } on fail var error(m) { + + } +} + +function f3() { + do { + fail e; + } on fail var m { + + } +} + +function f4() { + do { + fail e; + } on fail error error(m) { + + } +} + +function f5() { + string m = "str"; + do { + fail error(m); + } on fail var error(m) { + + } +}