Skip to content

Commit

Permalink
Merge pull request #41843 from LakshanWeerasinghe/fix-#41834
Browse files Browse the repository at this point in the history
Make RegExp type inherently immutable
  • Loading branch information
KavinduZoysa authored Feb 2, 2024
2 parents e55604f + 1e296dc commit 7585955
Show file tree
Hide file tree
Showing 8 changed files with 46 additions and 1 deletion.
Original file line number Diff line number Diff line change
Expand Up @@ -1953,6 +1953,7 @@ public static boolean isInherentlyImmutableType(Type sourceType) {
case TypeTags.TYPEDESC_TAG:
case TypeTags.FUNCTION_POINTER_TAG:
case TypeTags.HANDLE_TAG:
case TypeTags.REG_EXP_TYPE_TAG:
return true;
case TypeTags.XML_TAG:
return ((BXmlType) sourceType).constraint.getTag() == TypeTags.NEVER_TAG;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1498,6 +1498,7 @@ public boolean isInherentlyImmutableType(BType type) {
case TypeTags.INVOKABLE:
case TypeTags.TYPEDESC:
case TypeTags.HANDLE:
case TypeTags.REGEXP:
return true;
case TypeTags.XML:
return getImpliedType(((BXMLType) type).constraint).tag == TypeTags.NEVER;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -193,6 +193,8 @@ public void testImmutableTypesNegative() {
"'(json & readonly)[]'", 407, 28);
validateError(result, index++, "incompatible types: expected '(json & readonly)[]', found " +
"'(xml & readonly)[]'", 408, 29);
validateError(result, index++, "incompatible types: expected " +
"'((stream<int>|ballerina/lang.string:0.0.0:RegExp) & readonly)', found 'stream<int>'", 412, 48);

assertEquals(result.getErrorCount(), index);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,8 @@ public Object[] dataToTestRegExp() {
"testAssignabilityWithRegExp",
"testSubtypingWithRegExp",
"testRegExpWithVar",
"testRegExpWithUserDefinedType"
"testRegExpWithUserDefinedType",
"testRegExpReadonlyLocalVars"
};
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@

import ballerina/jballerina.java;
import ballerina/lang.'xml;
import ballerina/lang.regexp;

// readonly-type-descriptor := readonly
// A shape belongs to the type readonly if its read-only bit is on.
Expand Down Expand Up @@ -163,6 +164,14 @@ function testRuntimeIsTypeForInherentlyImmutableBasicTypes() {
'xml:Text xmlText = xml `xml text`;
any n = xmlText;
assertTrue(n is readonly);

any reg1 = re `pattern`;
assertTrue(reg1 is readonly);

readonly reg2 = re `pattern`;
assertTrue(reg2 is readonly);

assertTrue(regexp:fromString("pattern") is readonly);
}

function testRuntimeIsTypeForNeverImmutableBasicTypes() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1197,6 +1197,11 @@ function testReadOnlyIntersectionWithJsonAndAnydata() {
assertFalse(l is (string|error)[]);
}

function testSelectivelyImmutabilityWithRegexp() {
(stream<int>|string:RegExp) & readonly x = re `pattern`;
assertTrue(x is (string:RegExp & readonly));
}

const ASSERTION_ERROR_REASON = "AssertionError";

function assertTrue(any|error actual) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -407,3 +407,7 @@ function testReadOnlyIntersectionWithJsonAndAnydataNegative() {
(xml & readonly)[] n = k; // error
(json & readonly)[] _ = n; // error
}

function testUnsupportedIntersectionWithReadonly(stream<int> strm) {
(stream<int>|string:RegExp) & readonly _ = strm;
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
import ballerina/lang.regexp;

function testBasicRegExp() {
string:RegExp _ = re `AB*|[^c-d]{1,5}`;
Expand Down Expand Up @@ -105,6 +106,27 @@ function testRegExpWithUserDefinedType() {
assertEquality(re `AB*|[^c-d]{1,5}`, x7);
}

type T1 string:RegExp & readonly;
type T2 regexp:RegExp & readonly;

type Foo record {|
int e;
readonly regexp:RegExp f;
|};

Foo & readonly rf = {e: 1, f: re `test`};

function testRegExpReadonlyLocalVars() {
string:RegExp & readonly r1 = re `test`;
assertEquality(true, r1 is readonly);

T1 & readonly r2 = re `test`;
assertEquality(true, r2 is readonly);

(T2 & readonly) & string:RegExp r3 = re `test`;
assertEquality(true, r3 is readonly);
}

const ASSERTION_ERROR_REASON = "AssertionError";

function assertEquality(any|error expected, any|error actual) {
Expand Down

0 comments on commit 7585955

Please sign in to comment.