Skip to content

CFA Assertions Not Active on Implicitly-Typed Function Calls #33580

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

Closed
molisani opened this issue Sep 24, 2019 · 10 comments · Fixed by #33622
Closed

CFA Assertions Not Active on Implicitly-Typed Function Calls #33580

molisani opened this issue Sep 24, 2019 · 10 comments · Fixed by #33622
Assignees
Labels
Breaking Change Would introduce errors in existing code Bug A bug in TypeScript

Comments

@molisani
Copy link
Contributor

TypeScript Version: 3.7.0-insiders.20190923 (this tgz from this comment)

Search Terms: asserts cfa control flow analysis

Code

class Foo {
}

interface BarChild {
    parent: Bar;
}

class Bar {
    static staticAdd(f: Foo): asserts f is Foo & BarChild {}
    add(f: Foo): asserts f is Foo & BarChild {}
    innerTest() {
        const innerFoo = new Foo();
        this.add(innerFoo);
        innerFoo.parent;  // this compiles successfully
    }
}

function main() {
    const foo1 = new Foo();
    const bar1 = new Bar();
    bar1.add(foo1);
    foo1.parent;  // this is an ERROR - Property 'parent' does not exist on type 'Foo'. ts(2339)

    const foo2 = new Foo();
    Bar.staticAdd(foo2);
    foo2.parent;  // this compiles successfully
}

The Bar.add assertion works when called inside another method of Bar but fails when called externally from main. I added a static function assertion to show that assertion still works otherwise in main.

Expected behavior: In main after bar1.add(foo1), foo1 should be of type Foo & BarChild.

Actual behavior: In main after bar1.add(foo1), foo1 is still type Foo.

Playground Link: I've duplicated the sample code above in this playground link, but at the time of posting the nightly version does not have these changes.

Related Issues: #32695 This feature was merged to master yesterday, so instead of commenting on a closed PR I opened a new issue.

@sandersn sandersn added the Bug A bug in TypeScript label Sep 24, 2019
@sandersn sandersn added this to the TypeScript 3.7.0 milestone Sep 24, 2019
@jack-williams
Copy link
Collaborator

I think this is working as intended, and the issue is that you are missing explicit type annotations.

A function call is analyzed as an assertion call or never-returning call when ….
each identifier in the function name references an entity with an explicit type, and

This makes the error go away:

const bar1: Bar = new Bar();

I will just put this here to annoy people.

@molisani
Copy link
Contributor Author

Ah, thanks for the link to the comment. That explains what is going on.

Was it a specific decision to require explicit type annotations to "activate" assertions, or is it a technical restriction? Regardless, it would be nice to not have to add otherwise-unnecessary type annotations to get this to work.

@RyanCavanaugh
Copy link
Member

It's a technical restriction, otherwise control flow would have to do an unbounded number of passes to determine if a given function ever returned

@molisani
Copy link
Contributor Author

Alright, thanks for the quick and informative response @jack-williams and @RyanCavanaugh. While I do agree with Jack's comment on the PR that this will catch a lot of people, feel free to handle this issue however you see fit.

@molisani molisani changed the title CFA Assertions Fail on Externally-Invoked Class Methods CFA Assertions Not Active on Implicitly-Typed Function Calls Sep 24, 2019
@ahejlsberg
Copy link
Member

I'm going to mark this working as intended, although we should probably discuss whether to issue errors when assertion functions and non-returning functions are used in a manner that doesn't get picked up by control flow analysis. See #32695 (comment).

@ahejlsberg ahejlsberg added Working as Intended The behavior described is the intended behavior; this is not a bug and removed Bug A bug in TypeScript labels Sep 25, 2019
@ahejlsberg ahejlsberg removed this from the TypeScript 3.7.0 milestone Sep 25, 2019
@jcalz
Copy link
Contributor

jcalz commented Sep 26, 2019

Yeah, an error with a corresponding annotation quick-fix would hopefully mitigate this? Or something to stem the expected tide of duplicates of this issue being filed and the analogous SO questions.

@jack-williams
Copy link
Collaborator

My concern with an error would be libraries upgrading to use assertions and clients breaking because they didn't use a type annotation on previously OK code.

@ahejlsberg
Copy link
Member

Ok, with two issues reported in short order I'm convinced this merits an error as suggested by @jack-williams. I'm changing this back to a bug.

@ahejlsberg ahejlsberg added Bug A bug in TypeScript and removed Working as Intended The behavior described is the intended behavior; this is not a bug labels Sep 26, 2019
@ahejlsberg ahejlsberg added this to the TypeScript 3.7.0 milestone Sep 26, 2019
@ahejlsberg
Copy link
Member

ahejlsberg commented Sep 26, 2019

My concern with an error would be libraries upgrading to use assertions and clients breaking because they didn't use a type annotation on previously OK code.

I'm not concerned with issuing errors on non-CFA-recognized assertion function calls since assertions are new feature and no existing code uses them.

The fact that we now report reachability errors following calls to never-returning functions is already a breaking change, so also issuing errors when such functions are called in a manner that CFA doesn't recognized doesn't materially change the situation.

@jack-williams
Copy link
Collaborator

Makes sense - I overlooked the general changes you made to reachability analysis beyond assert.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Breaking Change Would introduce errors in existing code Bug A bug in TypeScript
Projects
None yet
Development

Successfully merging a pull request may close this issue.

7 participants