ballerina-lang
ballerina-lang copied to clipboard
[Bug]: Getting `Symbol is 'null'`and fail whenever executes Semantic APIs in compiler extension in package 'ballerina:sql:1.12.0'
Description
The ballerina source code would not compile. error: compilation failed: The compiler extension in package 'ballerina:sql:1.12.0' failed to complete. Symbol is 'null'
error: compilation failed: The compiler extension in package 'ballerina:sql:1.12.0' failed to complete. Symbol is 'null'
Steps to Reproduce
Affected Version(s)
2201.8.4 and 2201.8.6. Probably version 8
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
What happens in the Semantic API internally is we are trying to get the symbol from the in the definition() of BallerinaTypeReferenceTypeSymvol, it getts null in the symbol.
https://github.com/ballerina-platform/ballerina-lang/blob/254d5cd94649e179fabf0d8d254192785d7b17ce/compiler/ballerina-lang/src/main/java/io/ballerina/compiler/api/impl/symbols/BallerinaTypeReferenceTypeSymbol.java#L116
This is the place we get the exception originated https://github.com/ballerina-platform/ballerina-lang/blob/254d5cd94649e179fabf0d8d254192785d7b17ce/compiler/ballerina-lang/src/main/java/io/ballerina/compiler/api/impl/SymbolFactory.java#L151
Things to check first.
- Debug the SQL tool against the given Ballerina source code and check whether we are getting the correct semantic model.
- If it is correct, we need verify that we are creating the correct symbol in
SymbolFactory.getBCompiledSymbolfunction. - Check whether that why we are not getting the
symbolin the scope.
The issue originated from version 2201.8.0 onwards, as it builds for version 2201.7.5. The primary reason for this issue is that the owner of the tSymbol produced by the getDeterminedType API is invalid. The owner of the tSymbol produced for decodedJwt in https://github.com/avishka95/digiops-finance/blob/d0ba0d88fe5bb20c9c54786db756b62b76326685/apps/expense-claims/backend/service.bal#L254 is the same as the owner of the tSymbol referred via jwt in https://github.com/avishka95/digiops-finance/blob/d0ba0d88fe5bb20c9c54786db756b62b76326685/apps/expense-claims/backend/request_interceptor.bal#L29.
Moreover, making the following changes to the code temporarily resolves the problem:
- If we remove the type narrowing here and have a
checkexpression here https://github.com/avishka95/digiops-finance/blob/d0ba0d88fe5bb20c9c54786db756b62b76326685/apps/expense-claims/backend/service.bal#L242-L249. - Remove the
cloneReadonlyand have the variable as it is. Apparently, the issue is only visible if we use the lang lib methods associated with it.
The problem can be narrowed down to the following source code.
import ballerina/sql;
sql:ConnectionPool connPool = {};
public type Rec record {
int id;
string name;
};
function fn() {
readonly & Rec|int rec = 1;
if rec is int {
return;
}
_ = rec.entries();
}
The following observations can be recorded for the above code:
- The
sqlmodule should be imported to run the syntax analysis task in the compiler plugin. - A record should be defined, and an immutable record with a union type should be created as a local variable.
- After a type narrowing, access the respective variable using a library method.
Consider the following cases and the determined type for each variable reference (rec1, rec2, and rec3). Ideally, all these types should be consistent. However, as we've seen in the commit, the type narrower sets the effective type as the narrowed type for the case 1 (it sets the RecordType).
public type Rec record {
int id;
string name;
};
function fn() returns error? {
// Case 1: with type narrowing
readonly & Rec|int rec1 = 1;
if rec1 is int {
return;
}
_ = rec1.entries(); // RecordType
// Case 2: with check expression
readonly & Rec rec2 = check returnRecOrError();
_ = rec2.entries(); // IntersectionType
// Case 3: with type cast
readonly & Rec|int rec3 = 1;
_ = (<readonly & Rec>rec3).entries(); // IntersectionType
}
function returnRecOrError() returns readonly & Rec|error => error("error");
Added to the 2201.8.7 milestone: https://github.com/ballerina-platform/ballerina-release/issues/2631
This issue is NOT closed with a proper Reason/ label. Make sure to add proper reason label before closing. Please add or leave a comment with the proper reason label now.
- Reason/EngineeringMistake - The issue occurred due to a mistake made in the past.
- Reason/Regression - The issue has introduced a regression.
- Reason/MultipleComponentInteraction - Issue occured due to interactions in multiple components.
- Reason/Complex - Issue occurred due to complex scenario.
- Reason/Invalid - Issue is invalid.
- Reason/Other - None of the above cases.