Skip to content

Commit 4eef417

Browse files
committed
Merge remote-tracking branch 'origin/master' into go_to_implementation_pr
2 parents fd93699 + bbf80a7 commit 4eef417

File tree

8 files changed

+300
-26
lines changed

8 files changed

+300
-26
lines changed

src/compiler/checker.ts

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -7603,16 +7603,24 @@ namespace ts {
76037603
}
76047604
return;
76057605
}
7606-
// Find each target constituent type that has an identically matching source
7607-
// constituent type, and for each such target constituent type infer from the type to
7608-
// itself. When inferring from a type to itself we effectively find all type parameter
7609-
// occurrences within that type and infer themselves as their type arguments.
7606+
// Find each source constituent type that has an identically matching target constituent
7607+
// type, and for each such type infer from the type to itself. When inferring from a
7608+
// type to itself we effectively find all type parameter occurrences within that type
7609+
// and infer themselves as their type arguments. We have special handling for numeric
7610+
// and string literals because the number and string types are not represented as unions
7611+
// of all their possible values.
76107612
let matchingTypes: Type[];
7611-
for (const t of (<UnionOrIntersectionType>target).types) {
7612-
if (typeIdenticalToSomeType(t, (<UnionOrIntersectionType>source).types)) {
7613+
for (const t of (<UnionOrIntersectionType>source).types) {
7614+
if (typeIdenticalToSomeType(t, (<UnionOrIntersectionType>target).types)) {
76137615
(matchingTypes || (matchingTypes = [])).push(t);
76147616
inferFromTypes(t, t);
76157617
}
7618+
else if (t.flags & (TypeFlags.NumberLiteral | TypeFlags.StringLiteral)) {
7619+
const b = getBaseTypeOfLiteralType(t);
7620+
if (typeIdenticalToSomeType(b, (<UnionOrIntersectionType>target).types)) {
7621+
(matchingTypes || (matchingTypes = [])).push(t, b);
7622+
}
7623+
}
76167624
}
76177625
// Next, to improve the quality of inferences, reduce the source and target types by
76187626
// removing the identically matched constituents. For example, when inferring from

src/compiler/transformers/es6.ts

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ namespace ts {
1010
/** Enables substitutions for block-scoped bindings. */
1111
BlockScopedBindings = 1 << 1,
1212
}
13+
1314
/**
1415
* If loop contains block scoped binding captured in some function then loop body is converted to a function.
1516
* Lexical bindings declared in loop initializer will be passed into the loop body function as parameters,
@@ -166,6 +167,9 @@ namespace ts {
166167
let enclosingBlockScopeContainerParent: Node;
167168
let containingNonArrowFunction: FunctionLikeDeclaration | ClassElement;
168169

170+
/** Tracks the container that determines whether `super.x` is a static. */
171+
let superScopeContainer: FunctionLikeDeclaration | ClassElement;
172+
169173
/**
170174
* Used to track if we are emitting body of the converted loop
171175
*/
@@ -203,6 +207,7 @@ namespace ts {
203207

204208
function saveStateAndInvoke<T>(node: Node, f: (node: Node) => T): T {
205209
const savedContainingNonArrowFunction = containingNonArrowFunction;
210+
const savedSuperScopeContainer = superScopeContainer;
206211
const savedCurrentParent = currentParent;
207212
const savedCurrentNode = currentNode;
208213
const savedEnclosingBlockScopeContainer = enclosingBlockScopeContainer;
@@ -219,6 +224,7 @@ namespace ts {
219224

220225
convertedLoopState = savedConvertedLoopState;
221226
containingNonArrowFunction = savedContainingNonArrowFunction;
227+
superScopeContainer = savedSuperScopeContainer;
222228
currentParent = savedCurrentParent;
223229
currentNode = savedCurrentNode;
224230
enclosingBlockScopeContainer = savedEnclosingBlockScopeContainer;
@@ -414,13 +420,16 @@ namespace ts {
414420
}
415421

416422
switch (currentParent.kind) {
423+
case SyntaxKind.FunctionExpression:
417424
case SyntaxKind.Constructor:
418425
case SyntaxKind.MethodDeclaration:
419426
case SyntaxKind.GetAccessor:
420427
case SyntaxKind.SetAccessor:
421428
case SyntaxKind.FunctionDeclaration:
422-
case SyntaxKind.FunctionExpression:
423429
containingNonArrowFunction = <FunctionLikeDeclaration>currentParent;
430+
if (!(containingNonArrowFunction.emitFlags & NodeEmitFlags.AsyncFunctionBody)) {
431+
superScopeContainer = containingNonArrowFunction;
432+
}
424433
break;
425434
}
426435
}
@@ -2820,9 +2829,9 @@ namespace ts {
28202829
* Visits the `super` keyword
28212830
*/
28222831
function visitSuperKeyword(node: PrimaryExpression): LeftHandSideExpression {
2823-
return containingNonArrowFunction
2824-
&& isClassElement(containingNonArrowFunction)
2825-
&& !hasModifier(containingNonArrowFunction, ModifierFlags.Static)
2832+
return superScopeContainer
2833+
&& isClassElement(superScopeContainer)
2834+
&& !hasModifier(superScopeContainer, ModifierFlags.Static)
28262835
&& currentParent.kind !== SyntaxKind.CallExpression
28272836
? createPropertyAccess(createIdentifier("_super"), "prototype")
28282837
: createIdentifier("_super");

tests/baselines/reference/asyncMethodWithSuper_es5.js

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -69,11 +69,11 @@ var B = (function (_super) {
6969
var a, b;
7070
return __generator(this, function (_a) {
7171
// call with property access
72-
_super.x.call(this);
72+
_super.prototype.x.call(this);
7373
// call with element access
74-
_super["x"].call(this);
75-
a = _super.x;
76-
b = _super["x"];
74+
_super.prototype["x"].call(this);
75+
a = _super.prototype.x;
76+
b = _super.prototype["x"];
7777
return [2 /*return*/];
7878
});
7979
});
@@ -85,15 +85,15 @@ var B = (function (_super) {
8585
return __generator(this, function (_c) {
8686
f = function () { };
8787
// call with property access
88-
_super.x.call(this);
88+
_super.prototype.x.call(this);
8989
// call with element access
90-
_super["x"].call(this);
91-
a = _super.x;
92-
b = _super["x"];
90+
_super.prototype["x"].call(this);
91+
a = _super.prototype.x;
92+
b = _super.prototype["x"];
9393
// property access (assign)
94-
_super.x = f;
94+
_super.prototype.x = f;
9595
// element access (assign)
96-
_super["x"] = f;
96+
_super.prototype["x"] = f;
9797
// destructuring assign with property access
9898
(_a = { f: f }, super.x = _a.f, _a);
9999
// destructuring assign with element access
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
//// [typeInferenceLiteralUnion.ts]
2+
// Repro from #10901
3+
/**
4+
* Administrivia: JavaScript primitive types and Date
5+
*/
6+
export type Primitive = number | string | boolean | Date;
7+
8+
/**
9+
* Administrivia: anything with a valueOf(): number method is comparable, so we allow it in numeric operations
10+
*/
11+
interface Numeric {
12+
valueOf(): number;
13+
}
14+
15+
// Not very useful, but meets Numeric
16+
class NumCoercible {
17+
public a: number;
18+
19+
constructor(a: number) {
20+
this.a = a;
21+
}
22+
public valueOf() {
23+
return this.a;
24+
}
25+
}
26+
27+
/**
28+
* Return the min and max simultaneously.
29+
*/
30+
export function extent<T extends Numeric>(array: Array<T | Primitive>): [T | Primitive, T | Primitive] | [undefined, undefined] {
31+
return [undefined, undefined];
32+
}
33+
34+
35+
let extentMixed: [Primitive | NumCoercible, Primitive | NumCoercible] | [undefined, undefined];
36+
extentMixed = extent([new NumCoercible(10), 13, '12', true]);
37+
38+
39+
//// [typeInferenceLiteralUnion.js]
40+
"use strict";
41+
// Not very useful, but meets Numeric
42+
var NumCoercible = (function () {
43+
function NumCoercible(a) {
44+
this.a = a;
45+
}
46+
NumCoercible.prototype.valueOf = function () {
47+
return this.a;
48+
};
49+
return NumCoercible;
50+
}());
51+
/**
52+
* Return the min and max simultaneously.
53+
*/
54+
function extent(array) {
55+
return [undefined, undefined];
56+
}
57+
exports.extent = extent;
58+
var extentMixed;
59+
extentMixed = extent([new NumCoercible(10), 13, '12', true]);
Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
=== tests/cases/compiler/typeInferenceLiteralUnion.ts ===
2+
// Repro from #10901
3+
/**
4+
* Administrivia: JavaScript primitive types and Date
5+
*/
6+
export type Primitive = number | string | boolean | Date;
7+
>Primitive : Symbol(Primitive, Decl(typeInferenceLiteralUnion.ts, 0, 0))
8+
>Date : Symbol(Date, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --))
9+
10+
/**
11+
* Administrivia: anything with a valueOf(): number method is comparable, so we allow it in numeric operations
12+
*/
13+
interface Numeric {
14+
>Numeric : Symbol(Numeric, Decl(typeInferenceLiteralUnion.ts, 4, 57))
15+
16+
valueOf(): number;
17+
>valueOf : Symbol(Numeric.valueOf, Decl(typeInferenceLiteralUnion.ts, 9, 19))
18+
}
19+
20+
// Not very useful, but meets Numeric
21+
class NumCoercible {
22+
>NumCoercible : Symbol(NumCoercible, Decl(typeInferenceLiteralUnion.ts, 11, 1))
23+
24+
public a: number;
25+
>a : Symbol(NumCoercible.a, Decl(typeInferenceLiteralUnion.ts, 14, 20))
26+
27+
constructor(a: number) {
28+
>a : Symbol(a, Decl(typeInferenceLiteralUnion.ts, 17, 16))
29+
30+
this.a = a;
31+
>this.a : Symbol(NumCoercible.a, Decl(typeInferenceLiteralUnion.ts, 14, 20))
32+
>this : Symbol(NumCoercible, Decl(typeInferenceLiteralUnion.ts, 11, 1))
33+
>a : Symbol(NumCoercible.a, Decl(typeInferenceLiteralUnion.ts, 14, 20))
34+
>a : Symbol(a, Decl(typeInferenceLiteralUnion.ts, 17, 16))
35+
}
36+
public valueOf() {
37+
>valueOf : Symbol(NumCoercible.valueOf, Decl(typeInferenceLiteralUnion.ts, 19, 5))
38+
39+
return this.a;
40+
>this.a : Symbol(NumCoercible.a, Decl(typeInferenceLiteralUnion.ts, 14, 20))
41+
>this : Symbol(NumCoercible, Decl(typeInferenceLiteralUnion.ts, 11, 1))
42+
>a : Symbol(NumCoercible.a, Decl(typeInferenceLiteralUnion.ts, 14, 20))
43+
}
44+
}
45+
46+
/**
47+
* Return the min and max simultaneously.
48+
*/
49+
export function extent<T extends Numeric>(array: Array<T | Primitive>): [T | Primitive, T | Primitive] | [undefined, undefined] {
50+
>extent : Symbol(extent, Decl(typeInferenceLiteralUnion.ts, 23, 1))
51+
>T : Symbol(T, Decl(typeInferenceLiteralUnion.ts, 28, 23))
52+
>Numeric : Symbol(Numeric, Decl(typeInferenceLiteralUnion.ts, 4, 57))
53+
>array : Symbol(array, Decl(typeInferenceLiteralUnion.ts, 28, 42))
54+
>Array : Symbol(Array, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --))
55+
>T : Symbol(T, Decl(typeInferenceLiteralUnion.ts, 28, 23))
56+
>Primitive : Symbol(Primitive, Decl(typeInferenceLiteralUnion.ts, 0, 0))
57+
>T : Symbol(T, Decl(typeInferenceLiteralUnion.ts, 28, 23))
58+
>Primitive : Symbol(Primitive, Decl(typeInferenceLiteralUnion.ts, 0, 0))
59+
>T : Symbol(T, Decl(typeInferenceLiteralUnion.ts, 28, 23))
60+
>Primitive : Symbol(Primitive, Decl(typeInferenceLiteralUnion.ts, 0, 0))
61+
62+
return [undefined, undefined];
63+
>undefined : Symbol(undefined)
64+
>undefined : Symbol(undefined)
65+
}
66+
67+
68+
let extentMixed: [Primitive | NumCoercible, Primitive | NumCoercible] | [undefined, undefined];
69+
>extentMixed : Symbol(extentMixed, Decl(typeInferenceLiteralUnion.ts, 33, 3))
70+
>Primitive : Symbol(Primitive, Decl(typeInferenceLiteralUnion.ts, 0, 0))
71+
>NumCoercible : Symbol(NumCoercible, Decl(typeInferenceLiteralUnion.ts, 11, 1))
72+
>Primitive : Symbol(Primitive, Decl(typeInferenceLiteralUnion.ts, 0, 0))
73+
>NumCoercible : Symbol(NumCoercible, Decl(typeInferenceLiteralUnion.ts, 11, 1))
74+
75+
extentMixed = extent([new NumCoercible(10), 13, '12', true]);
76+
>extentMixed : Symbol(extentMixed, Decl(typeInferenceLiteralUnion.ts, 33, 3))
77+
>extent : Symbol(extent, Decl(typeInferenceLiteralUnion.ts, 23, 1))
78+
>NumCoercible : Symbol(NumCoercible, Decl(typeInferenceLiteralUnion.ts, 11, 1))
79+
Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
=== tests/cases/compiler/typeInferenceLiteralUnion.ts ===
2+
// Repro from #10901
3+
/**
4+
* Administrivia: JavaScript primitive types and Date
5+
*/
6+
export type Primitive = number | string | boolean | Date;
7+
>Primitive : Primitive
8+
>Date : Date
9+
10+
/**
11+
* Administrivia: anything with a valueOf(): number method is comparable, so we allow it in numeric operations
12+
*/
13+
interface Numeric {
14+
>Numeric : Numeric
15+
16+
valueOf(): number;
17+
>valueOf : () => number
18+
}
19+
20+
// Not very useful, but meets Numeric
21+
class NumCoercible {
22+
>NumCoercible : NumCoercible
23+
24+
public a: number;
25+
>a : number
26+
27+
constructor(a: number) {
28+
>a : number
29+
30+
this.a = a;
31+
>this.a = a : number
32+
>this.a : number
33+
>this : this
34+
>a : number
35+
>a : number
36+
}
37+
public valueOf() {
38+
>valueOf : () => number
39+
40+
return this.a;
41+
>this.a : number
42+
>this : this
43+
>a : number
44+
}
45+
}
46+
47+
/**
48+
* Return the min and max simultaneously.
49+
*/
50+
export function extent<T extends Numeric>(array: Array<T | Primitive>): [T | Primitive, T | Primitive] | [undefined, undefined] {
51+
>extent : <T extends Numeric>(array: (string | number | boolean | Date | T)[]) => [string | number | boolean | Date | T, string | number | boolean | Date | T] | [undefined, undefined]
52+
>T : T
53+
>Numeric : Numeric
54+
>array : (string | number | boolean | Date | T)[]
55+
>Array : T[]
56+
>T : T
57+
>Primitive : Primitive
58+
>T : T
59+
>Primitive : Primitive
60+
>T : T
61+
>Primitive : Primitive
62+
63+
return [undefined, undefined];
64+
>[undefined, undefined] : [undefined, undefined]
65+
>undefined : undefined
66+
>undefined : undefined
67+
}
68+
69+
70+
let extentMixed: [Primitive | NumCoercible, Primitive | NumCoercible] | [undefined, undefined];
71+
>extentMixed : [undefined, undefined] | [string | number | boolean | Date | NumCoercible, string | number | boolean | Date | NumCoercible]
72+
>Primitive : Primitive
73+
>NumCoercible : NumCoercible
74+
>Primitive : Primitive
75+
>NumCoercible : NumCoercible
76+
77+
extentMixed = extent([new NumCoercible(10), 13, '12', true]);
78+
>extentMixed = extent([new NumCoercible(10), 13, '12', true]) : [undefined, undefined] | [string | number | boolean | Date | NumCoercible, string | number | boolean | Date | NumCoercible]
79+
>extentMixed : [undefined, undefined] | [string | number | boolean | Date | NumCoercible, string | number | boolean | Date | NumCoercible]
80+
>extent([new NumCoercible(10), 13, '12', true]) : [undefined, undefined] | [string | number | boolean | Date | NumCoercible, string | number | boolean | Date | NumCoercible]
81+
>extent : <T extends Numeric>(array: (string | number | boolean | Date | T)[]) => [string | number | boolean | Date | T, string | number | boolean | Date | T] | [undefined, undefined]
82+
>[new NumCoercible(10), 13, '12', true] : (true | NumCoercible | 13 | "12")[]
83+
>new NumCoercible(10) : NumCoercible
84+
>NumCoercible : typeof NumCoercible
85+
>10 : 10
86+
>13 : 13
87+
>'12' : "12"
88+
>true : true
89+

tests/baselines/reference/unionTypeInference.errors.txt

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,7 @@
11
tests/cases/conformance/types/typeRelationships/typeInference/unionTypeInference.ts(9,15): error TS2345: Argument of type '2' is not assignable to parameter of type 'string | 1'.
2-
tests/cases/conformance/types/typeRelationships/typeInference/unionTypeInference.ts(13,15): error TS2345: Argument of type 'number | "hello"' is not assignable to parameter of type 'string | 1'.
3-
Type 'number' is not assignable to type 'string | 1'.
42

53

6-
==== tests/cases/conformance/types/typeRelationships/typeInference/unionTypeInference.ts (2 errors) ====
4+
==== tests/cases/conformance/types/typeRelationships/typeInference/unionTypeInference.ts (1 errors) ====
75
// Verify that inferences made *to* a type parameter in a union type are secondary
86
// to inferences made directly to that type parameter
97

@@ -19,9 +17,6 @@ tests/cases/conformance/types/typeRelationships/typeInference/unionTypeInference
1917
var a2 = f(1, "hello");
2018
var a3: number;
2119
var a3 = f(1, a1 || "hello");
22-
~~~~~~~~~~~~~
23-
!!! error TS2345: Argument of type 'number | "hello"' is not assignable to parameter of type 'string | 1'.
24-
!!! error TS2345: Type 'number' is not assignable to type 'string | 1'.
2520
var a4: any;
2621
var a4 = f(undefined, "abc");
2722

0 commit comments

Comments
 (0)