Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Spec Deviation] Freezing a container should narrow its inherent type to a type that consists of just its current shape #13189

Closed
MaryamZi opened this issue Jan 16, 2019 · 4 comments
Assignees
Labels
Area/Compiler Area/JVMCodeGen JVM code generation module Points/5 Equivalent to five day effort Team/jBallerina All the issues related to BIR, JVM backend code generation and runtime Type/SpecDeviation

Comments

@MaryamZi
Copy link
Member

Description:
According to the spec (v0.990:2019-01-16 - page 17), "A frozen container value belongs to a type if and only if the type contains the shape of the value. Thus after a container value is frozen, its inherent type does not provide additional information that cannot be derived from the value. In other words, freezing a container narrows its inherent type to a type that consists of just its current shape"

The is check works as expected after freezing a value:

import ballerina/io;

public function main(string... args) {
    map<string|int> m1 = { str: "string only" };
    anydata a = m1;  
    io:println(a is map<string>); // false

    _ = a.freeze();
    io:println(a is map<string>); // true
}

But when trying to use such a value in the context of the narrowed type, the original type is still considered.

import ballerina/io;

public function main(string... args) {
    map<string|int> m1 = { str: "string only" };
    anydata a = m1;

    _ = a.freeze();
    io:println(a is map<string>); // true

    map<map<string>> m2 = {};
    insertMemberToMap(m2, "strMap", a); // panics with {ballerina}InherentTypeViolation {"message":"invalid map insertion: expected value of type 'map<string>', found 'map<string|int>'"}
}

public function insertMemberToMap(map<any> mapVal, string index, any member) {
    mapVal[index] = member;
}

Casting/assertion also fails similarly.

Affected Versions:
0.990.2

@anupama-pathirage anupama-pathirage added the Team/CompilerFE All issues related to Language implementation and Compiler, this exclude run times. label Apr 30, 2019
@hasithaa
Copy link
Contributor

hasithaa commented Aug 2, 2019

@MaryamZi Please verify this w.r.t 2019R3

@MaryamZi
Copy link
Member Author

MaryamZi commented Aug 4, 2019

IMO, this is still valid.

The 2019R3 spec says

  • "For an immutable value, looking like a type and belonging to a type are the same thing." (5. Values, types and variables)

  • "The inherent type of an immutable container is a singleton type with the container's shape as its single member. Thus, an immutable container value belongs to a type if and only if the type contains the shape of the value." (Structured values)

@anupama-pathirage anupama-pathirage added Team/jBallerina All the issues related to BIR, JVM backend code generation and runtime and removed Team/CompilerFE All issues related to Language implementation and Compiler, this exclude run times. labels Aug 5, 2019
@Kishanthan Kishanthan added this to the Ballerina 1.0.0-beta milestone Aug 6, 2019
@Kishanthan Kishanthan removed this from the Ballerina 1.0.0-beta milestone Aug 27, 2019
@vinok88
Copy link
Contributor

vinok88 commented Aug 27, 2019

Following code runs fine now with v1-0-0-alpha3 pack. Do we need any fixes here?

import ballerina/io;

public function main(string... args) {
    map<string|int> m1 = { str: "string only" };
    anydata a = m1.cloneReadOnly();

    // _ = a.freeze();
    io:println(a is map<string>); // true

    map<map<string>> m2 = {};
    insertMemberToMap(m2, "strMap", a); // panics with {ballerina}InherentTypeViolation {"message":"invalid map insertion: expected value of type 'map<string>', found 'map<string|int>'"}
}

public function insertMemberToMap(map<any> mapVal, string index, any member) {
    mapVal[index] = member;
}

@MaryamZi
Copy link
Member Author

Yeah, this scenario seems to work fine.

Even though we don't change the inherent type, since most updates are done by first checking checkIsType() we should be able to achieve the expected behaviour in general. May have to validate if there are any related paths that do not go through checkIsType() though.

However as mentioned in #15278 (comment), typeof should return a singleton type representing the shape of the value if it is immutable. This is not implemented yet, and we have to do one of the following

  • change the inherent type itself as mentioned in this issue
  • check if the value is immutable when evaluating typeof and return a new typedesc there (but this could cause issues since we expect a single typedesc - reference equality will fail)

@gimantha gimantha added this to the Ballerina 1.0.x milestone Oct 17, 2019
@Kishanthan Kishanthan removed this from the Ballerina 1.0.x milestone Aug 25, 2020
@warunalakshitha warunalakshitha added the Points/3 Equivalent to three days effort label Jul 16, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Area/Compiler Area/JVMCodeGen JVM code generation module Points/5 Equivalent to five day effort Team/jBallerina All the issues related to BIR, JVM backend code generation and runtime Type/SpecDeviation
Projects
None yet
Development

Successfully merging a pull request may close this issue.

9 participants