Merge pull request #3822 from Microsoft/typeArgumentInferenceApparentType

Take the apparent type of the source during type argument inference
This commit is contained in:
Jason Freeman 2015-07-14 14:17:17 -07:00
commit f344ec10c4
9 changed files with 157 additions and 22 deletions

View File

@ -5538,30 +5538,33 @@ namespace ts {
inferFromTypes(sourceType, target);
}
}
else if (source.flags & TypeFlags.ObjectType && (target.flags & (TypeFlags.Reference | TypeFlags.Tuple) ||
(target.flags & TypeFlags.Anonymous) && target.symbol && target.symbol.flags & (SymbolFlags.Method | SymbolFlags.TypeLiteral | SymbolFlags.Class))) {
// If source is an object type, and target is a type reference, a tuple type, the type of a method, or a type literal, infer from members
if (isInProcess(source, target)) {
return;
}
if (isDeeplyNestedGeneric(source, sourceStack, depth) && isDeeplyNestedGeneric(target, targetStack, depth)) {
return;
}
else {
source = getApparentType(source);
if (source.flags & TypeFlags.ObjectType && (target.flags & (TypeFlags.Reference | TypeFlags.Tuple) ||
(target.flags & TypeFlags.Anonymous) && target.symbol && target.symbol.flags & (SymbolFlags.Method | SymbolFlags.TypeLiteral | SymbolFlags.Class))) {
// If source is an object type, and target is a type reference, a tuple type, the type of a method, or a type literal, infer from members
if (isInProcess(source, target)) {
return;
}
if (isDeeplyNestedGeneric(source, sourceStack, depth) && isDeeplyNestedGeneric(target, targetStack, depth)) {
return;
}
if (depth === 0) {
sourceStack = [];
targetStack = [];
if (depth === 0) {
sourceStack = [];
targetStack = [];
}
sourceStack[depth] = source;
targetStack[depth] = target;
depth++;
inferFromProperties(source, target);
inferFromSignatures(source, target, SignatureKind.Call);
inferFromSignatures(source, target, SignatureKind.Construct);
inferFromIndexTypes(source, target, IndexKind.String, IndexKind.String);
inferFromIndexTypes(source, target, IndexKind.Number, IndexKind.Number);
inferFromIndexTypes(source, target, IndexKind.String, IndexKind.Number);
depth--;
}
sourceStack[depth] = source;
targetStack[depth] = target;
depth++;
inferFromProperties(source, target);
inferFromSignatures(source, target, SignatureKind.Call);
inferFromSignatures(source, target, SignatureKind.Construct);
inferFromIndexTypes(source, target, IndexKind.String, IndexKind.String);
inferFromIndexTypes(source, target, IndexKind.Number, IndexKind.Number);
inferFromIndexTypes(source, target, IndexKind.String, IndexKind.Number);
depth--;
}
}

View File

@ -0,0 +1,12 @@
//// [typeArgumentInferenceApparentType1.ts]
function method<T>(iterable: Iterable<T>): T {
return;
}
var res: string = method("test");
//// [typeArgumentInferenceApparentType1.js]
function method(iterable) {
return;
}
var res = method("test");

View File

@ -0,0 +1,16 @@
=== tests/cases/compiler/typeArgumentInferenceApparentType1.ts ===
function method<T>(iterable: Iterable<T>): T {
>method : Symbol(method, Decl(typeArgumentInferenceApparentType1.ts, 0, 0))
>T : Symbol(T, Decl(typeArgumentInferenceApparentType1.ts, 0, 16))
>iterable : Symbol(iterable, Decl(typeArgumentInferenceApparentType1.ts, 0, 19))
>Iterable : Symbol(Iterable, Decl(lib.d.ts, 1681, 1))
>T : Symbol(T, Decl(typeArgumentInferenceApparentType1.ts, 0, 16))
>T : Symbol(T, Decl(typeArgumentInferenceApparentType1.ts, 0, 16))
return;
}
var res: string = method("test");
>res : Symbol(res, Decl(typeArgumentInferenceApparentType1.ts, 4, 3))
>method : Symbol(method, Decl(typeArgumentInferenceApparentType1.ts, 0, 0))

View File

@ -0,0 +1,18 @@
=== tests/cases/compiler/typeArgumentInferenceApparentType1.ts ===
function method<T>(iterable: Iterable<T>): T {
>method : <T>(iterable: Iterable<T>) => T
>T : T
>iterable : Iterable<T>
>Iterable : Iterable<T>
>T : T
>T : T
return;
}
var res: string = method("test");
>res : string
>method("test") : string
>method : <T>(iterable: Iterable<T>) => T
>"test" : string

View File

@ -0,0 +1,17 @@
//// [typeArgumentInferenceApparentType2.ts]
function method<T>(iterable: Iterable<T>): T {
function inner<U extends Iterable<T>>() {
var u: U;
var res: T = method(u);
}
return;
}
//// [typeArgumentInferenceApparentType2.js]
function method(iterable) {
function inner() {
var u;
var res = method(u);
}
return;
}

View File

@ -0,0 +1,27 @@
=== tests/cases/compiler/typeArgumentInferenceApparentType2.ts ===
function method<T>(iterable: Iterable<T>): T {
>method : Symbol(method, Decl(typeArgumentInferenceApparentType2.ts, 0, 0))
>T : Symbol(T, Decl(typeArgumentInferenceApparentType2.ts, 0, 16))
>iterable : Symbol(iterable, Decl(typeArgumentInferenceApparentType2.ts, 0, 19))
>Iterable : Symbol(Iterable, Decl(lib.d.ts, 1681, 1))
>T : Symbol(T, Decl(typeArgumentInferenceApparentType2.ts, 0, 16))
>T : Symbol(T, Decl(typeArgumentInferenceApparentType2.ts, 0, 16))
function inner<U extends Iterable<T>>() {
>inner : Symbol(inner, Decl(typeArgumentInferenceApparentType2.ts, 0, 46))
>U : Symbol(U, Decl(typeArgumentInferenceApparentType2.ts, 1, 19))
>Iterable : Symbol(Iterable, Decl(lib.d.ts, 1681, 1))
>T : Symbol(T, Decl(typeArgumentInferenceApparentType2.ts, 0, 16))
var u: U;
>u : Symbol(u, Decl(typeArgumentInferenceApparentType2.ts, 2, 11))
>U : Symbol(U, Decl(typeArgumentInferenceApparentType2.ts, 1, 19))
var res: T = method(u);
>res : Symbol(res, Decl(typeArgumentInferenceApparentType2.ts, 3, 11))
>T : Symbol(T, Decl(typeArgumentInferenceApparentType2.ts, 0, 16))
>method : Symbol(method, Decl(typeArgumentInferenceApparentType2.ts, 0, 0))
>u : Symbol(u, Decl(typeArgumentInferenceApparentType2.ts, 2, 11))
}
return;
}

View File

@ -0,0 +1,28 @@
=== tests/cases/compiler/typeArgumentInferenceApparentType2.ts ===
function method<T>(iterable: Iterable<T>): T {
>method : <T>(iterable: Iterable<T>) => T
>T : T
>iterable : Iterable<T>
>Iterable : Iterable<T>
>T : T
>T : T
function inner<U extends Iterable<T>>() {
>inner : <U extends Iterable<T>>() => void
>U : U
>Iterable : Iterable<T>
>T : T
var u: U;
>u : U
>U : U
var res: T = method(u);
>res : T
>T : T
>method(u) : T
>method : <T>(iterable: Iterable<T>) => T
>u : U
}
return;
}

View File

@ -0,0 +1,6 @@
//@target: ES6
function method<T>(iterable: Iterable<T>): T {
return;
}
var res: string = method("test");

View File

@ -0,0 +1,8 @@
//@target: ES6
function method<T>(iterable: Iterable<T>): T {
function inner<U extends Iterable<T>>() {
var u: U;
var res: T = method(u);
}
return;
}