Skip to content

Commit

Permalink
Bailout early from isFunctionObjectType for evolving arrays (#58049)
Browse files Browse the repository at this point in the history
Co-authored-by: Jake Bailey <[email protected]>
  • Loading branch information
Andarist and jakebailey authored Jul 26, 2024
1 parent 74cefa8 commit 1da9630
Show file tree
Hide file tree
Showing 5 changed files with 150 additions and 0 deletions.
3 changes: 3 additions & 0 deletions src/compiler/checker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27381,6 +27381,9 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
}

function isFunctionObjectType(type: ObjectType): boolean {
if (getObjectFlags(type) & ObjectFlags.EvolvingArray) {
return false;
}
// We do a quick check for a "bind" property before performing the more expensive subtype
// check. This gives us a quicker out in the common case where an object type is not a function.
const resolved = resolveStructuredTypeMembers(type);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
narrowSwitchOptionalChainContainmentEvolvingArrayNoCrash1.ts(1,5): error TS7034: Variable 'foo' implicitly has type 'any[]' in some locations where its type cannot be determined.
narrowSwitchOptionalChainContainmentEvolvingArrayNoCrash1.ts(5,5): error TS7005: Variable 'foo' implicitly has an 'any[]' type.


==== narrowSwitchOptionalChainContainmentEvolvingArrayNoCrash1.ts (2 errors) ====
let foo = [];
~~~
!!! error TS7034: Variable 'foo' implicitly has type 'any[]' in some locations where its type cannot be determined.

switch (foo?.length) {
case 1:
foo[0];
~~~
!!! error TS7005: Variable 'foo' implicitly has an 'any[]' type.
}

let bar = [];

switch (bar?.length) {
case 1: {
bar.push("baz");
const arr: string[] = bar;
}
}

Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
//// [tests/cases/compiler/narrowSwitchOptionalChainContainmentEvolvingArrayNoCrash1.ts] ////

=== narrowSwitchOptionalChainContainmentEvolvingArrayNoCrash1.ts ===
let foo = [];
>foo : Symbol(foo, Decl(narrowSwitchOptionalChainContainmentEvolvingArrayNoCrash1.ts, 0, 3))

switch (foo?.length) {
>foo?.length : Symbol(Array.length, Decl(lib.es5.d.ts, --, --))
>foo : Symbol(foo, Decl(narrowSwitchOptionalChainContainmentEvolvingArrayNoCrash1.ts, 0, 3))
>length : Symbol(Array.length, Decl(lib.es5.d.ts, --, --))

case 1:
foo[0];
>foo : Symbol(foo, Decl(narrowSwitchOptionalChainContainmentEvolvingArrayNoCrash1.ts, 0, 3))
}

let bar = [];
>bar : Symbol(bar, Decl(narrowSwitchOptionalChainContainmentEvolvingArrayNoCrash1.ts, 7, 3))

switch (bar?.length) {
>bar?.length : Symbol(Array.length, Decl(lib.es5.d.ts, --, --))
>bar : Symbol(bar, Decl(narrowSwitchOptionalChainContainmentEvolvingArrayNoCrash1.ts, 7, 3))
>length : Symbol(Array.length, Decl(lib.es5.d.ts, --, --))

case 1: {
bar.push("baz");
>bar.push : Symbol(Array.push, Decl(lib.es5.d.ts, --, --))
>bar : Symbol(bar, Decl(narrowSwitchOptionalChainContainmentEvolvingArrayNoCrash1.ts, 7, 3))
>push : Symbol(Array.push, Decl(lib.es5.d.ts, --, --))

const arr: string[] = bar;
>arr : Symbol(arr, Decl(narrowSwitchOptionalChainContainmentEvolvingArrayNoCrash1.ts, 12, 9))
>bar : Symbol(bar, Decl(narrowSwitchOptionalChainContainmentEvolvingArrayNoCrash1.ts, 7, 3))
}
}

Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
//// [tests/cases/compiler/narrowSwitchOptionalChainContainmentEvolvingArrayNoCrash1.ts] ////

=== narrowSwitchOptionalChainContainmentEvolvingArrayNoCrash1.ts ===
let foo = [];
>foo : any[]
> : ^^^^^
>[] : never[]
> : ^^^^^^^

switch (foo?.length) {
>foo?.length : number
> : ^^^^^^
>foo : any[]
> : ^^^^^
>length : number
> : ^^^^^^

case 1:
>1 : 1
> : ^

foo[0];
>foo[0] : any
> : ^^^
>foo : any[]
> : ^^^^^
>0 : 0
> : ^
}

let bar = [];
>bar : any[]
> : ^^^^^
>[] : never[]
> : ^^^^^^^

switch (bar?.length) {
>bar?.length : number
> : ^^^^^^
>bar : any[]
> : ^^^^^
>length : number
> : ^^^^^^

case 1: {
>1 : 1
> : ^

bar.push("baz");
>bar.push("baz") : number
> : ^^^^^^
>bar.push : (...items: any[]) => number
> : ^^^^ ^^^^^^^^^^^^
>bar : any[]
> : ^^^^^
>push : (...items: any[]) => number
> : ^^^^ ^^^^^^^^^^^^
>"baz" : "baz"
> : ^^^^^

const arr: string[] = bar;
>arr : string[]
> : ^^^^^^^^
>bar : string[]
> : ^^^^^^^^
}
}

Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
// @strict: true
// @noEmit: true

let foo = [];

switch (foo?.length) {
case 1:
foo[0];
}

let bar = [];

switch (bar?.length) {
case 1: {
bar.push("baz");
const arr: string[] = bar;
}
}

0 comments on commit 1da9630

Please sign in to comment.