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

[Bug]: Type narrowing problem (Redeclared symbol error when same symbol is used in two blocks) #39065

Closed
uthaiyashankar opened this issue Dec 15, 2022 · 3 comments · Fixed by #40679
Assignees
Labels
Priority/Blocker Team/CompilerFE All issues related to Language implementation and Compiler, this exclude run times. Type/Bug userCategory/Compilation

Comments

@uthaiyashankar
Copy link
Contributor

Description

See the following program. Getting a redeclared symbol error at line 21. If I comment line 16, this problem will go away (This is a simplified code to recreate problem, so don't look at the logic 🙂 ) Sounds like a bug to me?

import ballerina/test;

@test:Config
public function runFromLastUpdatedDate() {

    // Get last results updated date from the database
    int? lastUpdatedDate = ();
    if lastUpdatedDate is () {
            int year = 2022;
            int month = 12;

            month += 1;
            if month == 13 {
                year += 1;
                month = 1;
            }
    } else {

        int year = 2022;
        int month = 12;
    }
}

Screenshot 2022-12-15 at 12 44 32

Steps to Reproduce

No response

Affected Version(s)

Ballerina 2201.3.0 (Swan Lake Update 3)
Language specification 2022R4
Update Tool 1.3.12

OS, DB, other environment details and versions

No response

Related area

-> Compilation

Related issue(s) (optional)

No response

Suggested label(s) (optional)

No response

Suggested assignee(s) (optional)

No response

@ballerina-bot ballerina-bot added needTriage The issue has to be inspected and labeled manually userCategory/Compilation labels Dec 15, 2022
@uthaiyashankar
Copy link
Contributor Author

This is another example of type narrowing problem :

type DataChange record {
    int id;
    int org_id;
    string column_name;
    string updated_date;
};

type Data record {
    int id;
    int org_id;
    string author;
    string created_date;
}; 

function processData((DataChange|Data)[] dataModification) returns error? {
    foreach (DataChange|Data) event in dataModification {
        if (event is DataChange) {
            string updatedTime = event.updated_date;
        } else {
            string updatedTime = event.created_date;
        }
    }
}

Screenshot 2022-12-15 at 13 19 11

@MaryamZi MaryamZi added the Team/CompilerFE All issues related to Language implementation and Compiler, this exclude run times. label Dec 15, 2022
@MaryamZi
Copy link
Member

This is another example of type narrowing problem :

type DataChange record {
    int id;
    int org_id;
    string column_name;
    string updated_date;
};

type Data record {
    int id;
    int org_id;
    string author;
    string created_date;
}; 

function processData((DataChange|Data)[] dataModification) returns error? {
    foreach (DataChange|Data) event in dataModification {
        if (event is DataChange) {
            string updatedTime = event.updated_date;
        } else {
            string updatedTime = event.created_date;
        }
    }
}

Screenshot 2022-12-15 at 13 19 11

This (the type not being narrowed in the else block) is the expected behaviour according to the current spec.

Since the records are open and mutable and given that the current specification defines the value space of the union to contain a value (v)

  • that belongs to DataChange|Data
  • but v is DataChange and v is Data may evaluate to false individually

we don't narrow in the else block.

record {
    int id;
    int org_id;
    anydata column_name?;
    anydata updated_date?;
    anydata author?;
    anydata created_date?;
} rec = {id: 1024, org_id: 100045, author: "me", created_date: "01-12-2022"};
processData([rec]); // jBallerina doesn't allow it, but valid according to the spec

This will change with proposed changes to narrowing/typing though. But the current behaviour is correct according to the current spec.

You would have to explicitly check for Data in order for the type to be narrowed.

function processData((DataChange|Data)[] dataModification) returns error? {
    foreach DataChange|Data event in dataModification {
        if event is DataChange {
            string updatedTime = event.updated_date;
        } else if event is Data {
            string updatedTime = event.created_date;
        } else {
            panic error("unexpected value");
        }
    }
}

Or, narrowing will work as expected if the records were immutable (or closed).

function processData(readonly & (DataChange|Data)[] dataModification) returns error? {
    foreach DataChange|Data event in dataModification {
        if event is DataChange {
            string updatedTime = event.updated_date;
        } else {
            string updatedTime = event.created_date;
        }
    }
}

@github-actions
Copy link

This issue is NOT closed with a proper Reason/ label. Make sure to add proper reason label before closing. Please add or leave a comment with the proper reason label now.

      - Reason/EngineeringMistake - The issue occurred due to a mistake made in the past.
      - Reason/Regression - The issue has introduced a regression.
      - Reason/MultipleComponentInteraction - Issue occured due to interactions in multiple components.
      - Reason/Complex - Issue occurred due to complex scenario.
      - Reason/Invalid - Issue is invalid.
      - Reason/Other - None of the above cases.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment