Skip to content

Commit

Permalink
Merge pull request #42521 from Thushara-Piyasekara/fix-error-code-inc…
Browse files Browse the repository at this point in the history
…onsistency

Fix `BFields` of generated immutable `BRecords` not being marked as `SymbolFlags.READONLY`
  • Loading branch information
gimantha authored Oct 4, 2024
2 parents e3c0757 + f4b21aa commit afc5db7
Show file tree
Hide file tree
Showing 6 changed files with 114 additions and 10 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -224,8 +224,8 @@ private static BIntersectionType setImmutableIntersectionType(Type type, Set<Typ
for (Map.Entry<String, Field> entry : originalFields.entrySet()) {
Field originalField = entry.getValue();
fields.put(entry.getKey(),
new BField(getImmutableType(originalField.getFieldType(), unresolvedTypes),
originalField.getFieldName(), originalField.getFlags()));
new BField(getImmutableType(originalField.getFieldType(), unresolvedTypes),
originalField.getFieldName(), originalField.getFlags() | SymbolFlags.READONLY));
}

BRecordType immutableRecordType = new BRecordType(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,8 @@ public class MappingConstructorExprTest {
private CompileResult inferRecordResult;
private CompileResult spreadOpFieldResult;
private CompileResult readOnlyFieldResult;
private CompileResult resultWithTupleUpdateMethod;
private CompileResult resultWithoutTupleUpdateMethod;

@BeforeClass
public void setup() {
Expand All @@ -47,6 +49,10 @@ public void setup() {
varNameFieldResult = BCompileUtil.compile("test-src/expressions/mappingconstructor/var_name_field.bal");
spreadOpFieldResult = BCompileUtil.compile("test-src/expressions/mappingconstructor/spread_op_field.bal");
readOnlyFieldResult = BCompileUtil.compile("test-src/expressions/mappingconstructor/readonly_field.bal");
resultWithTupleUpdateMethod =
BCompileUtil.compile("test-src/types/readonly/test_tuple_vs_array_readonly_violation_consistency.bal");
resultWithoutTupleUpdateMethod = BCompileUtil.compile("test-src/types/readonly/" +
"test_tuple_vs_array_readonly_violation_without_tuple_update_method.bal");
}

@Test(dataProvider = "mappingConstructorTests")
Expand Down Expand Up @@ -379,6 +385,16 @@ public void testReadOnlyFields(String test) {
BRunUtil.invoke(readOnlyFieldResult, test);
}

@Test
public void testReadOnlyFields2() {
BRunUtil.invoke(resultWithTupleUpdateMethod, "testFrozenAnyArrayElementUpdate");
}

@Test
public void testReadOnlyFields3() {
BRunUtil.invoke(resultWithoutTupleUpdateMethod, "testFrozenAnyArrayElementUpdate");
}

@DataProvider(name = "readOnlyFieldTests")
public Object[][] readOnlyFieldTests() {
return new Object[][] {
Expand Down Expand Up @@ -502,5 +518,7 @@ public void tearDown() {
inferRecordResult = null;
spreadOpFieldResult = null;
readOnlyFieldResult = null;
resultWithTupleUpdateMethod = null;
resultWithoutTupleUpdateMethod = null;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -169,8 +169,8 @@ public void testCreateRawDetails() {
}

@Test(expectedExceptions = BLangTestException.class,
expectedExceptionsMessageRegExp = ".*Invalid update of record field: modification not allowed on readonly " +
"value.*")
expectedExceptionsMessageRegExp = "error: \\{ballerina/lang.map}InherentTypeViolation \\{\"message\":" +
"\"cannot update 'readonly' field 'name' in record of type 'Details & readonly'\".*")
public void testCreateDetails() {
BRunUtil.invoke(result, "testCreateDetails");
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,8 +47,8 @@ function testRecordTypeAnnotationReadonlyValueEdit() {
assertEquality(true, res is error);

error resError = <error> res;
assertEquality("{ballerina/lang.map}InvalidUpdate", resError.message());
assertEquality("Invalid update of record field: modification not allowed on readonly value",
assertEquality("{ballerina/lang.map}InherentTypeViolation", resError.message());
assertEquality("cannot update 'readonly' field 'foo' in record of type 'Annot & readonly'",
resError.detail()["message"]);
}

Expand All @@ -73,8 +73,8 @@ function testAnnotationOnObjectTypeReadonlyValueEdit() {
assertEquality(true, res is error);

error resError = <error> res;
assertEquality("{ballerina/lang.map}InvalidUpdate", resError.message());
assertEquality("Invalid update of record field: modification not allowed on readonly value",
assertEquality("{ballerina/lang.map}InherentTypeViolation", resError.message());
assertEquality("cannot update 'readonly' field 'foo' in record of type 'Annot & readonly'",
resError.detail()["message"]);
}

Expand All @@ -97,8 +97,8 @@ function testAnnotationOnFunctionTypeReadonlyValueEdit() {
assertTrue(res is error);

error resError = <error> res;
assertEquality("{ballerina/lang.map}InvalidUpdate", resError.message());
assertEquality("Invalid update of record field: modification not allowed on readonly value",
assertEquality("{ballerina/lang.map}InherentTypeViolation", resError.message());
assertEquality("cannot update 'readonly' field 'foo' in record of type 'Annot & readonly'",
resError.detail()["message"]);
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
// Copyright (c) 2024, WSO2 LLC. (http://www.wso2.com).
//
// 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.

import ballerina/test;

type Employee record {|
int id;
string name;
|};

function testFrozenAnyArrayElementUpdate() returns error? {
error? actualError = trap frozenAnyArrayElementUpdate();
test:assertTrue(actualError is error);
error e = <error>actualError;
test:assertEquals(e.message(), "{ballerina/lang.map}InherentTypeViolation");
test:assertEquals(e.detail()["message"],
"cannot update 'readonly' field 'name' in record of type '(Employee & readonly)'");
}

function frozenAnyArrayElementUpdate() returns error? {
Employee e1 = {name: "Em", id: 1000};
anydata[] i1 = [e1];
anydata[] i2 = i1.cloneReadOnly();
Employee e2 = check trap <Employee>i2[0];
e2["name"] = "Zee";
return ();
}

function frozenTupleUpdate() {
Employee e1 = {name: "Em", id: 1000};
[int, Employee] t1 = [1, e1];
[int, Employee] t2 = t1.cloneReadOnly();
Employee e2 = {name: "Zee", id: 1200};
t2[1] = e2;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
// Copyright (c) 2024, WSO2 LLC. (http://www.wso2.com).
//
// 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.
import ballerina/test;

type Employee record {|
int id;
string name;
|};

function frozenAnyArrayElementUpdate() returns error? {
Employee e1 = {name: "Em", id: 1000};
anydata[] i1 = [e1];
anydata[] i2 = i1.cloneReadOnly();
Employee e2 = check trap <Employee>i2[0];
e2["name"] = "Zee";
return ();
}

function testFrozenAnyArrayElementUpdate() returns error? {
error? actualError = trap frozenAnyArrayElementUpdate();
test:assertTrue(actualError is error);
test:assertEquals((<error>actualError).message(), "{ballerina/lang.map}InherentTypeViolation");
test:assertEquals((<error>actualError).detail()["message"],
"cannot update 'readonly' field 'name' in record of type 'Employee & readonly'");
}

0 comments on commit afc5db7

Please sign in to comment.