ballerina-lang
ballerina-lang copied to clipboard
[Bug]: BIRGen crashes for error binding pattern in `on fail` with multiple `check` expressions
Description
$title.
Steps to Reproduce
function f1(string str) {
do {
check f2();
check f2();
} on fail error error(message) {
}
}
function f2() returns error? {
}
[2024-04-04 15:53:03,017] SEVERE {b7a.log.crash} - null
java.lang.AssertionError
at org.wso2.ballerinalang.compiler.tree.BLangNodeVisitor.visit(BLangNodeVisitor.java:626)
at org.wso2.ballerinalang.compiler.tree.expressions.BLangSimpleVarRef.accept(BLangSimpleVarRef.java:65)
at org.wso2.ballerinalang.compiler.bir.BIRGen.createCall(BIRGen.java:1381)
at org.wso2.ballerinalang.compiler.bir.BIRGen.visit(BIRGen.java:1149)
at org.wso2.ballerinalang.compiler.tree.expressions.BLangInvocation.accept(BLangInvocation.java:128)
at org.wso2.ballerinalang.compiler.bir.BIRGen.visit(BIRGen.java:1097)
at org.wso2.ballerinalang.compiler.tree.statements.BLangSimpleVariableDef.accept(BLangSimpleVariableDef.java:50)
at org.wso2.ballerinalang.compiler.bir.BIRGen.visit(BIRGen.java:994)
at org.wso2.ballerinalang.compiler.tree.statements.BLangBlockStmt.accept(BLangBlockStmt.java:65)
at org.wso2.ballerinalang.compiler.bir.BIRGen.visit(BIRGen.java:994)
at org.wso2.ballerinalang.compiler.tree.statements.BLangBlockStmt.accept(BLangBlockStmt.java:65)
at org.wso2.ballerinalang.compiler.bir.BIRGen.visit(BIRGen.java:1159)
at org.wso2.ballerinalang.compiler.tree.expressions.BLangStatementExpression.accept(BLangStatementExpression.java:53)
at org.wso2.ballerinalang.compiler.bir.BIRGen.visit(BIRGen.java:1056)
at org.wso2.ballerinalang.compiler.tree.statements.BLangFail.accept(BLangFail.java:59)
at org.wso2.ballerinalang.compiler.bir.BIRGen.visit(BIRGen.java:994)
at org.wso2.ballerinalang.compiler.tree.statements.BLangBlockStmt.accept(BLangBlockStmt.java:65)
at org.wso2.ballerinalang.compiler.bir.BIRGen.visit(BIRGen.java:1535)
at org.wso2.ballerinalang.compiler.tree.statements.BLangIf.accept(BLangIf.java:60)
at org.wso2.ballerinalang.compiler.bir.BIRGen.visit(BIRGen.java:994)
at org.wso2.ballerinalang.compiler.tree.statements.BLangBlockStmt.accept(BLangBlockStmt.java:65)
at org.wso2.ballerinalang.compiler.bir.BIRGen.visit(BIRGen.java:1159)
at org.wso2.ballerinalang.compiler.tree.expressions.BLangStatementExpression.accept(BLangStatementExpression.java:53)
at org.wso2.ballerinalang.compiler.bir.BIRGen.visit(BIRGen.java:1137)
at org.wso2.ballerinalang.compiler.tree.statements.BLangExpressionStmt.accept(BLangExpressionStmt.java:51)
at org.wso2.ballerinalang.compiler.bir.BIRGen.visit(BIRGen.java:994)
at org.wso2.ballerinalang.compiler.tree.statements.BLangBlockStmt.accept(BLangBlockStmt.java:65)
at org.wso2.ballerinalang.compiler.bir.BIRGen.visit(BIRGen.java:744)
at org.wso2.ballerinalang.compiler.tree.BLangBlockFunctionBody.accept(BLangBlockFunctionBody.java:60)
at org.wso2.ballerinalang.compiler.bir.BIRGen.visit(BIRGen.java:704)
at org.wso2.ballerinalang.compiler.tree.BLangFunction.accept(BLangFunction.java:77)
at org.wso2.ballerinalang.compiler.bir.BIRGen.lambda$visit$5(BIRGen.java:352)
at java.base/java.util.ArrayList.forEach(ArrayList.java:1511)
at org.wso2.ballerinalang.compiler.bir.BIRGen.visit(BIRGen.java:352)
at org.wso2.ballerinalang.compiler.tree.BLangPackage.accept(BLangPackage.java:167)
at org.wso2.ballerinalang.compiler.bir.BIRGen.genBIR(BIRGen.java:292)
at io.ballerina.projects.internal.CompilerPhaseRunner.birGen(CompilerPhaseRunner.java:216)
at io.ballerina.projects.internal.CompilerPhaseRunner.performBirGenPhases(CompilerPhaseRunner.java:153)
at io.ballerina.projects.ModuleContext.generateCodeInternal(ModuleContext.java:454)
at io.ballerina.projects.ModuleCompilationState$4.generatePlatformSpecificCode(ModuleCompilationState.java:132)
at io.ballerina.projects.ModuleContext.generatePlatformSpecificCode(ModuleContext.java:387)
at io.ballerina.projects.JBallerinaBackend.performCodeGen(JBallerinaBackend.java:173)
at io.ballerina.projects.JBallerinaBackend.<init>(JBallerinaBackend.java:142)
at io.ballerina.projects.JBallerinaBackend.lambda$from$0(JBallerinaBackend.java:126)
at java.base/java.util.HashMap.computeIfAbsent(HashMap.java:1220)
at io.ballerina.projects.PackageCompilation.getCompilerBackend(PackageCompilation.java:176)
at io.ballerina.projects.JBallerinaBackend.from(JBallerinaBackend.java:125)
at io.ballerina.projects.JBallerinaBackend.from(JBallerinaBackend.java:113)
at io.ballerina.cli.task.CompileTask.execute(CompileTask.java:217)
at io.ballerina.cli.TaskExecutor.executeTasks(TaskExecutor.java:40)
at io.ballerina.cli.cmd.RunCommand.execute(RunCommand.java:250)
at java.base/java.util.Optional.ifPresent(Optional.java:178)
at io.ballerina.cli.launcher.Main.main(Main.java:58)
Affected Version(s)
Current master (U9-snapshot)
OS, DB, other environment details and versions
No response
Related area
-> Compilation
Related issue(s) (optional)
No response
Suggested label(s) (optional)
No response
Suggested assignee(s) (optional)
No response
Even with capture binding patterns, if we explicitly call a function like message() on the error value in a match statement, the backend crashes. This happens on U8 also.
function f1(string str) returns int {
do {
check f2(str);
check f2(str);
} on fail error e {
match e.message() {
"Error 1" => {
return 1;
}
}
}
return 2;
}
function f2(string str) returns error? => ();
[2024-04-08 15:06:42,108] SEVERE {b7a.log.crash} - Cannot read field "kind" because "moveIns.rhsOp.variableDcl" is null
java.lang.NullPointerException: Cannot read field "kind" because "moveIns.rhsOp.variableDcl" is null
at org.wso2.ballerinalang.compiler.bir.optimizer.BIROptimizer$RHSTempVarOptimizer.visit(BIROptimizer.java:157)
at org.wso2.ballerinalang.compiler.bir.model.BIRNode$BIRBasicBlock.accept(BIRNode.java:485)
at org.wso2.ballerinalang.compiler.bir.optimizer.BIROptimizer$RHSTempVarOptimizer.lambda$visit$3(BIROptimizer.java:119)
at java.base/java.util.ArrayList.forEach(ArrayList.java:1511)
at org.wso2.ballerinalang.compiler.bir.optimizer.BIROptimizer$RHSTempVarOptimizer.visit(BIROptimizer.java:119)
at org.wso2.ballerinalang.compiler.bir.model.BIRNode$BIRFunction.accept(BIRNode.java:432)
at org.wso2.ballerinalang.compiler.bir.optimizer.BIROptimizer$RHSTempVarOptimizer.lambda$visit$1(BIROptimizer.java:105)
at java.base/java.util.ArrayList.forEach(ArrayList.java:1511)
at org.wso2.ballerinalang.compiler.bir.optimizer.BIROptimizer$RHSTempVarOptimizer.visit(BIROptimizer.java:105)
at org.wso2.ballerinalang.compiler.bir.model.BIRNode$BIRPackage.accept(BIRNode.java:89)
at org.wso2.ballerinalang.compiler.bir.optimizer.BIROptimizer.optimizePackage(BIROptimizer.java:82)
at org.wso2.ballerinalang.compiler.bir.BIRGen.genBIR(BIRGen.java:291)
at io.ballerina.projects.internal.CompilerPhaseRunner.birGen(CompilerPhaseRunner.java:220)
at io.ballerina.projects.internal.CompilerPhaseRunner.performBirGenPhases(CompilerPhaseRunner.java:157)
at io.ballerina.projects.ModuleContext.generateCodeInternal(ModuleContext.java:454)
at io.ballerina.projects.ModuleCompilationState$4.generatePlatformSpecificCode(ModuleCompilationState.java:132)
at io.ballerina.projects.ModuleContext.generatePlatformSpecificCode(ModuleContext.java:387)
at io.ballerina.projects.JBallerinaBackend.performCodeGen(JBallerinaBackend.java:174)
at io.ballerina.projects.JBallerinaBackend.<init>(JBallerinaBackend.java:143)
at io.ballerina.projects.JBallerinaBackend.lambda$from$0(JBallerinaBackend.java:121)
at java.base/java.util.HashMap.computeIfAbsent(HashMap.java:1220)
at io.ballerina.projects.PackageCompilation.getCompilerBackend(PackageCompilation.java:176)
at io.ballerina.projects.JBallerinaBackend.from(JBallerinaBackend.java:120)
at io.ballerina.cli.task.CompileTask.execute(CompileTask.java:201)
at io.ballerina.cli.TaskExecutor.executeTasks(TaskExecutor.java:40)
at io.ballerina.cli.cmd.RunCommand.execute(RunCommand.java:223)
at java.base/java.util.Optional.ifPresent(Optional.java:178)
at io.ballerina.cli.launcher.Main.main(Main.java:58)
The error BP has been temporarily disallowed on the U9 branch via https://github.com/ballerina-platform/ballerina-lang/pull/42503.
Need to also address https://github.com/ballerina-platform/ballerina-lang/blob/2201.9.x/tests/jballerina-unit-test/src/test/resources/test-src/statements/onfail/on-fail-clause.bal#L591 when reverting the changes in that PR.
We have tried a few approaches:
-
Generate a separate function for statements within the on-fail clause. This method allows to desugar only once for the on-fail clause, but creating this function is complex, due to that we move away from this approach.
-
Clone the type binding and use it within the on-fail clause. While this seemed promising, we encountered some issues with this approach. The proposed solution is mentioned in the following doc.https://docs.google.com/document/d/1Dy7WLP7Ne8lqUKzIF89TYskf_8KmaBLLfb4XZypP7mw/edit?usp=sharing
With this task, we identified that the Do on-fail within the Query Action isn't desugared correctly. This needs to be addressed first to resolve the issue as well. https://github.com/ballerina-platform/ballerina-lang/issues/42632
This exception can be seen here too.
public function main() {
var r = {name:"John", nums: [1, 2, 3]};
record {|string name; int[] nums;|} {nums: [...numbers]} = r;
doSomething(numbers);
}
function doSomething(any value) {
}
Exception Details
[2024-07-23 15:15:10,338] SEVERE {b7a.log.crash} - Cannot read field "kind" because "moveIns.rhsOp.variableDcl" is null
java.lang.NullPointerException: Cannot read field "kind" because "moveIns.rhsOp.variableDcl" is null
at org.wso2.ballerinalang.compiler.bir.optimizer.BIROptimizer$RHSTempVarOptimizer.visit(BIROptimizer.java:169)
at org.wso2.ballerinalang.compiler.bir.model.BIRNode$BIRBasicBlock.accept(BIRNode.java:485)
at org.wso2.ballerinalang.compiler.bir.optimizer.BIROptimizer$RHSTempVarOptimizer.lambda$visit$3(BIROptimizer.java:131)
at java.base/java.util.ArrayList.forEach(ArrayList.java:1511)
at org.wso2.ballerinalang.compiler.bir.optimizer.BIROptimizer$RHSTempVarOptimizer.visit(BIROptimizer.java:131)
at org.wso2.ballerinalang.compiler.bir.model.BIRNode$BIRFunction.accept(BIRNode.java:432)
at org.wso2.ballerinalang.compiler.bir.optimizer.BIROptimizer$RHSTempVarOptimizer.lambda$visit$1(BIROptimizer.java:117)
at java.base/java.util.ArrayList.forEach(ArrayList.java:1511)
at org.wso2.ballerinalang.compiler.bir.optimizer.BIROptimizer$RHSTempVarOptimizer.visit(BIROptimizer.java:117)
at org.wso2.ballerinalang.compiler.bir.model.BIRNode$BIRPackage.accept(BIRNode.java:89)
at org.wso2.ballerinalang.compiler.bir.optimizer.BIROptimizer.optimizePackage(BIROptimizer.java:89)
at org.wso2.ballerinalang.compiler.bir.BIRGen.genBIR(BIRGen.java:294)
at io.ballerina.projects.internal.CompilerPhaseRunner.birGen(CompilerPhaseRunner.java:216)
at io.ballerina.projects.internal.CompilerPhaseRunner.performBirGenPhases(CompilerPhaseRunner.java:153)
at io.ballerina.projects.ModuleContext.generateCodeInternal(ModuleContext.java:454)
at io.ballerina.projects.ModuleCompilationState$4.generatePlatformSpecificCode(ModuleCompilationState.java:132)
at io.ballerina.projects.ModuleContext.generatePlatformSpecificCode(ModuleContext.java:387)
at io.ballerina.projects.JBallerinaBackend.performCodeGen(JBallerinaBackend.java:173)
at io.ballerina.projects.JBallerinaBackend.<init>(JBallerinaBackend.java:142)
at io.ballerina.projects.JBallerinaBackend.lambda$from$0(JBallerinaBackend.java:126)
at java.base/java.util.HashMap.computeIfAbsent(HashMap.java:1220)
at io.ballerina.projects.PackageCompilation.getCompilerBackend(PackageCompilation.java:179)
at io.ballerina.projects.JBallerinaBackend.from(JBallerinaBackend.java:125)
at io.ballerina.projects.JBallerinaBackend.from(JBallerinaBackend.java:113)
at io.ballerina.cli.task.CompileTask.execute(CompileTask.java:219)
at io.ballerina.cli.TaskExecutor.executeTasks(TaskExecutor.java:40)
at io.ballerina.cli.cmd.RunCommand.execute(RunCommand.java:254)
at java.base/java.util.Optional.ifPresent(Optional.java:178)
at io.ballerina.cli.launcher.Main.main(Main.java:58)
ERROR [.:(1:1,1:1)] Compilation failed due to: Cannot read field "kind" because "moveIns.rhsOp.variableDcl" is null
error: compilation contains errors
This exception can be seen here too.
public function main() { var r = {name:"John", nums: [1, 2, 3]}; record {|string name; int[] nums;|} {nums: [...numbers]} = r; doSomething(numbers); } function doSomething(any value) { }Exception Details
The rest variable symbol is not getting defined properly and not getting appended to the symbolVarMap in
https://github.com/dulajdilshan/ballerina-lang/blob/e1e2be1af6c6e37c45dc8c659610c98214dadfd7/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/bir/BIRGen.java#L1892