IssueRaiser

Trade-offs in Control Flow Analysis

Some rough notes from a conversation @ahejlsberg and I had earlier about trade-offs in the control flow analysis work based on running the real-world code (RWC) tests. For obvious reasons I'll be comparing what Flow does with similar examples to compare and contrast possible outcomes. The primary question is: When a function is invoked, what should we assume its side effects are? One option is to be _pessimistic_ and reset all narrowings, assuming that any function might mutate any object it could possibly get its hands on. Another option is to be _optimistic_ and assume the function doesn't modify any state. Both of these seem to be bad. This problem spans both locals (which might be subject to some "closed over or not" analysis) and object fields. #### Optimistic: Bad behavior on locals The TypeScript compiler has code like this: ``` ts enum Token { Alpha, Beta, Gamma } let token = Token.Alpha; function nextToken() { token = Token.Beta; } function maybeNextToken() { if (... something ...) { nextToken(); } } function doSomething() { if (token !== Token.Alpha) { maybeNextToken(); } // is this possible? if (token === Token.Alpha) { // something happens } } ``` Optimistically assuming `token` isn't modified by `maybeNextToken` incorrectly flags `token === Token.Alpha` as an impossibility. However, in other cases, this is a _good_ check to do! See later examples. #### Optimistic: Bad behavior on fields The RWC suite

Posted by RyanCavanaugh on Jul 28, 2016, 12:03 AM

Tags

Related issues

Raise real-world problems, find people facing the same issue, and discuss solutions.5,000 issues0 comments

github (Software)

Trade-offs in Control Flow Analysis

RyanCavanaughJul 28, 2016, 12:03 AM

Some rough notes from a conversation @ahejlsberg and I had earlier about trade-offs in the control flow analysis work based on running the real-world code (RWC) tests. For obvious reasons I'll be comparing what Flow does with similar examples to compare and contrast possible outcomes. The primary question is: When a function is invoked, what should we assume its side effects are? One option is to be _pessimistic_ and reset all narrowings, assuming that any function might mutate any object it could possibly get its hands on. Another option is to be _optimistic_ and assume the function doesn't modify any state. Both of these seem to be bad. This problem spans both locals (which might be subject to some "closed over or not" analysis) and object fields. #### Optimistic: Bad behavior on locals The TypeScript compiler has code like this: ``` ts enum Token { Alpha, Beta, Gamma } let token = Token.Alpha; function nextToken() { token = Token.Beta; } function maybeNextToken() { if (... something ...) { nextToken(); } } function doSomething() { if (token !== Token.Alpha) { maybeNextToken(); } // is this possible? if (token === Token.Alpha) { // something happens } } ``` Optimistically assuming `token` isn't modified by `maybeNextToken` incorrectly flags `token === Token.Alpha` as an impossibility. However, in other cases, this is a _good_ check to do! See later examples. #### Optimistic: Bad behavior on fields The RWC suite

Comments (0)

No comments yet. Start the discussion.

Comment on this issue