Skip to content

Commit af027f3

Browse files
Bail on 0- and 1-length lists in removeSubtypes to avoid spurious circularity problems (microsoft#46981)
* Creates a reasonable workaround for microsoft#46939 * Remove unrelated newline * Do the cheap length check ahead of the cache check * Actually do it.
1 parent d8b21a8 commit af027f3

10 files changed

+265
-0
lines changed

src/compiler/checker.ts

+6
Original file line numberDiff line numberDiff line change
@@ -14393,11 +14393,17 @@ namespace ts {
1439314393
}
1439414394

1439514395
function removeSubtypes(types: Type[], hasObjectTypes: boolean): Type[] | undefined {
14396+
// [] and [T] immediately reduce to [] and [T] respectively
14397+
if (types.length < 2) {
14398+
return types;
14399+
}
14400+
1439614401
const id = getTypeListId(types);
1439714402
const match = subtypeReductionCache.get(id);
1439814403
if (match) {
1439914404
return match;
1440014405
}
14406+
1440114407
// We assume that redundant primitive types have already been removed from the types array and that there
1440214408
// are no any and unknown types in the array. Thus, the only possible supertypes for primitive types are empty
1440314409
// object types, and if none of those are present we can exclude primitive types from the subtype check.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
tests/cases/compiler/trivialSubtypeReductionNoStructuralCheck.ts(3,7): error TS7023: 'steps' implicitly has return type 'any' because it does not have a return type annotation and is referenced directly or indirectly in one of its return expressions.
2+
3+
4+
==== tests/cases/compiler/trivialSubtypeReductionNoStructuralCheck.ts (1 errors) ====
5+
declare const props: WizardStepProps;
6+
export class Wizard {
7+
get steps() {
8+
~~~~~
9+
!!! error TS7023: 'steps' implicitly has return type 'any' because it does not have a return type annotation and is referenced directly or indirectly in one of its return expressions.
10+
return {
11+
wizard: this,
12+
...props,
13+
} as WizardStepProps;
14+
}
15+
}
16+
17+
export interface WizardStepProps {
18+
wizard?: Wizard;
19+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
//// [trivialSubtypeReductionNoStructuralCheck.ts]
2+
declare const props: WizardStepProps;
3+
export class Wizard {
4+
get steps() {
5+
return {
6+
wizard: this,
7+
...props,
8+
} as WizardStepProps;
9+
}
10+
}
11+
12+
export interface WizardStepProps {
13+
wizard?: Wizard;
14+
}
15+
16+
//// [trivialSubtypeReductionNoStructuralCheck.js]
17+
"use strict";
18+
var __assign = (this && this.__assign) || function () {
19+
__assign = Object.assign || function(t) {
20+
for (var s, i = 1, n = arguments.length; i < n; i++) {
21+
s = arguments[i];
22+
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
23+
t[p] = s[p];
24+
}
25+
return t;
26+
};
27+
return __assign.apply(this, arguments);
28+
};
29+
Object.defineProperty(exports, "__esModule", { value: true });
30+
exports.Wizard = void 0;
31+
var Wizard = /** @class */ (function () {
32+
function Wizard() {
33+
}
34+
Object.defineProperty(Wizard.prototype, "steps", {
35+
get: function () {
36+
return __assign({ wizard: this }, props);
37+
},
38+
enumerable: false,
39+
configurable: true
40+
});
41+
return Wizard;
42+
}());
43+
exports.Wizard = Wizard;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
=== tests/cases/compiler/trivialSubtypeReductionNoStructuralCheck.ts ===
2+
declare const props: WizardStepProps;
3+
>props : Symbol(props, Decl(trivialSubtypeReductionNoStructuralCheck.ts, 0, 13))
4+
>WizardStepProps : Symbol(WizardStepProps, Decl(trivialSubtypeReductionNoStructuralCheck.ts, 8, 1))
5+
6+
export class Wizard {
7+
>Wizard : Symbol(Wizard, Decl(trivialSubtypeReductionNoStructuralCheck.ts, 0, 37))
8+
9+
get steps() {
10+
>steps : Symbol(Wizard.steps, Decl(trivialSubtypeReductionNoStructuralCheck.ts, 1, 21))
11+
12+
return {
13+
wizard: this,
14+
>wizard : Symbol(wizard, Decl(trivialSubtypeReductionNoStructuralCheck.ts, 3, 12))
15+
>this : Symbol(Wizard, Decl(trivialSubtypeReductionNoStructuralCheck.ts, 0, 37))
16+
17+
...props,
18+
>props : Symbol(props, Decl(trivialSubtypeReductionNoStructuralCheck.ts, 0, 13))
19+
20+
} as WizardStepProps;
21+
>WizardStepProps : Symbol(WizardStepProps, Decl(trivialSubtypeReductionNoStructuralCheck.ts, 8, 1))
22+
}
23+
}
24+
25+
export interface WizardStepProps {
26+
>WizardStepProps : Symbol(WizardStepProps, Decl(trivialSubtypeReductionNoStructuralCheck.ts, 8, 1))
27+
28+
wizard?: Wizard;
29+
>wizard : Symbol(WizardStepProps.wizard, Decl(trivialSubtypeReductionNoStructuralCheck.ts, 10, 34))
30+
>Wizard : Symbol(Wizard, Decl(trivialSubtypeReductionNoStructuralCheck.ts, 0, 37))
31+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
=== tests/cases/compiler/trivialSubtypeReductionNoStructuralCheck.ts ===
2+
declare const props: WizardStepProps;
3+
>props : WizardStepProps
4+
5+
export class Wizard {
6+
>Wizard : Wizard
7+
8+
get steps() {
9+
>steps : any
10+
11+
return {
12+
>{ wizard: this, ...props, } as WizardStepProps : WizardStepProps
13+
>{ wizard: this, ...props, } : { wizard: Wizard; }
14+
15+
wizard: this,
16+
>wizard : this
17+
>this : this
18+
19+
...props,
20+
>props : WizardStepProps
21+
22+
} as WizardStepProps;
23+
}
24+
}
25+
26+
export interface WizardStepProps {
27+
wizard?: Wizard;
28+
>wizard : Wizard | undefined
29+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
//// [trivialSubtypeReductionNoStructuralCheck2.ts]
2+
declare const props: WizardStepProps;
3+
export class Wizard {
4+
get steps() {
5+
return {
6+
wizard: this as Wizard,
7+
...props,
8+
} as WizardStepProps;
9+
}
10+
}
11+
12+
export interface WizardStepProps {
13+
wizard?: Wizard;
14+
}
15+
16+
//// [trivialSubtypeReductionNoStructuralCheck2.js]
17+
"use strict";
18+
var __assign = (this && this.__assign) || function () {
19+
__assign = Object.assign || function(t) {
20+
for (var s, i = 1, n = arguments.length; i < n; i++) {
21+
s = arguments[i];
22+
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
23+
t[p] = s[p];
24+
}
25+
return t;
26+
};
27+
return __assign.apply(this, arguments);
28+
};
29+
Object.defineProperty(exports, "__esModule", { value: true });
30+
exports.Wizard = void 0;
31+
var Wizard = /** @class */ (function () {
32+
function Wizard() {
33+
}
34+
Object.defineProperty(Wizard.prototype, "steps", {
35+
get: function () {
36+
return __assign({ wizard: this }, props);
37+
},
38+
enumerable: false,
39+
configurable: true
40+
});
41+
return Wizard;
42+
}());
43+
exports.Wizard = Wizard;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
=== tests/cases/compiler/trivialSubtypeReductionNoStructuralCheck2.ts ===
2+
declare const props: WizardStepProps;
3+
>props : Symbol(props, Decl(trivialSubtypeReductionNoStructuralCheck2.ts, 0, 13))
4+
>WizardStepProps : Symbol(WizardStepProps, Decl(trivialSubtypeReductionNoStructuralCheck2.ts, 8, 1))
5+
6+
export class Wizard {
7+
>Wizard : Symbol(Wizard, Decl(trivialSubtypeReductionNoStructuralCheck2.ts, 0, 37))
8+
9+
get steps() {
10+
>steps : Symbol(Wizard.steps, Decl(trivialSubtypeReductionNoStructuralCheck2.ts, 1, 21))
11+
12+
return {
13+
wizard: this as Wizard,
14+
>wizard : Symbol(wizard, Decl(trivialSubtypeReductionNoStructuralCheck2.ts, 3, 12))
15+
>this : Symbol(Wizard, Decl(trivialSubtypeReductionNoStructuralCheck2.ts, 0, 37))
16+
>Wizard : Symbol(Wizard, Decl(trivialSubtypeReductionNoStructuralCheck2.ts, 0, 37))
17+
18+
...props,
19+
>props : Symbol(props, Decl(trivialSubtypeReductionNoStructuralCheck2.ts, 0, 13))
20+
21+
} as WizardStepProps;
22+
>WizardStepProps : Symbol(WizardStepProps, Decl(trivialSubtypeReductionNoStructuralCheck2.ts, 8, 1))
23+
}
24+
}
25+
26+
export interface WizardStepProps {
27+
>WizardStepProps : Symbol(WizardStepProps, Decl(trivialSubtypeReductionNoStructuralCheck2.ts, 8, 1))
28+
29+
wizard?: Wizard;
30+
>wizard : Symbol(WizardStepProps.wizard, Decl(trivialSubtypeReductionNoStructuralCheck2.ts, 10, 34))
31+
>Wizard : Symbol(Wizard, Decl(trivialSubtypeReductionNoStructuralCheck2.ts, 0, 37))
32+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
=== tests/cases/compiler/trivialSubtypeReductionNoStructuralCheck2.ts ===
2+
declare const props: WizardStepProps;
3+
>props : WizardStepProps
4+
5+
export class Wizard {
6+
>Wizard : Wizard
7+
8+
get steps() {
9+
>steps : WizardStepProps
10+
11+
return {
12+
>{ wizard: this as Wizard, ...props, } as WizardStepProps : WizardStepProps
13+
>{ wizard: this as Wizard, ...props, } : { wizard: Wizard; }
14+
15+
wizard: this as Wizard,
16+
>wizard : Wizard
17+
>this as Wizard : Wizard
18+
>this : this
19+
20+
...props,
21+
>props : WizardStepProps
22+
23+
} as WizardStepProps;
24+
}
25+
}
26+
27+
export interface WizardStepProps {
28+
wizard?: Wizard;
29+
>wizard : Wizard | undefined
30+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
// @strict: true
2+
// @target: es5
3+
4+
declare const props: WizardStepProps;
5+
export class Wizard {
6+
get steps() {
7+
return {
8+
wizard: this,
9+
...props,
10+
} as WizardStepProps;
11+
}
12+
}
13+
14+
export interface WizardStepProps {
15+
wizard?: Wizard;
16+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
// @strict: true
2+
// @target: es5
3+
4+
declare const props: WizardStepProps;
5+
export class Wizard {
6+
get steps() {
7+
return {
8+
wizard: this as Wizard,
9+
...props,
10+
} as WizardStepProps;
11+
}
12+
}
13+
14+
export interface WizardStepProps {
15+
wizard?: Wizard;
16+
}

0 commit comments

Comments
 (0)