-
Notifications
You must be signed in to change notification settings - Fork 758
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[WIP] Support constant spread-list-member
within the keys of a table
#42388
Conversation
spread-list-member
within the keys of a tablespread-list-member
within the keys of a table
Codecov ReportAttention: Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## master #42388 +/- ##
=========================================
Coverage 76.50% 76.50%
- Complexity 53178 53183 +5
=========================================
Files 2892 2892
Lines 201004 201004
Branches 26188 26189 +1
=========================================
+ Hits 153771 153782 +11
+ Misses 38772 38762 -10
+ Partials 8461 8460 -1 ☔ View full report in Codecov by Sentry. |
...-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/analyzer/DataflowAnalyzer.java
Show resolved
Hide resolved
} else { | ||
dlog.error(((BLangExpression) node).pos, DiagnosticErrorCode.EXPRESSION_IS_NOT_A_CONSTANT_EXPRESSION); | ||
dlog.error(node.getPosition(), DiagnosticErrorCode.EXPRESSION_IS_NOT_A_CONSTANT_EXPRESSION); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since there's a codecov warning, can we check if we have tests for this?
We can add a test with a non-const spread expression too.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
AFAIK, this line was added as a fail-safe mechanism, and all non-constant expressions are handled through:
Line 1516 in 5c364c4
private boolean isConstExpression(BLangExpression expression) { |
We also have negative tests for each non-constant spread expression.
ballerina-lang/tests/jballerina-unit-test/src/test/resources/test-src/types/table/table-negative.bal
Line 588 in e3f55f4
{k: [12, ...intArr], value: 17} |
} else if (node.getKind() == NodeKind.LIST_CONSTRUCTOR_SPREAD_OP) { | ||
result = 31 * result + hash(((BLangListConstructorExpr.BLangListConstructorSpreadOpExpr) node).expr); | ||
} else if (node.getKind() == NodeKind.RECORD_LITERAL_SPREAD_OP) { | ||
result = 31 * result + hash(((BLangRecordLiteral.BLangRecordSpreadOperatorField) node).expr); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Case 1 - These wouldn't be correct/sufficient with something like
type Row record {|
readonly int[]|int[][] k;
int value;
|};
const int[] INT_ARR = [1, 2];
public function main() {
table<Row> key (k) _ = table [
{k: [...INT_ARR], value: 0},
{k: [INT_ARR], value: 0}
];
}
right?
Crashes anyway
[2024-03-25 11:10:41,566] SEVERE {b7a.log.crash} - Cannot read field "tag" because the return value of "org.wso2.ballerinalang.compiler.semantics.analyzer.Types.getImpliedType(org.wso2.ballerinalang.compiler.semantics.model.types.BType)" is null
java.lang.NullPointerException: Cannot read field "tag" because the return value of "org.wso2.ballerinalang.compiler.semantics.analyzer.Types.getImpliedType(org.wso2.ballerinalang.compiler.semantics.model.types.BType)" is null
at org.wso2.ballerinalang.compiler.semantics.analyzer.Types.isValueType(Types.java:443)
at org.wso2.ballerinalang.compiler.semantics.analyzer.Types.isSameType(Types.java:422)
at org.wso2.ballerinalang.compiler.semantics.analyzer.Types.isSameType(Types.java:385)
at org.wso2.ballerinalang.compiler.semantics.analyzer.Types.isAssignable(Types.java:858)
at org.wso2.ballerinalang.compiler.semantics.analyzer.Types.isAssignable(Types.java:846)
at org.wso2.ballerinalang.compiler.semantics.analyzer.DataflowAnalyzer.getTypeEquality(DataflowAnalyzer.java:1530)
at org.wso2.ballerinalang.compiler.semantics.analyzer.DataflowAnalyzer.equality(DataflowAnalyzer.java:1286)
at org.wso2.ballerinalang.compiler.semantics.analyzer.DataflowAnalyzer.checkForKeyEquality(DataflowAnalyzer.java:1139)
at org.wso2.ballerinalang.compiler.semantics.analyzer.DataflowAnalyzer.checkForDuplicateKeys(DataflowAnalyzer.java:1122)
at org.wso2.ballerinalang.compiler.semantics.analyzer.DataflowAnalyzer.visit(DataflowAnalyzer.java:1111)
at org.wso2.ballerinalang.compiler.tree.expressions.BLangTableConstructorExpr.accept(BLangTableConstructorExpr.java:70)
at org.wso2.ballerinalang.compiler.semantics.analyzer.DataflowAnalyzer.analyzeNode(DataflowAnalyzer.java:2532)
at org.wso2.ballerinalang.compiler.semantics.analyzer.DataflowAnalyzer.visit(DataflowAnalyzer.java:690)
at org.wso2.ballerinalang.compiler.tree.BLangSimpleVariable.accept(BLangSimpleVariable.java:54)
at org.wso2.ballerinalang.compiler.semantics.analyzer.DataflowAnalyzer.analyzeNode(DataflowAnalyzer.java:2532)
at org.wso2.ballerinalang.compiler.semantics.analyzer.DataflowAnalyzer.visit(DataflowAnalyzer.java:653)
at org.wso2.ballerinalang.compiler.tree.statements.BLangSimpleVariableDef.accept(BLangSimpleVariableDef.java:50)
at org.wso2.ballerinalang.compiler.semantics.analyzer.DataflowAnalyzer.analyzeNode(DataflowAnalyzer.java:2532)
at org.wso2.ballerinalang.compiler.semantics.analyzer.DataflowAnalyzer.visit(DataflowAnalyzer.java:472)
at org.wso2.ballerinalang.compiler.tree.BLangBlockFunctionBody.accept(BLangBlockFunctionBody.java:60)
at org.wso2.ballerinalang.compiler.semantics.analyzer.DataflowAnalyzer.analyzeNode(DataflowAnalyzer.java:2532)
at org.wso2.ballerinalang.compiler.semantics.analyzer.DataflowAnalyzer.analyzeBranch(DataflowAnalyzer.java:2500)
at org.wso2.ballerinalang.compiler.semantics.analyzer.DataflowAnalyzer.visit(DataflowAnalyzer.java:429)
at org.wso2.ballerinalang.compiler.tree.BLangFunction.accept(BLangFunction.java:76)
at org.wso2.ballerinalang.compiler.semantics.analyzer.DataflowAnalyzer.analyzeNode(DataflowAnalyzer.java:2532)
at org.wso2.ballerinalang.compiler.semantics.analyzer.DataflowAnalyzer.visit(DataflowAnalyzer.java:344)
at org.wso2.ballerinalang.compiler.tree.BLangPackage.accept(BLangPackage.java:167)
at org.wso2.ballerinalang.compiler.semantics.analyzer.DataflowAnalyzer.analyzeNode(DataflowAnalyzer.java:2532)
at org.wso2.ballerinalang.compiler.semantics.analyzer.DataflowAnalyzer.analyze(DataflowAnalyzer.java:314)
at io.ballerina.projects.internal.CompilerPhaseRunner.dataflowAnalyze(CompilerPhaseRunner.java:196)
at io.ballerina.projects.internal.CompilerPhaseRunner.performTypeCheckPhases(CompilerPhaseRunner.java:120)
at io.ballerina.projects.ModuleContext.compileInternal(ModuleContext.java:435)
at io.ballerina.projects.ModuleCompilationState$1.compile(ModuleCompilationState.java:45)
at io.ballerina.projects.ModuleContext.compile(ModuleContext.java:383)
at io.ballerina.projects.PackageCompilation.compileModulesInternal(PackageCompilation.java:208)
at io.ballerina.projects.PackageCompilation.compileModules(PackageCompilation.java:192)
at io.ballerina.projects.PackageCompilation.compile(PackageCompilation.java:99)
at io.ballerina.projects.PackageCompilation.from(PackageCompilation.java:94)
at io.ballerina.projects.PackageContext.getPackageCompilation(PackageContext.java:243)
at io.ballerina.projects.Package.getCompilation(Package.java:150)
at io.ballerina.projects.Package.runCodeGeneratorPlugins(Package.java:323)
at io.ballerina.cli.task.CompileTask.execute(CompileTask.java:144)
at io.ballerina.cli.TaskExecutor.executeTasks(TaskExecutor.java:40)
at io.ballerina.cli.cmd.RunCommand.execute(RunCommand.java:247)
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 "tag" because the return value of "org.wso2.ballerinalang.compiler.semantics.analyzer.Types.getImpliedType(org.wso2.ballerinalang.compiler.semantics.model.types.BType)" is null
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also crashes for
type Row record {|
readonly int[] k;
int value;
|};
const int[] INT_ARR = [1, 2];
public function main() {
table<Row> key (k) _ = table [
{k: [...INT_ARR], value: 0},
{k: [...INT_ARR], value: 0}
];
}
} else if (node.getKind() == NodeKind.LIST_CONSTRUCTOR_SPREAD_OP) { | ||
result = 31 * result + hash(((BLangListConstructorExpr.BLangListConstructorSpreadOpExpr) node).expr); | ||
} else if (node.getKind() == NodeKind.RECORD_LITERAL_SPREAD_OP) { | ||
result = 31 * result + hash(((BLangRecordLiteral.BLangRecordSpreadOperatorField) node).expr); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Case 2 - same key isn't detected at compile-time when one is via spread and the other is via values defined directly.
type Row record {|
readonly int[] k;
int value;
|};
const int[] INT_ARR = [1, 2];
public function main() {
table<Row> key (k) _ = table [
{k: [...INT_ARR], value: 0},
{k: [1, 2], value: 0}
];
}
Fails at runtime instead.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this is not specific to the spread op. The same concern can be reproduced with a simple constant, and the 'duplicate key' error is not generated at compile time.
type Row record {|
readonly int k;
int value;
|};
const VAL = 1;
public function main() {
table<Row> key (k) _ = table [
{k: 1, value: 0},
{k: VAL, value: 0}
];
}
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Appears that this is a known issue: #35584
This PR has been open for more than 15 days with no activity. This will be closed in 3 days unless the |
This PR has been open for more than 15 days with no activity. This will be closed in 3 days unless the |
This PR has been open for more than 15 days with no activity. This will be closed in 3 days unless the |
spread-list-member
within the keys of a tablespread-list-member
within the keys of a table
This PR has been open for more than 15 days with no activity. This will be closed in 3 days unless the |
This PR has been open for more than 15 days with no activity. This will be closed in 3 days unless the |
This PR has been open for more than 15 days with no activity. This will be closed in 3 days unless the |
This PR has been open for more than 15 days with no activity. This will be closed in 3 days unless the |
This PR has been open for more than 15 days with no activity. This will be closed in 3 days unless the |
This PR has been open for more than 15 days with no activity. This will be closed in 3 days unless the |
This PR has been open for more than 15 days with no activity. This will be closed in 3 days unless the |
Need to revisit the design again. Till then we will be closing this PR. |
Purpose
As mentioned in the spec, structural constructors are allowed as long as their subexpressions are also constant. However, as mentioned in #41979, an invalid diagnostic is produced when a
spread-list-member
is within such constructors.Related to: #41992
Fixes #41979
Check List