-
Notifications
You must be signed in to change notification settings - Fork 12.5k
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
Control flow analysis for array construction #11432
Merged
Merged
Changes from 20 commits
Commits
Show all changes
24 commits
Select commit
Hold shift + click to select a range
9ca2569
Use control flow analysis for variables initialized with []
ahejlsberg b5c1055
Accept new baselines
ahejlsberg 9c4190b
Introduce sameMap function
ahejlsberg 144f4ff
Accept new baselines
ahejlsberg a9c2b23
Add tests
ahejlsberg c0c2271
Accept new baselines
ahejlsberg b8d5226
Merge branch 'master' into controlFlowArrays
ahejlsberg 12906a7
Fix some minor issues
ahejlsberg 2f5af2e
Add additional test
ahejlsberg 71b9b33
Fix issue in control flow analysis of nested loops
ahejlsberg d202b1c
Add test
ahejlsberg 89826a5
Accept new baselines
ahejlsberg e6b588a
Support parentheses and comma operator with evolving arrays
ahejlsberg 612ed1e
Fix minor issue
ahejlsberg e9858de
Add test
ahejlsberg c9e2f95
Accept new baselines
ahejlsberg 38278ee
Fix typo
ahejlsberg 1dedca7
Support 'unshift' and fix typo
ahejlsberg 620b3f9
Fix test
ahejlsberg a27a68f
Add additional tests
ahejlsberg bf301e9
Treat reference to empty evolving array as an implicit any[]
ahejlsberg bfa4197
Update tests
ahejlsberg 79ed3a7
Accept new baselines
ahejlsberg c876d92
Merge branch 'master' into controlFlowArrays
ahejlsberg File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
99 changes: 99 additions & 0 deletions
99
tests/baselines/reference/controlFlowArrayErrors.errors.txt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,99 @@ | ||
tests/cases/compiler/controlFlowArrayErrors.ts(6,9): error TS7005: Variable 'y' implicitly has an 'any[]' type. | ||
tests/cases/compiler/controlFlowArrayErrors.ts(14,9): error TS7005: Variable 'y' implicitly has an 'any[]' type. | ||
tests/cases/compiler/controlFlowArrayErrors.ts(20,9): error TS7034: Variable 'x' implicitly has type 'any[]' in some locations where its type cannot be determined. | ||
tests/cases/compiler/controlFlowArrayErrors.ts(23,9): error TS7005: Variable 'x' implicitly has an 'any[]' type. | ||
tests/cases/compiler/controlFlowArrayErrors.ts(30,12): error TS2345: Argument of type 'true' is not assignable to parameter of type 'string | number'. | ||
tests/cases/compiler/controlFlowArrayErrors.ts(35,12): error TS2345: Argument of type 'true' is not assignable to parameter of type 'string | number'. | ||
tests/cases/compiler/controlFlowArrayErrors.ts(49,5): error TS2349: Cannot invoke an expression whose type lacks a call signature. Type '((...items: (string | number)[]) => number) | ((...items: boolean[]) => number)' has no compatible call signatures. | ||
tests/cases/compiler/controlFlowArrayErrors.ts(57,12): error TS2345: Argument of type '"hello"' is not assignable to parameter of type 'number'. | ||
tests/cases/compiler/controlFlowArrayErrors.ts(61,11): error TS7034: Variable 'x' implicitly has type 'any[]' in some locations where its type cannot be determined. | ||
tests/cases/compiler/controlFlowArrayErrors.ts(64,9): error TS7005: Variable 'x' implicitly has an 'any[]' type. | ||
|
||
|
||
==== tests/cases/compiler/controlFlowArrayErrors.ts (10 errors) ==== | ||
|
||
declare function cond(): boolean; | ||
|
||
function f1() { | ||
let x = []; | ||
let y = x; // Implicit any[] error | ||
~ | ||
!!! error TS7005: Variable 'y' implicitly has an 'any[]' type. | ||
x.push(5); | ||
let z = x; | ||
} | ||
|
||
function f2() { | ||
let x; | ||
x = []; | ||
let y = x; // Implicit any[] error | ||
~ | ||
!!! error TS7005: Variable 'y' implicitly has an 'any[]' type. | ||
x.push(5); | ||
let z = x; | ||
} | ||
|
||
function f3() { | ||
let x = []; // Implicit any[] error in some locations | ||
~ | ||
!!! error TS7034: Variable 'x' implicitly has type 'any[]' in some locations where its type cannot be determined. | ||
x.push(5); | ||
function g() { | ||
x; // Implicit any[] error | ||
~ | ||
!!! error TS7005: Variable 'x' implicitly has an 'any[]' type. | ||
} | ||
} | ||
|
||
function f4() { | ||
let x; | ||
x = [5, "hello"]; // Non-evolving array | ||
x.push(true); // Error | ||
~~~~ | ||
!!! error TS2345: Argument of type 'true' is not assignable to parameter of type 'string | number'. | ||
} | ||
|
||
function f5() { | ||
let x = [5, "hello"]; // Non-evolving array | ||
x.push(true); // Error | ||
~~~~ | ||
!!! error TS2345: Argument of type 'true' is not assignable to parameter of type 'string | number'. | ||
} | ||
|
||
function f6() { | ||
let x; | ||
if (cond()) { | ||
x = []; | ||
x.push(5); | ||
x.push("hello"); | ||
} | ||
else { | ||
x = [true]; // Non-evolving array | ||
} | ||
x; // boolean[] | (string | number)[] | ||
x.push(99); // Error | ||
~~~~~~~~~~ | ||
!!! error TS2349: Cannot invoke an expression whose type lacks a call signature. Type '((...items: (string | number)[]) => number) | ((...items: boolean[]) => number)' has no compatible call signatures. | ||
} | ||
|
||
function f7() { | ||
let x = []; // x has evolving array value | ||
x.push(5); | ||
let y = x; // y has non-evolving array value | ||
x.push("hello"); // Ok | ||
y.push("hello"); // Error | ||
~~~~~~~ | ||
!!! error TS2345: Argument of type '"hello"' is not assignable to parameter of type 'number'. | ||
} | ||
|
||
function f8() { | ||
const x = []; // Implicit any[] error in some locations | ||
~ | ||
!!! error TS7034: Variable 'x' implicitly has type 'any[]' in some locations where its type cannot be determined. | ||
x.push(5); | ||
function g() { | ||
x; // Implicit any[] error | ||
~ | ||
!!! error TS7005: Variable 'x' implicitly has an 'any[]' type. | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,125 @@ | ||
//// [controlFlowArrayErrors.ts] | ||
|
||
declare function cond(): boolean; | ||
|
||
function f1() { | ||
let x = []; | ||
let y = x; // Implicit any[] error | ||
x.push(5); | ||
let z = x; | ||
} | ||
|
||
function f2() { | ||
let x; | ||
x = []; | ||
let y = x; // Implicit any[] error | ||
x.push(5); | ||
let z = x; | ||
} | ||
|
||
function f3() { | ||
let x = []; // Implicit any[] error in some locations | ||
x.push(5); | ||
function g() { | ||
x; // Implicit any[] error | ||
} | ||
} | ||
|
||
function f4() { | ||
let x; | ||
x = [5, "hello"]; // Non-evolving array | ||
x.push(true); // Error | ||
} | ||
|
||
function f5() { | ||
let x = [5, "hello"]; // Non-evolving array | ||
x.push(true); // Error | ||
} | ||
|
||
function f6() { | ||
let x; | ||
if (cond()) { | ||
x = []; | ||
x.push(5); | ||
x.push("hello"); | ||
} | ||
else { | ||
x = [true]; // Non-evolving array | ||
} | ||
x; // boolean[] | (string | number)[] | ||
x.push(99); // Error | ||
} | ||
|
||
function f7() { | ||
let x = []; // x has evolving array value | ||
x.push(5); | ||
let y = x; // y has non-evolving array value | ||
x.push("hello"); // Ok | ||
y.push("hello"); // Error | ||
} | ||
|
||
function f8() { | ||
const x = []; // Implicit any[] error in some locations | ||
x.push(5); | ||
function g() { | ||
x; // Implicit any[] error | ||
} | ||
} | ||
|
||
//// [controlFlowArrayErrors.js] | ||
function f1() { | ||
var x = []; | ||
var y = x; // Implicit any[] error | ||
x.push(5); | ||
var z = x; | ||
} | ||
function f2() { | ||
var x; | ||
x = []; | ||
var y = x; // Implicit any[] error | ||
x.push(5); | ||
var z = x; | ||
} | ||
function f3() { | ||
var x = []; // Implicit any[] error in some locations | ||
x.push(5); | ||
function g() { | ||
x; // Implicit any[] error | ||
} | ||
} | ||
function f4() { | ||
var x; | ||
x = [5, "hello"]; // Non-evolving array | ||
x.push(true); // Error | ||
} | ||
function f5() { | ||
var x = [5, "hello"]; // Non-evolving array | ||
x.push(true); // Error | ||
} | ||
function f6() { | ||
var x; | ||
if (cond()) { | ||
x = []; | ||
x.push(5); | ||
x.push("hello"); | ||
} | ||
else { | ||
x = [true]; // Non-evolving array | ||
} | ||
x; // boolean[] | (string | number)[] | ||
x.push(99); // Error | ||
} | ||
function f7() { | ||
var x = []; // x has evolving array value | ||
x.push(5); | ||
var y = x; // y has non-evolving array value | ||
x.push("hello"); // Ok | ||
y.push("hello"); // Error | ||
} | ||
function f8() { | ||
var x = []; // Implicit any[] error in some locations | ||
x.push(5); | ||
function g() { | ||
x; // Implicit any[] error | ||
} | ||
} |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
why isn't AutoArrayType a new subtype of AnonymousType? I think it would make it easier to track the property that auto array types don't escape the dynamic scope of
getFlowTypeOfReference
.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't follow.
autoArrayType
is the declared type of an auto-inferredany[]
and it's already used outside ofgetFlowTypeOfReference
.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's separate from
autoArrayType
, whose type is actually TypeReference.I'm talking about the comment at the top of the new code that says
I was suggesting something like:
And then having the new code that returns AnonymousType today return AutoArrayType instead.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh, I see. The issue with doing it that way is that we don't have a
TypeFlags.EvolvingArrayType
that would indicate an evolving array type (because we're out of flag bits). Instead, we distinguish by looking for theelementType
property onAnonymousType
, so it has to be part ofAnonymousType
.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok, that makes sense.