Bailout early from isFunctionObjectType for evolving arrays (#58049)

Co-authored-by: Jake Bailey <5341706+jakebailey@users.noreply.github.com>
This commit is contained in:
Mateusz Burzyński 2024-07-26 19:09:02 +02:00 committed by GitHub
parent 74cefa848c
commit 1da9630a34
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 150 additions and 0 deletions

View File

@ -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);

View File

@ -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;
}
}

View File

@ -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))
}
}

View File

@ -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[]
> : ^^^^^^^^
}
}

View File

@ -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;
}
}