Skip to content

Commit

Permalink
Merge pull request #40336 from MaryamZi/make-self-final
Browse files Browse the repository at this point in the history
Make `self` final
  • Loading branch information
MaryamZi authored May 18, 2023
2 parents 2b56307 + 10a7e9e commit 427f58d
Show file tree
Hide file tree
Showing 6 changed files with 123 additions and 1 deletion.
Original file line number Diff line number Diff line change
Expand Up @@ -797,6 +797,7 @@ public static BLangSimpleVariable createReceiver(Location pos, BType type) {
IdentifierNode identifier = createIdentifier(pos, Names.SELF.getValue());
receiver.setName(identifier);
receiver.setBType(type);
receiver.flagSet.add(Flag.FINAL);
return receiver;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,8 @@ public Object[] isolatedFunctionTests() {
"testAccessingFinalIsolatedObjectInIsolatedFunction",
"testIsolationOfBoundMethods",
"testFinalReadOnlyServiceAccessInIsolatedFunction",
"testFinalReadOnlyRawTemplateAccessInIsolatedFunction"
"testFinalReadOnlyRawTemplateAccessInIsolatedFunction",
"testIsolatedFunctionWithSelfAsCapturedVariable"
};
}

Expand Down Expand Up @@ -243,6 +244,8 @@ public void testIsolatedFunctionsNegative() {
validateError(result, i++, INVALID_MUTABLE_STORAGE_ACCESS_ERROR, 311, 70);
validateWarning(result, i++, "unused variable 'fn9'", 313, 4);
validateError(result, i++, INVALID_MUTABLE_STORAGE_ACCESS_ERROR, 313, 76);
validateError(result, i++, "invalid access of mutable storage in an 'isolated' function", 322, 81);
validateError(result, i++, "invalid access of mutable storage in an 'isolated' function", 331, 64);
Assert.assertEquals(result.getErrorCount(), i - 23);
Assert.assertEquals(result.getWarnCount(), 23);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ public class ObjectTest {
"cannot use 'check' in the default expression of a record field";
private static final String INVALID_USAGE_OF_CHECK_IN_INITIALIZER_IN_OBJECT_WITH_NO_INIT =
"cannot use 'check' in an object field initializer of an object with no 'init' method";
private static final String CANNOT_ASSIGN_TO_FINAL_SELF = "cannot assign a value to final 'self'";

private CompileResult checkInInitializerResult;
private CompileResult checkFunctionReferencesResult;
Expand Down Expand Up @@ -513,6 +514,16 @@ public void testObjectInitFunctionNegative() {
23, 5);
}

@Test
public void testObjectSelfBeingImplicitlyFinal() {
CompileResult result = BCompileUtil.compile("test-src/object/object_self_final_negative.bal");
int index = 0;
BAssertUtil.validateError(result, index++, CANNOT_ASSIGN_TO_FINAL_SELF, 25, 9);
BAssertUtil.validateError(result, index++, CANNOT_ASSIGN_TO_FINAL_SELF, 40, 9);
BAssertUtil.validateError(result, index++, CANNOT_ASSIGN_TO_FINAL_SELF, 47, 13);
Assert.assertEquals(result.getErrorCount(), index);
}

@Test(description = "Test nillable initialization")
@SuppressWarnings("unchecked")
public void testNillableInitialization() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -504,6 +504,45 @@ isolated function testFinalReadOnlyRawTemplateAccessInIsolatedFunction() {
assertEquality(<int[]>[10, 20], tmp3.insertions);
}

readonly class IsolatedFunctionWithReadOnlySelfAsCapturedVariable {
string[] words;
int length;

isolated function init(string[] & readonly words, int length) {
self.words = words;
self.length = length;
}

isolated function getCount() returns int =>
self.words.filter(
isolated function (string word) returns boolean => word.length() == self.length).length();
}

isolated class IsolatedFunctionWithIsolatedSelfAsCapturedVariable {
private string[] words;
private int min = 10;

isolated function init(string[] words) {
self.words = words.clone();
}

isolated function compare() returns boolean {
lock {
return self.words.some(isolated function (string s) returns boolean => s.length() > self.min);
}
}
}

function testIsolatedFunctionWithSelfAsCapturedVariable() {
string[] words = ["hello", "world", "this", "is", "a", "test"];

IsolatedFunctionWithReadOnlySelfAsCapturedVariable a = new (words.cloneReadOnly(), 4);
assertEquality(2, a.getCount());

IsolatedFunctionWithIsolatedSelfAsCapturedVariable b = new (words);
assertEquality(false, b.compare());
}

isolated function assertEquality(any|error expected, any|error actual) {
if expected is anydata && actual is anydata && expected == actual {
return;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -312,3 +312,21 @@ function testAnonIsolatedFuncAccessingImplicitlyFinalVarsNegative(int[] i) {

isolated function (int[]) returns int[] fn9 = let int[] k = i in (l) => k;
}

class TestInvalidAccessOfSelfAsCapturedVariableInIsolatedFunction {
string[] words = [];
int length = 3;

isolated function getCount() returns int =>
self.words.filter(
isolated function (string word) returns boolean => word.length() == self.length).length();
}

object {} testInvalidAccessOfSelfAsCapturedVariableInIsolatedFunction = object {
string[] words = [];
int length = 3;

isolated function getCount() returns int =>
self.words.filter(
isolated function (string word) returns boolean => self.length == word.length()).length();
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
// Copyright (c) 2023 WSO2 LLC. (http://www.wso2.org) All Rights Reserved.
//
// WSO2 LLC. licenses this file to you under the Apache License,
// Version 2.0 (the "License"); you may not use this file except
// in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.

class Class {
int i;

function init(int i) {
self.i = i;
}

function fn() {
self = new (3);
}
}

string modStr = "original";

object {} modOb = object {
string s;

function init() {
self.s = modStr;
}

function fn() {
modStr = "updated";
self = new;
}
};

function testInvalidAssignmentToSelf() {
var _ = object {
function fn() {
self = new;
}
};
}

0 comments on commit 427f58d

Please sign in to comment.