From 59be264be521e154c4a97fa1d5365083c1f00c19 Mon Sep 17 00:00:00 2001 From: Jason Freeman Date: Fri, 10 Jul 2015 18:16:51 -0700 Subject: [PATCH 1/2] Take the apparent type of the source in type argument inference --- src/compiler/checker.ts | 47 ++++++++++++++++++++++------------------- 1 file changed, 25 insertions(+), 22 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index dd5e42e0f4c..ae44585fc5b 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -5508,30 +5508,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--; } } From 72ef479ddd98731f3423f2acfd0db83103317148 Mon Sep 17 00:00:00 2001 From: Jason Freeman Date: Fri, 10 Jul 2015 18:16:59 -0700 Subject: [PATCH 2/2] Add tests --- .../typeArgumentInferenceApparentType1.js | 12 ++++++++ ...typeArgumentInferenceApparentType1.symbols | 16 +++++++++++ .../typeArgumentInferenceApparentType1.types | 18 ++++++++++++ .../typeArgumentInferenceApparentType2.js | 17 +++++++++++ ...typeArgumentInferenceApparentType2.symbols | 27 ++++++++++++++++++ .../typeArgumentInferenceApparentType2.types | 28 +++++++++++++++++++ .../typeArgumentInferenceApparentType1.ts | 6 ++++ .../typeArgumentInferenceApparentType2.ts | 8 ++++++ 8 files changed, 132 insertions(+) create mode 100644 tests/baselines/reference/typeArgumentInferenceApparentType1.js create mode 100644 tests/baselines/reference/typeArgumentInferenceApparentType1.symbols create mode 100644 tests/baselines/reference/typeArgumentInferenceApparentType1.types create mode 100644 tests/baselines/reference/typeArgumentInferenceApparentType2.js create mode 100644 tests/baselines/reference/typeArgumentInferenceApparentType2.symbols create mode 100644 tests/baselines/reference/typeArgumentInferenceApparentType2.types create mode 100644 tests/cases/compiler/typeArgumentInferenceApparentType1.ts create mode 100644 tests/cases/compiler/typeArgumentInferenceApparentType2.ts diff --git a/tests/baselines/reference/typeArgumentInferenceApparentType1.js b/tests/baselines/reference/typeArgumentInferenceApparentType1.js new file mode 100644 index 00000000000..7a4f1ea19f5 --- /dev/null +++ b/tests/baselines/reference/typeArgumentInferenceApparentType1.js @@ -0,0 +1,12 @@ +//// [typeArgumentInferenceApparentType1.ts] +function method(iterable: Iterable): T { + return; +} + +var res: string = method("test"); + +//// [typeArgumentInferenceApparentType1.js] +function method(iterable) { + return; +} +var res = method("test"); diff --git a/tests/baselines/reference/typeArgumentInferenceApparentType1.symbols b/tests/baselines/reference/typeArgumentInferenceApparentType1.symbols new file mode 100644 index 00000000000..abcb8fdfc68 --- /dev/null +++ b/tests/baselines/reference/typeArgumentInferenceApparentType1.symbols @@ -0,0 +1,16 @@ +=== tests/cases/compiler/typeArgumentInferenceApparentType1.ts === +function method(iterable: Iterable): 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)) + diff --git a/tests/baselines/reference/typeArgumentInferenceApparentType1.types b/tests/baselines/reference/typeArgumentInferenceApparentType1.types new file mode 100644 index 00000000000..29fd1aeca18 --- /dev/null +++ b/tests/baselines/reference/typeArgumentInferenceApparentType1.types @@ -0,0 +1,18 @@ +=== tests/cases/compiler/typeArgumentInferenceApparentType1.ts === +function method(iterable: Iterable): T { +>method : (iterable: Iterable) => T +>T : T +>iterable : Iterable +>Iterable : Iterable +>T : T +>T : T + + return; +} + +var res: string = method("test"); +>res : string +>method("test") : string +>method : (iterable: Iterable) => T +>"test" : string + diff --git a/tests/baselines/reference/typeArgumentInferenceApparentType2.js b/tests/baselines/reference/typeArgumentInferenceApparentType2.js new file mode 100644 index 00000000000..cf9f3bca00e --- /dev/null +++ b/tests/baselines/reference/typeArgumentInferenceApparentType2.js @@ -0,0 +1,17 @@ +//// [typeArgumentInferenceApparentType2.ts] +function method(iterable: Iterable): T { + function inner>() { + var u: U; + var res: T = method(u); + } + return; +} + +//// [typeArgumentInferenceApparentType2.js] +function method(iterable) { + function inner() { + var u; + var res = method(u); + } + return; +} diff --git a/tests/baselines/reference/typeArgumentInferenceApparentType2.symbols b/tests/baselines/reference/typeArgumentInferenceApparentType2.symbols new file mode 100644 index 00000000000..86cf8e7cdcd --- /dev/null +++ b/tests/baselines/reference/typeArgumentInferenceApparentType2.symbols @@ -0,0 +1,27 @@ +=== tests/cases/compiler/typeArgumentInferenceApparentType2.ts === +function method(iterable: Iterable): 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>() { +>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; +} diff --git a/tests/baselines/reference/typeArgumentInferenceApparentType2.types b/tests/baselines/reference/typeArgumentInferenceApparentType2.types new file mode 100644 index 00000000000..6a0e6ae6454 --- /dev/null +++ b/tests/baselines/reference/typeArgumentInferenceApparentType2.types @@ -0,0 +1,28 @@ +=== tests/cases/compiler/typeArgumentInferenceApparentType2.ts === +function method(iterable: Iterable): T { +>method : (iterable: Iterable) => T +>T : T +>iterable : Iterable +>Iterable : Iterable +>T : T +>T : T + + function inner>() { +>inner : >() => void +>U : U +>Iterable : Iterable +>T : T + + var u: U; +>u : U +>U : U + + var res: T = method(u); +>res : T +>T : T +>method(u) : T +>method : (iterable: Iterable) => T +>u : U + } + return; +} diff --git a/tests/cases/compiler/typeArgumentInferenceApparentType1.ts b/tests/cases/compiler/typeArgumentInferenceApparentType1.ts new file mode 100644 index 00000000000..4cc4a0dd4e5 --- /dev/null +++ b/tests/cases/compiler/typeArgumentInferenceApparentType1.ts @@ -0,0 +1,6 @@ +//@target: ES6 +function method(iterable: Iterable): T { + return; +} + +var res: string = method("test"); \ No newline at end of file diff --git a/tests/cases/compiler/typeArgumentInferenceApparentType2.ts b/tests/cases/compiler/typeArgumentInferenceApparentType2.ts new file mode 100644 index 00000000000..88ae4df8c4c --- /dev/null +++ b/tests/cases/compiler/typeArgumentInferenceApparentType2.ts @@ -0,0 +1,8 @@ +//@target: ES6 +function method(iterable: Iterable): T { + function inner>() { + var u: U; + var res: T = method(u); + } + return; +} \ No newline at end of file