Skip to content

Comments

Fix configurable default field errors for configurable variables#44403

Open
iamvirul wants to merge 3 commits intoballerina-platform:masterfrom
iamvirul:bugfix/union-type-config-vars-mutable
Open

Fix configurable default field errors for configurable variables#44403
iamvirul wants to merge 3 commits intoballerina-platform:masterfrom
iamvirul:bugfix/union-type-config-vars-mutable

Conversation

@iamvirul
Copy link
Member

@iamvirul iamvirul commented Nov 14, 2025

Purpose

Approach

  • Updated IsolationAnalyzer to skip mutable-storage diagnostics when a record/object field default references a symbol flagged with Flags.CONFIGURABLE.
  • Added regression coverage via test-src/statements/variabledef/configurable_record_field_default.bal and a new GlobalVarTest.testConfigurableVarInRecordFieldDefaultValue, guarding the reported scenario.

Samples

  • tests/jballerina-unit-test/src/test/resources/test-src/statements/variabledef/configurable_record_field_default.bal demonstrates assigning a configurable string|string[]? to a record field default.

Remarks

  • Verified with ./gradlew :jballerina-unit-test:test --tests org.ballerinalang.test.types.globalvar.GlobalVarTest on JDK 21.

Check List

Summary

This pull request fixes a compiler validation issue where configurable module variables were incorrectly treated as mutable storage when used as default values for record or object fields, causing an erroneous diagnostic.

Changes

  • Compiler: Updated IsolationAnalyzer to skip the mutable-storage diagnostic when a field default expression references a symbol flagged with Flags.CONFIGURABLE. This allows configurable globals (including union-typed configurable variables) to serve as default initializers without requiring them to be readonly.
  • Tests: Added a unit test (GlobalVarTest.testConfigurableVarInRecordFieldDefaultValue) and a Ballerina test resource (tests/.../configurable_record_field_default.bal) that verify a configurable string|string[]? variable can be used as a record field default without compiler errors.

Outcome

Configurable global variables can now be referenced by record/object field defaults without triggering an incorrect mutable-storage error, removing the need for workarounds like marking such globals readonly.

…n record and object field default values. Add unit test for configurable variable usage in record field default values.
@codecov
Copy link

codecov bot commented Nov 14, 2025

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 75.03%. Comparing base (840270a) to head (feb8bf5).
⚠️ Report is 10 commits behind head on master.

Additional details and impacted files
@@             Coverage Diff              @@
##             master   #44403      +/-   ##
============================================
- Coverage     75.03%   75.03%   -0.01%     
  Complexity    58700    58700              
============================================
  Files          3601     3601              
  Lines        227095   227098       +3     
  Branches      29572    29574       +2     
============================================
+ Hits         170392   170393       +1     
- Misses        47203    47204       +1     
- Partials       9500     9501       +1     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

Comment on lines 1307 to 1310
if ((recordFieldDefaultValue || objectFieldDefaultValueRequiringIsolation) &&
Symbols.isFlagOn(flags, Flags.CONFIGURABLE)) {
return;
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure if this is the correct fix.

A configurable variable is implicitly final and immutable, so the check at L1315 should be sufficient. The issue here seems to be that the relevant flags aren't set when this check happens.

For example, the following works

configurable string|string[]? fooConfig = ();

isolated int[] x = [1, 2, 3];

function fn() returns string|string[]?  {
    lock {
        foreach var i in x {

        }
        
        // This is allowed because the flags are set by the time this check happens
        return fooConfig; 
    }
}

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi @MaryamZi,

You're completely right - configurable variables are implicitly readonly, so the check at L1315 should naturally succeed. Because fooConfig is perfectly readonly, the issue in #44284 should have passed safely through that initial finality condition instead of failing as mutable storage.

The root cause of this failure is that SemanticAnalyzer processes type definitions (and their record field default values) before global variables. When the varRefExpr for the configurable variable is evaluated inside a record field's default value, the configurable variable's symbol type hasn't been mutated to its readonly intersection type yet.

Consequently, varRefExpr.getBType() (accessType) in IsolationAnalyzer holds onto the initial, non-readonly type (e.g., string|string[]?). While varRefExpr keeps the stale definition, the variable's underlying symbol symbol.type correctly holds the freshly updated readonly intersection type later on.

I've pushed a cleaner fix to remove the specific bypass for Flags.CONFIGURABLE. Instead, I updated the check in IsolationAnalyzer to honor symbol.type alongside accessType.

@coderabbitai
Copy link

coderabbitai bot commented Feb 20, 2026

No actionable comments were generated in the recent review. 🎉


📝 Walkthrough

Walkthrough

Refines IsolationAnalyzer early-exit in visit(BLangSimpleVarRef) to short-circuit when a final/finally symbol's access type or the symbol's own type is a subtype of the ReadOnly/Isolated object union. Adds a unit test and test resource validating configurable union variable usage as a record field default.

Changes

Cohort / File(s) Summary
Isolation Analyzer Logic
compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/analyzer/IsolationAnalyzer.java
Broadened the FINAL / FUNCTION_FINAL short-circuit condition in visit(BLangSimpleVarRef) to also return early when the symbol's declared type is a subtype of the ReadOnlyOrIsolated object union, preventing further isolation checks for such final symbols.
Test Coverage
tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/types/globalvar/GlobalVarTest.java, tests/jballerina-unit-test/src/test/resources/test-src/statements/variabledef/configurable_record_field_default.bal
Added testConfigurableVarInRecordFieldDefaultValue() and corresponding .bal test resource to verify configurable union-typed variables can be used as record field default values without causing compiler diagnostics.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Poem

🐰 I peeked at types both unioned and shy,
A final hop — the analyzer let them by.
No longer marked mutable where default fields play,
I nibble a carrot and dance on my way. 🥕

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title 'Fix configurable default field errors for configurable variables' accurately describes the main change - fixing a compiler issue where configurable variables caused errors when used in record field defaults.
Description check ✅ Passed The PR description covers Purpose, Approach, Samples, and Remarks sections with clear explanations, though the checklist shows not all optional items (changelog, documentation, other test types) were completed.
Linked Issues check ✅ Passed The code changes successfully address issue #44284 by updating IsolationAnalyzer to handle CONFIGURABLE-flagged symbols and adding comprehensive test coverage for the fix.
Out of Scope Changes check ✅ Passed All changes are directly related to fixing the configurable variable issue: IsolationAnalyzer refinement, test coverage addition, and test resource file creation - no out-of-scope modifications detected.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
  • 📝 Generate docstrings (stacked PR)
  • 📝 Generate docstrings (commit on current branch)
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

Comment @coderabbitai help to get the list of available commands and usage tips.

@iamvirul iamvirul requested a review from MaryamZi February 20, 2026 13:42
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug]: Configurable Variables with Union Type Recognized as a Mutable Storage

2 participants