Merge pull request #5921 from Microsoft/revert-5919-port_union_reduction_to_1.7

Revert "Port union reduction to 1.7"
This commit is contained in:
Vladimir Matveev 2015-12-03 17:19:39 -08:00
commit 564c7b448f
17 changed files with 41 additions and 1167 deletions

View File

@ -43,8 +43,6 @@ namespace ts {
let emptyArray: any[] = [];
let emptySymbols: SymbolTable = {};
let jsxElementClassType: Type = undefined;
let compilerOptions = host.getCompilerOptions();
let languageVersion = compilerOptions.target || ScriptTarget.ES3;
let modulekind = compilerOptions.module ? compilerOptions.module : languageVersion === ScriptTarget.ES6 ? ModuleKind.ES6 : ModuleKind.None;
@ -4940,6 +4938,9 @@ namespace ts {
}
return objectTypeRelatedTo(<ObjectType>source, <ObjectType>target, /*reportErrors*/ false);
}
if (source.flags & TypeFlags.TypeParameter && target.flags & TypeFlags.TypeParameter) {
return typeParameterIdenticalTo(<TypeParameter>source, <TypeParameter>target);
}
if (source.flags & TypeFlags.Union && target.flags & TypeFlags.Union ||
source.flags & TypeFlags.Intersection && target.flags & TypeFlags.Intersection) {
if (result = eachTypeRelatedToSomeType(<UnionOrIntersectionType>source, <UnionOrIntersectionType>target)) {
@ -5070,6 +5071,20 @@ namespace ts {
return result;
}
function typeParameterIdenticalTo(source: TypeParameter, target: TypeParameter): Ternary {
if (source.symbol.name !== target.symbol.name) {
return Ternary.False;
}
// covers case when both type parameters does not have constraint (both equal to noConstraintType)
if (source.constraint === target.constraint) {
return Ternary.True;
}
if (source.constraint === noConstraintType || target.constraint === noConstraintType) {
return Ternary.False;
}
return isIdenticalTo(source.constraint, target.constraint);
}
// Determine if two object types are related by structure. First, check if the result is already available in the global cache.
// Second, check if we have already started a comparison of the given two types in which case we assume the result to be true.
// Third, check if both types are part of deeply nested chains of generic type instantiations and if so assume the types are
@ -5592,20 +5607,27 @@ namespace ts {
return Ternary.False;
}
}
// Check that the two signatures have the same number of type parameters. We might consider
// also checking that any type parameter constraints match, but that would require instantiating
// the constraints with a common set of type arguments to get relatable entities in places where
// type parameters occur in the constraints. The complexity of doing that doesn't seem worthwhile,
// particularly as we're comparing erased versions of the signatures below.
if ((source.typeParameters ? source.typeParameters.length : 0) !== (target.typeParameters ? target.typeParameters.length : 0)) {
let result = Ternary.True;
if (source.typeParameters && target.typeParameters) {
if (source.typeParameters.length !== target.typeParameters.length) {
return Ternary.False;
}
for (let i = 0, len = source.typeParameters.length; i < len; ++i) {
let related = compareTypes(source.typeParameters[i], target.typeParameters[i]);
if (!related) {
return Ternary.False;
}
result &= related;
}
}
else if (source.typeParameters || target.typeParameters) {
return Ternary.False;
}
// Spec 1.0 Section 3.8.3 & 3.8.4:
// M and N (the signatures) are instantiated using type Any as the type argument for all type parameters declared by M and N
source = getErasedSignature(source);
target = getErasedSignature(target);
let result = Ternary.True;
const targetLen = target.parameters.length;
let targetLen = target.parameters.length;
for (let i = 0; i < targetLen; i++) {
let s = isRestParameterIndex(source, i) ? getRestTypeOfSignature(source) : getTypeOfSymbol(source.parameters[i]);
let t = isRestParameterIndex(target, i) ? getRestTypeOfSignature(target) : getTypeOfSymbol(target.parameters[i]);
@ -5906,17 +5928,6 @@ namespace ts {
}
function inferFromTypes(source: Type, target: Type) {
if (source.flags & TypeFlags.Union && target.flags & TypeFlags.Union ||
source.flags & TypeFlags.Intersection && target.flags & TypeFlags.Intersection) {
// Source and target are both unions or both intersections. To improve the quality of
// inferences we first reduce the types by removing constituents that are identically
// matched by a constituent in the other type. For example, when inferring from
// 'string | string[]' to 'string | T', we reduce the types to 'string[]' and 'T'.
const reducedSource = reduceUnionOrIntersectionType(<UnionOrIntersectionType>source, <UnionOrIntersectionType>target);
const reducedTarget = reduceUnionOrIntersectionType(<UnionOrIntersectionType>target, <UnionOrIntersectionType>source);
source = reducedSource;
target = reducedTarget;
}
if (target.flags & TypeFlags.TypeParameter) {
// If target is a type parameter, make an inference, unless the source type contains
// the anyFunctionType (the wildcard type that's used to avoid contextually typing functions).
@ -5927,7 +5938,8 @@ namespace ts {
if (source.flags & TypeFlags.ContainsAnyFunctionType) {
return;
}
const typeParameters = context.typeParameters;
let typeParameters = context.typeParameters;
for (let i = 0; i < typeParameters.length; i++) {
if (target === typeParameters[i]) {
let inferences = context.inferences[i];
@ -5999,9 +6011,12 @@ namespace ts {
}
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 (source.flags & TypeFlags.ObjectType && (
target.flags & TypeFlags.Reference && (<TypeReference>target).typeArguments ||
target.flags & 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 with type arguments, a tuple type,
// the type of a method, or a type literal, infer from members
if (isInProcess(source, target)) {
return;
}
@ -6074,41 +6089,6 @@ namespace ts {
}
}
function typeIdenticalToSomeType(source: Type, target: UnionOrIntersectionType): boolean {
for (const t of target.types) {
if (isTypeIdenticalTo(source, t)) {
return true;
}
}
return false;
}
/**
* Return the reduced form of the source type. This type is computed by by removing all source
* constituents that have an identical match in the target type.
*/
function reduceUnionOrIntersectionType(source: UnionOrIntersectionType, target: UnionOrIntersectionType) {
let sourceTypes = source.types;
let sourceIndex = 0;
let modified = false;
while (sourceIndex < sourceTypes.length) {
if (typeIdenticalToSomeType(sourceTypes[sourceIndex], target)) {
if (!modified) {
sourceTypes = sourceTypes.slice(0);
modified = true;
}
sourceTypes.splice(sourceIndex, 1);
}
else {
sourceIndex++;
}
}
if (modified) {
return source.flags & TypeFlags.Union ? getUnionType(sourceTypes, /*noSubtypeReduction*/ true) : getIntersectionType(sourceTypes);
}
return source;
}
function getInferenceCandidates(context: InferenceContext, index: number): Type[] {
let inferences = context.inferences[index];
return inferences.primary || inferences.secondary || emptyArray;
@ -7882,6 +7862,7 @@ namespace ts {
return prop || unknownSymbol;
}
let jsxElementClassType: Type = undefined;
function getJsxGlobalElementClassType(): Type {
if (!jsxElementClassType) {
jsxElementClassType = getExportedTypeFromNamespace(JsxNames.JSX, JsxNames.ElementClass);

View File

@ -1,32 +0,0 @@
//// [genericSignatureIdentity.ts]
// This test is here to remind us of our current limits of type identity checking.
// Ideally all of the below declarations would be considered different (and thus errors)
// but they aren't because we erase type parameters to type any and don't check that
// constraints are identical.
var x: {
<T extends Date>(x: T): T;
};
var x: {
<T extends number>(x: T): T;
};
var x: {
<T>(x: T): T;
};
var x: {
<T>(x: any): any;
};
//// [genericSignatureIdentity.js]
// This test is here to remind us of our current limits of type identity checking.
// Ideally all of the below declarations would be considered different (and thus errors)
// but they aren't because we erase type parameters to type any and don't check that
// constraints are identical.
var x;
var x;
var x;
var x;

View File

@ -1,49 +0,0 @@
=== tests/cases/compiler/genericSignatureIdentity.ts ===
// This test is here to remind us of our current limits of type identity checking.
// Ideally all of the below declarations would be considered different (and thus errors)
// but they aren't because we erase type parameters to type any and don't check that
// constraints are identical.
var x: {
>x : Symbol(x, Decl(genericSignatureIdentity.ts, 5, 3), Decl(genericSignatureIdentity.ts, 9, 3), Decl(genericSignatureIdentity.ts, 13, 3), Decl(genericSignatureIdentity.ts, 17, 3))
<T extends Date>(x: T): T;
>T : Symbol(T, Decl(genericSignatureIdentity.ts, 6, 5))
>Date : Symbol(Date, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --))
>x : Symbol(x, Decl(genericSignatureIdentity.ts, 6, 21))
>T : Symbol(T, Decl(genericSignatureIdentity.ts, 6, 5))
>T : Symbol(T, Decl(genericSignatureIdentity.ts, 6, 5))
};
var x: {
>x : Symbol(x, Decl(genericSignatureIdentity.ts, 5, 3), Decl(genericSignatureIdentity.ts, 9, 3), Decl(genericSignatureIdentity.ts, 13, 3), Decl(genericSignatureIdentity.ts, 17, 3))
<T extends number>(x: T): T;
>T : Symbol(T, Decl(genericSignatureIdentity.ts, 10, 5))
>x : Symbol(x, Decl(genericSignatureIdentity.ts, 10, 23))
>T : Symbol(T, Decl(genericSignatureIdentity.ts, 10, 5))
>T : Symbol(T, Decl(genericSignatureIdentity.ts, 10, 5))
};
var x: {
>x : Symbol(x, Decl(genericSignatureIdentity.ts, 5, 3), Decl(genericSignatureIdentity.ts, 9, 3), Decl(genericSignatureIdentity.ts, 13, 3), Decl(genericSignatureIdentity.ts, 17, 3))
<T>(x: T): T;
>T : Symbol(T, Decl(genericSignatureIdentity.ts, 14, 5))
>x : Symbol(x, Decl(genericSignatureIdentity.ts, 14, 8))
>T : Symbol(T, Decl(genericSignatureIdentity.ts, 14, 5))
>T : Symbol(T, Decl(genericSignatureIdentity.ts, 14, 5))
};
var x: {
>x : Symbol(x, Decl(genericSignatureIdentity.ts, 5, 3), Decl(genericSignatureIdentity.ts, 9, 3), Decl(genericSignatureIdentity.ts, 13, 3), Decl(genericSignatureIdentity.ts, 17, 3))
<T>(x: any): any;
>T : Symbol(T, Decl(genericSignatureIdentity.ts, 18, 5))
>x : Symbol(x, Decl(genericSignatureIdentity.ts, 18, 8))
};

View File

@ -1,49 +0,0 @@
=== tests/cases/compiler/genericSignatureIdentity.ts ===
// This test is here to remind us of our current limits of type identity checking.
// Ideally all of the below declarations would be considered different (and thus errors)
// but they aren't because we erase type parameters to type any and don't check that
// constraints are identical.
var x: {
>x : <T extends Date>(x: T) => T
<T extends Date>(x: T): T;
>T : T
>Date : Date
>x : T
>T : T
>T : T
};
var x: {
>x : <T extends Date>(x: T) => T
<T extends number>(x: T): T;
>T : T
>x : T
>T : T
>T : T
};
var x: {
>x : <T extends Date>(x: T) => T
<T>(x: T): T;
>T : T
>x : T
>T : T
>T : T
};
var x: {
>x : <T extends Date>(x: T) => T
<T>(x: any): any;
>T : T
>x : any
};

View File

@ -1,113 +0,0 @@
//// [unionAndIntersectionInference1.ts]
// Repro from #2264
interface Y { 'i am a very certain type': Y }
var y: Y = <Y>undefined;
function destructure<a, r>(
something: a | Y,
haveValue: (value: a) => r,
haveY: (value: Y) => r
): r {
return something === y ? haveY(y) : haveValue(<a>something);
}
var value = Math.random() > 0.5 ? 'hey!' : <Y>undefined;
var result = destructure(value, text => 'string', y => 'other one'); // text: string, y: Y
// Repro from #4212
function isVoid<a>(value: void | a): value is void {
return undefined;
}
function isNonVoid<a>(value: void | a) : value is a {
return undefined;
}
function foo1<a>(value: void|a): void {
if (isVoid(value)) {
value; // value is void
} else {
value; // value is a
}
}
function baz1<a>(value: void|a): void {
if (isNonVoid(value)) {
value; // value is a
} else {
value; // value is void
}
}
// Repro from #5417
type Maybe<T> = T | void;
function get<U>(x: U | void): U {
return null; // just an example
}
let foo: Maybe<string>;
get(foo).toUpperCase(); // Ok
// Repro from #5456
interface Man {
walks: boolean;
}
interface Bear {
roars: boolean;
}
interface Pig {
oinks: boolean;
}
declare function pigify<T>(y: T & Bear): T & Pig;
declare var mbp: Man & Bear;
pigify(mbp).oinks; // OK, mbp is treated as Pig
pigify(mbp).walks; // Ok, mbp is treated as Man
//// [unionAndIntersectionInference1.js]
// Repro from #2264
var y = undefined;
function destructure(something, haveValue, haveY) {
return something === y ? haveY(y) : haveValue(something);
}
var value = Math.random() > 0.5 ? 'hey!' : undefined;
var result = destructure(value, function (text) { return 'string'; }, function (y) { return 'other one'; }); // text: string, y: Y
// Repro from #4212
function isVoid(value) {
return undefined;
}
function isNonVoid(value) {
return undefined;
}
function foo1(value) {
if (isVoid(value)) {
value; // value is void
}
else {
value; // value is a
}
}
function baz1(value) {
if (isNonVoid(value)) {
value; // value is a
}
else {
value; // value is void
}
}
function get(x) {
return null; // just an example
}
var foo;
get(foo).toUpperCase(); // Ok
pigify(mbp).oinks; // OK, mbp is treated as Pig
pigify(mbp).walks; // Ok, mbp is treated as Man

View File

@ -1,202 +0,0 @@
=== tests/cases/conformance/types/typeRelationships/typeInference/unionAndIntersectionInference1.ts ===
// Repro from #2264
interface Y { 'i am a very certain type': Y }
>Y : Symbol(Y, Decl(unionAndIntersectionInference1.ts, 0, 0))
>Y : Symbol(Y, Decl(unionAndIntersectionInference1.ts, 0, 0))
var y: Y = <Y>undefined;
>y : Symbol(y, Decl(unionAndIntersectionInference1.ts, 3, 3))
>Y : Symbol(Y, Decl(unionAndIntersectionInference1.ts, 0, 0))
>Y : Symbol(Y, Decl(unionAndIntersectionInference1.ts, 0, 0))
>undefined : Symbol(undefined)
function destructure<a, r>(
>destructure : Symbol(destructure, Decl(unionAndIntersectionInference1.ts, 3, 24))
>a : Symbol(a, Decl(unionAndIntersectionInference1.ts, 4, 21))
>r : Symbol(r, Decl(unionAndIntersectionInference1.ts, 4, 23))
something: a | Y,
>something : Symbol(something, Decl(unionAndIntersectionInference1.ts, 4, 27))
>a : Symbol(a, Decl(unionAndIntersectionInference1.ts, 4, 21))
>Y : Symbol(Y, Decl(unionAndIntersectionInference1.ts, 0, 0))
haveValue: (value: a) => r,
>haveValue : Symbol(haveValue, Decl(unionAndIntersectionInference1.ts, 5, 21))
>value : Symbol(value, Decl(unionAndIntersectionInference1.ts, 6, 16))
>a : Symbol(a, Decl(unionAndIntersectionInference1.ts, 4, 21))
>r : Symbol(r, Decl(unionAndIntersectionInference1.ts, 4, 23))
haveY: (value: Y) => r
>haveY : Symbol(haveY, Decl(unionAndIntersectionInference1.ts, 6, 31))
>value : Symbol(value, Decl(unionAndIntersectionInference1.ts, 7, 12))
>Y : Symbol(Y, Decl(unionAndIntersectionInference1.ts, 0, 0))
>r : Symbol(r, Decl(unionAndIntersectionInference1.ts, 4, 23))
): r {
>r : Symbol(r, Decl(unionAndIntersectionInference1.ts, 4, 23))
return something === y ? haveY(y) : haveValue(<a>something);
>something : Symbol(something, Decl(unionAndIntersectionInference1.ts, 4, 27))
>y : Symbol(y, Decl(unionAndIntersectionInference1.ts, 3, 3))
>haveY : Symbol(haveY, Decl(unionAndIntersectionInference1.ts, 6, 31))
>y : Symbol(y, Decl(unionAndIntersectionInference1.ts, 3, 3))
>haveValue : Symbol(haveValue, Decl(unionAndIntersectionInference1.ts, 5, 21))
>a : Symbol(a, Decl(unionAndIntersectionInference1.ts, 4, 21))
>something : Symbol(something, Decl(unionAndIntersectionInference1.ts, 4, 27))
}
var value = Math.random() > 0.5 ? 'hey!' : <Y>undefined;
>value : Symbol(value, Decl(unionAndIntersectionInference1.ts, 12, 3))
>Math.random : Symbol(Math.random, Decl(lib.d.ts, --, --))
>Math : Symbol(Math, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --))
>random : Symbol(Math.random, Decl(lib.d.ts, --, --))
>Y : Symbol(Y, Decl(unionAndIntersectionInference1.ts, 0, 0))
>undefined : Symbol(undefined)
var result = destructure(value, text => 'string', y => 'other one'); // text: string, y: Y
>result : Symbol(result, Decl(unionAndIntersectionInference1.ts, 14, 3))
>destructure : Symbol(destructure, Decl(unionAndIntersectionInference1.ts, 3, 24))
>value : Symbol(value, Decl(unionAndIntersectionInference1.ts, 12, 3))
>text : Symbol(text, Decl(unionAndIntersectionInference1.ts, 14, 31))
>y : Symbol(y, Decl(unionAndIntersectionInference1.ts, 14, 49))
// Repro from #4212
function isVoid<a>(value: void | a): value is void {
>isVoid : Symbol(isVoid, Decl(unionAndIntersectionInference1.ts, 14, 68))
>a : Symbol(a, Decl(unionAndIntersectionInference1.ts, 18, 16))
>value : Symbol(value, Decl(unionAndIntersectionInference1.ts, 18, 19))
>a : Symbol(a, Decl(unionAndIntersectionInference1.ts, 18, 16))
>value : Symbol(value, Decl(unionAndIntersectionInference1.ts, 18, 19))
return undefined;
>undefined : Symbol(undefined)
}
function isNonVoid<a>(value: void | a) : value is a {
>isNonVoid : Symbol(isNonVoid, Decl(unionAndIntersectionInference1.ts, 20, 1))
>a : Symbol(a, Decl(unionAndIntersectionInference1.ts, 22, 19))
>value : Symbol(value, Decl(unionAndIntersectionInference1.ts, 22, 22))
>a : Symbol(a, Decl(unionAndIntersectionInference1.ts, 22, 19))
>value : Symbol(value, Decl(unionAndIntersectionInference1.ts, 22, 22))
>a : Symbol(a, Decl(unionAndIntersectionInference1.ts, 22, 19))
return undefined;
>undefined : Symbol(undefined)
}
function foo1<a>(value: void|a): void {
>foo1 : Symbol(foo1, Decl(unionAndIntersectionInference1.ts, 24, 1))
>a : Symbol(a, Decl(unionAndIntersectionInference1.ts, 26, 14))
>value : Symbol(value, Decl(unionAndIntersectionInference1.ts, 26, 17))
>a : Symbol(a, Decl(unionAndIntersectionInference1.ts, 26, 14))
if (isVoid(value)) {
>isVoid : Symbol(isVoid, Decl(unionAndIntersectionInference1.ts, 14, 68))
>value : Symbol(value, Decl(unionAndIntersectionInference1.ts, 26, 17))
value; // value is void
>value : Symbol(value, Decl(unionAndIntersectionInference1.ts, 26, 17))
} else {
value; // value is a
>value : Symbol(value, Decl(unionAndIntersectionInference1.ts, 26, 17))
}
}
function baz1<a>(value: void|a): void {
>baz1 : Symbol(baz1, Decl(unionAndIntersectionInference1.ts, 32, 1))
>a : Symbol(a, Decl(unionAndIntersectionInference1.ts, 34, 14))
>value : Symbol(value, Decl(unionAndIntersectionInference1.ts, 34, 17))
>a : Symbol(a, Decl(unionAndIntersectionInference1.ts, 34, 14))
if (isNonVoid(value)) {
>isNonVoid : Symbol(isNonVoid, Decl(unionAndIntersectionInference1.ts, 20, 1))
>value : Symbol(value, Decl(unionAndIntersectionInference1.ts, 34, 17))
value; // value is a
>value : Symbol(value, Decl(unionAndIntersectionInference1.ts, 34, 17))
} else {
value; // value is void
>value : Symbol(value, Decl(unionAndIntersectionInference1.ts, 34, 17))
}
}
// Repro from #5417
type Maybe<T> = T | void;
>Maybe : Symbol(Maybe, Decl(unionAndIntersectionInference1.ts, 40, 1))
>T : Symbol(T, Decl(unionAndIntersectionInference1.ts, 44, 11))
>T : Symbol(T, Decl(unionAndIntersectionInference1.ts, 44, 11))
function get<U>(x: U | void): U {
>get : Symbol(get, Decl(unionAndIntersectionInference1.ts, 44, 25))
>U : Symbol(U, Decl(unionAndIntersectionInference1.ts, 46, 13))
>x : Symbol(x, Decl(unionAndIntersectionInference1.ts, 46, 16))
>U : Symbol(U, Decl(unionAndIntersectionInference1.ts, 46, 13))
>U : Symbol(U, Decl(unionAndIntersectionInference1.ts, 46, 13))
return null; // just an example
}
let foo: Maybe<string>;
>foo : Symbol(foo, Decl(unionAndIntersectionInference1.ts, 50, 3))
>Maybe : Symbol(Maybe, Decl(unionAndIntersectionInference1.ts, 40, 1))
get(foo).toUpperCase(); // Ok
>get(foo).toUpperCase : Symbol(String.toUpperCase, Decl(lib.d.ts, --, --))
>get : Symbol(get, Decl(unionAndIntersectionInference1.ts, 44, 25))
>foo : Symbol(foo, Decl(unionAndIntersectionInference1.ts, 50, 3))
>toUpperCase : Symbol(String.toUpperCase, Decl(lib.d.ts, --, --))
// Repro from #5456
interface Man {
>Man : Symbol(Man, Decl(unionAndIntersectionInference1.ts, 51, 23))
walks: boolean;
>walks : Symbol(walks, Decl(unionAndIntersectionInference1.ts, 55, 15))
}
interface Bear {
>Bear : Symbol(Bear, Decl(unionAndIntersectionInference1.ts, 57, 1))
roars: boolean;
>roars : Symbol(roars, Decl(unionAndIntersectionInference1.ts, 59, 16))
}
interface Pig {
>Pig : Symbol(Pig, Decl(unionAndIntersectionInference1.ts, 61, 1))
oinks: boolean;
>oinks : Symbol(oinks, Decl(unionAndIntersectionInference1.ts, 63, 15))
}
declare function pigify<T>(y: T & Bear): T & Pig;
>pigify : Symbol(pigify, Decl(unionAndIntersectionInference1.ts, 65, 1))
>T : Symbol(T, Decl(unionAndIntersectionInference1.ts, 67, 24))
>y : Symbol(y, Decl(unionAndIntersectionInference1.ts, 67, 27))
>T : Symbol(T, Decl(unionAndIntersectionInference1.ts, 67, 24))
>Bear : Symbol(Bear, Decl(unionAndIntersectionInference1.ts, 57, 1))
>T : Symbol(T, Decl(unionAndIntersectionInference1.ts, 67, 24))
>Pig : Symbol(Pig, Decl(unionAndIntersectionInference1.ts, 61, 1))
declare var mbp: Man & Bear;
>mbp : Symbol(mbp, Decl(unionAndIntersectionInference1.ts, 68, 11))
>Man : Symbol(Man, Decl(unionAndIntersectionInference1.ts, 51, 23))
>Bear : Symbol(Bear, Decl(unionAndIntersectionInference1.ts, 57, 1))
pigify(mbp).oinks; // OK, mbp is treated as Pig
>pigify(mbp).oinks : Symbol(Pig.oinks, Decl(unionAndIntersectionInference1.ts, 63, 15))
>pigify : Symbol(pigify, Decl(unionAndIntersectionInference1.ts, 65, 1))
>mbp : Symbol(mbp, Decl(unionAndIntersectionInference1.ts, 68, 11))
>oinks : Symbol(Pig.oinks, Decl(unionAndIntersectionInference1.ts, 63, 15))
pigify(mbp).walks; // Ok, mbp is treated as Man
>pigify(mbp).walks : Symbol(Man.walks, Decl(unionAndIntersectionInference1.ts, 55, 15))
>pigify : Symbol(pigify, Decl(unionAndIntersectionInference1.ts, 65, 1))
>mbp : Symbol(mbp, Decl(unionAndIntersectionInference1.ts, 68, 11))
>walks : Symbol(Man.walks, Decl(unionAndIntersectionInference1.ts, 55, 15))

View File

@ -1,226 +0,0 @@
=== tests/cases/conformance/types/typeRelationships/typeInference/unionAndIntersectionInference1.ts ===
// Repro from #2264
interface Y { 'i am a very certain type': Y }
>Y : Y
>Y : Y
var y: Y = <Y>undefined;
>y : Y
>Y : Y
><Y>undefined : Y
>Y : Y
>undefined : undefined
function destructure<a, r>(
>destructure : <a, r>(something: a | Y, haveValue: (value: a) => r, haveY: (value: Y) => r) => r
>a : a
>r : r
something: a | Y,
>something : a | Y
>a : a
>Y : Y
haveValue: (value: a) => r,
>haveValue : (value: a) => r
>value : a
>a : a
>r : r
haveY: (value: Y) => r
>haveY : (value: Y) => r
>value : Y
>Y : Y
>r : r
): r {
>r : r
return something === y ? haveY(y) : haveValue(<a>something);
>something === y ? haveY(y) : haveValue(<a>something) : r
>something === y : boolean
>something : a | Y
>y : Y
>haveY(y) : r
>haveY : (value: Y) => r
>y : Y
>haveValue(<a>something) : r
>haveValue : (value: a) => r
><a>something : a
>a : a
>something : a | Y
}
var value = Math.random() > 0.5 ? 'hey!' : <Y>undefined;
>value : string | Y
>Math.random() > 0.5 ? 'hey!' : <Y>undefined : string | Y
>Math.random() > 0.5 : boolean
>Math.random() : number
>Math.random : () => number
>Math : Math
>random : () => number
>0.5 : number
>'hey!' : string
><Y>undefined : Y
>Y : Y
>undefined : undefined
var result = destructure(value, text => 'string', y => 'other one'); // text: string, y: Y
>result : string
>destructure(value, text => 'string', y => 'other one') : string
>destructure : <a, r>(something: a | Y, haveValue: (value: a) => r, haveY: (value: Y) => r) => r
>value : string | Y
>text => 'string' : (text: string) => string
>text : string
>'string' : string
>y => 'other one' : (y: Y) => string
>y : Y
>'other one' : string
// Repro from #4212
function isVoid<a>(value: void | a): value is void {
>isVoid : <a>(value: void | a) => value is void
>a : a
>value : void | a
>a : a
>value : any
return undefined;
>undefined : undefined
}
function isNonVoid<a>(value: void | a) : value is a {
>isNonVoid : <a>(value: void | a) => value is a
>a : a
>value : void | a
>a : a
>value : any
>a : a
return undefined;
>undefined : undefined
}
function foo1<a>(value: void|a): void {
>foo1 : <a>(value: void | a) => void
>a : a
>value : void | a
>a : a
if (isVoid(value)) {
>isVoid(value) : boolean
>isVoid : <a>(value: void | a) => value is void
>value : void | a
value; // value is void
>value : void
} else {
value; // value is a
>value : a
}
}
function baz1<a>(value: void|a): void {
>baz1 : <a>(value: void | a) => void
>a : a
>value : void | a
>a : a
if (isNonVoid(value)) {
>isNonVoid(value) : boolean
>isNonVoid : <a>(value: void | a) => value is a
>value : void | a
value; // value is a
>value : a
} else {
value; // value is void
>value : void
}
}
// Repro from #5417
type Maybe<T> = T | void;
>Maybe : T | void
>T : T
>T : T
function get<U>(x: U | void): U {
>get : <U>(x: U | void) => U
>U : U
>x : U | void
>U : U
>U : U
return null; // just an example
>null : null
}
let foo: Maybe<string>;
>foo : string | void
>Maybe : T | void
get(foo).toUpperCase(); // Ok
>get(foo).toUpperCase() : string
>get(foo).toUpperCase : () => string
>get(foo) : string
>get : <U>(x: U | void) => U
>foo : string | void
>toUpperCase : () => string
// Repro from #5456
interface Man {
>Man : Man
walks: boolean;
>walks : boolean
}
interface Bear {
>Bear : Bear
roars: boolean;
>roars : boolean
}
interface Pig {
>Pig : Pig
oinks: boolean;
>oinks : boolean
}
declare function pigify<T>(y: T & Bear): T & Pig;
>pigify : <T>(y: T & Bear) => T & Pig
>T : T
>y : T & Bear
>T : T
>Bear : Bear
>T : T
>Pig : Pig
declare var mbp: Man & Bear;
>mbp : Man & Bear
>Man : Man
>Bear : Bear
pigify(mbp).oinks; // OK, mbp is treated as Pig
>pigify(mbp).oinks : boolean
>pigify(mbp) : Man & Pig
>pigify : <T>(y: T & Bear) => T & Pig
>mbp : Man & Bear
>oinks : boolean
pigify(mbp).walks; // Ok, mbp is treated as Man
>pigify(mbp).walks : boolean
>pigify(mbp) : Man & Pig
>pigify : <T>(y: T & Bear) => T & Pig
>mbp : Man & Bear
>walks : boolean

View File

@ -1,45 +0,0 @@
//// [unionAndIntersectionInference2.ts]
declare function f1<T>(x: T | string): T;
var a1: string;
var b1: string | string[];
var c1: string[] | string;
var d1: string | { name: string };
var e1: number | string | boolean;
f1(a1); // string
f1(b1); // string[]
f1(c1); // string[]
f1(d1); // { name: string }
f1(e1); // number | boolean
declare function f2<T>(x: T & { name: string }): T;
var a2: string & { name: string };
var b2: { name: string } & string[];
var c2: string & { name: string } & number;
var d2: string & { name: string } & number & { name: string };
f2(a2); // string
f2(b2); // string[]
f2(c2); // string & number
f2(d2); // string & number
//// [unionAndIntersectionInference2.js]
var a1;
var b1;
var c1;
var d1;
var e1;
f1(a1); // string
f1(b1); // string[]
f1(c1); // string[]
f1(d1); // { name: string }
f1(e1); // number | boolean
var a2;
var b2;
var c2;
var d2;
f2(a2); // string
f2(b2); // string[]
f2(c2); // string & number
f2(d2); // string & number

View File

@ -1,85 +0,0 @@
=== tests/cases/conformance/types/typeRelationships/typeInference/unionAndIntersectionInference2.ts ===
declare function f1<T>(x: T | string): T;
>f1 : Symbol(f1, Decl(unionAndIntersectionInference2.ts, 0, 0))
>T : Symbol(T, Decl(unionAndIntersectionInference2.ts, 0, 20))
>x : Symbol(x, Decl(unionAndIntersectionInference2.ts, 0, 23))
>T : Symbol(T, Decl(unionAndIntersectionInference2.ts, 0, 20))
>T : Symbol(T, Decl(unionAndIntersectionInference2.ts, 0, 20))
var a1: string;
>a1 : Symbol(a1, Decl(unionAndIntersectionInference2.ts, 2, 3))
var b1: string | string[];
>b1 : Symbol(b1, Decl(unionAndIntersectionInference2.ts, 3, 3))
var c1: string[] | string;
>c1 : Symbol(c1, Decl(unionAndIntersectionInference2.ts, 4, 3))
var d1: string | { name: string };
>d1 : Symbol(d1, Decl(unionAndIntersectionInference2.ts, 5, 3))
>name : Symbol(name, Decl(unionAndIntersectionInference2.ts, 5, 18))
var e1: number | string | boolean;
>e1 : Symbol(e1, Decl(unionAndIntersectionInference2.ts, 6, 3))
f1(a1); // string
>f1 : Symbol(f1, Decl(unionAndIntersectionInference2.ts, 0, 0))
>a1 : Symbol(a1, Decl(unionAndIntersectionInference2.ts, 2, 3))
f1(b1); // string[]
>f1 : Symbol(f1, Decl(unionAndIntersectionInference2.ts, 0, 0))
>b1 : Symbol(b1, Decl(unionAndIntersectionInference2.ts, 3, 3))
f1(c1); // string[]
>f1 : Symbol(f1, Decl(unionAndIntersectionInference2.ts, 0, 0))
>c1 : Symbol(c1, Decl(unionAndIntersectionInference2.ts, 4, 3))
f1(d1); // { name: string }
>f1 : Symbol(f1, Decl(unionAndIntersectionInference2.ts, 0, 0))
>d1 : Symbol(d1, Decl(unionAndIntersectionInference2.ts, 5, 3))
f1(e1); // number | boolean
>f1 : Symbol(f1, Decl(unionAndIntersectionInference2.ts, 0, 0))
>e1 : Symbol(e1, Decl(unionAndIntersectionInference2.ts, 6, 3))
declare function f2<T>(x: T & { name: string }): T;
>f2 : Symbol(f2, Decl(unionAndIntersectionInference2.ts, 11, 7))
>T : Symbol(T, Decl(unionAndIntersectionInference2.ts, 13, 20))
>x : Symbol(x, Decl(unionAndIntersectionInference2.ts, 13, 23))
>T : Symbol(T, Decl(unionAndIntersectionInference2.ts, 13, 20))
>name : Symbol(name, Decl(unionAndIntersectionInference2.ts, 13, 31))
>T : Symbol(T, Decl(unionAndIntersectionInference2.ts, 13, 20))
var a2: string & { name: string };
>a2 : Symbol(a2, Decl(unionAndIntersectionInference2.ts, 15, 3))
>name : Symbol(name, Decl(unionAndIntersectionInference2.ts, 15, 18))
var b2: { name: string } & string[];
>b2 : Symbol(b2, Decl(unionAndIntersectionInference2.ts, 16, 3))
>name : Symbol(name, Decl(unionAndIntersectionInference2.ts, 16, 9))
var c2: string & { name: string } & number;
>c2 : Symbol(c2, Decl(unionAndIntersectionInference2.ts, 17, 3))
>name : Symbol(name, Decl(unionAndIntersectionInference2.ts, 17, 18))
var d2: string & { name: string } & number & { name: string };
>d2 : Symbol(d2, Decl(unionAndIntersectionInference2.ts, 18, 3))
>name : Symbol(name, Decl(unionAndIntersectionInference2.ts, 18, 18))
>name : Symbol(name, Decl(unionAndIntersectionInference2.ts, 18, 46))
f2(a2); // string
>f2 : Symbol(f2, Decl(unionAndIntersectionInference2.ts, 11, 7))
>a2 : Symbol(a2, Decl(unionAndIntersectionInference2.ts, 15, 3))
f2(b2); // string[]
>f2 : Symbol(f2, Decl(unionAndIntersectionInference2.ts, 11, 7))
>b2 : Symbol(b2, Decl(unionAndIntersectionInference2.ts, 16, 3))
f2(c2); // string & number
>f2 : Symbol(f2, Decl(unionAndIntersectionInference2.ts, 11, 7))
>c2 : Symbol(c2, Decl(unionAndIntersectionInference2.ts, 17, 3))
f2(d2); // string & number
>f2 : Symbol(f2, Decl(unionAndIntersectionInference2.ts, 11, 7))
>d2 : Symbol(d2, Decl(unionAndIntersectionInference2.ts, 18, 3))

View File

@ -1,94 +0,0 @@
=== tests/cases/conformance/types/typeRelationships/typeInference/unionAndIntersectionInference2.ts ===
declare function f1<T>(x: T | string): T;
>f1 : <T>(x: T | string) => T
>T : T
>x : T | string
>T : T
>T : T
var a1: string;
>a1 : string
var b1: string | string[];
>b1 : string | string[]
var c1: string[] | string;
>c1 : string[] | string
var d1: string | { name: string };
>d1 : string | { name: string; }
>name : string
var e1: number | string | boolean;
>e1 : number | string | boolean
f1(a1); // string
>f1(a1) : string
>f1 : <T>(x: T | string) => T
>a1 : string
f1(b1); // string[]
>f1(b1) : string[]
>f1 : <T>(x: T | string) => T
>b1 : string | string[]
f1(c1); // string[]
>f1(c1) : string[]
>f1 : <T>(x: T | string) => T
>c1 : string[] | string
f1(d1); // { name: string }
>f1(d1) : { name: string; }
>f1 : <T>(x: T | string) => T
>d1 : string | { name: string; }
f1(e1); // number | boolean
>f1(e1) : number | boolean
>f1 : <T>(x: T | string) => T
>e1 : number | string | boolean
declare function f2<T>(x: T & { name: string }): T;
>f2 : <T>(x: T & { name: string; }) => T
>T : T
>x : T & { name: string; }
>T : T
>name : string
>T : T
var a2: string & { name: string };
>a2 : string & { name: string; }
>name : string
var b2: { name: string } & string[];
>b2 : { name: string; } & string[]
>name : string
var c2: string & { name: string } & number;
>c2 : string & { name: string; } & number
>name : string
var d2: string & { name: string } & number & { name: string };
>d2 : string & { name: string; } & number & { name: string; }
>name : string
>name : string
f2(a2); // string
>f2(a2) : string
>f2 : <T>(x: T & { name: string; }) => T
>a2 : string & { name: string; }
f2(b2); // string[]
>f2(b2) : string[]
>f2 : <T>(x: T & { name: string; }) => T
>b2 : { name: string; } & string[]
f2(c2); // string & number
>f2(c2) : string & number
>f2 : <T>(x: T & { name: string; }) => T
>c2 : string & { name: string; } & number
f2(d2); // string & number
>f2(d2) : string & number
>f2 : <T>(x: T & { name: string; }) => T
>d2 : string & { name: string; } & number & { name: string; }

View File

@ -1,17 +0,0 @@
//// [unionTypeParameterInference.ts]
// Regression test for #5861
interface Foo<T> { prop: T; }
declare function lift<U>(value: U | Foo<U>): Foo<U>;
function unlift<U>(value: U | Foo<U>): U {
return lift(value).prop;
}
//// [unionTypeParameterInference.js]
// Regression test for #5861
function unlift(value) {
return lift(value).prop;
}

View File

@ -1,35 +0,0 @@
=== tests/cases/compiler/unionTypeParameterInference.ts ===
// Regression test for #5861
interface Foo<T> { prop: T; }
>Foo : Symbol(Foo, Decl(unionTypeParameterInference.ts, 0, 0))
>T : Symbol(T, Decl(unionTypeParameterInference.ts, 2, 14))
>prop : Symbol(prop, Decl(unionTypeParameterInference.ts, 2, 18))
>T : Symbol(T, Decl(unionTypeParameterInference.ts, 2, 14))
declare function lift<U>(value: U | Foo<U>): Foo<U>;
>lift : Symbol(lift, Decl(unionTypeParameterInference.ts, 2, 29))
>U : Symbol(U, Decl(unionTypeParameterInference.ts, 4, 22))
>value : Symbol(value, Decl(unionTypeParameterInference.ts, 4, 25))
>U : Symbol(U, Decl(unionTypeParameterInference.ts, 4, 22))
>Foo : Symbol(Foo, Decl(unionTypeParameterInference.ts, 0, 0))
>U : Symbol(U, Decl(unionTypeParameterInference.ts, 4, 22))
>Foo : Symbol(Foo, Decl(unionTypeParameterInference.ts, 0, 0))
>U : Symbol(U, Decl(unionTypeParameterInference.ts, 4, 22))
function unlift<U>(value: U | Foo<U>): U {
>unlift : Symbol(unlift, Decl(unionTypeParameterInference.ts, 4, 52))
>U : Symbol(U, Decl(unionTypeParameterInference.ts, 6, 16))
>value : Symbol(value, Decl(unionTypeParameterInference.ts, 6, 19))
>U : Symbol(U, Decl(unionTypeParameterInference.ts, 6, 16))
>Foo : Symbol(Foo, Decl(unionTypeParameterInference.ts, 0, 0))
>U : Symbol(U, Decl(unionTypeParameterInference.ts, 6, 16))
>U : Symbol(U, Decl(unionTypeParameterInference.ts, 6, 16))
return lift(value).prop;
>lift(value).prop : Symbol(Foo.prop, Decl(unionTypeParameterInference.ts, 2, 18))
>lift : Symbol(lift, Decl(unionTypeParameterInference.ts, 2, 29))
>value : Symbol(value, Decl(unionTypeParameterInference.ts, 6, 19))
>prop : Symbol(Foo.prop, Decl(unionTypeParameterInference.ts, 2, 18))
}

View File

@ -1,36 +0,0 @@
=== tests/cases/compiler/unionTypeParameterInference.ts ===
// Regression test for #5861
interface Foo<T> { prop: T; }
>Foo : Foo<T>
>T : T
>prop : T
>T : T
declare function lift<U>(value: U | Foo<U>): Foo<U>;
>lift : <U>(value: U | Foo<U>) => Foo<U>
>U : U
>value : U | Foo<U>
>U : U
>Foo : Foo<T>
>U : U
>Foo : Foo<T>
>U : U
function unlift<U>(value: U | Foo<U>): U {
>unlift : <U>(value: U | Foo<U>) => U
>U : U
>value : U | Foo<U>
>U : U
>Foo : Foo<T>
>U : U
>U : U
return lift(value).prop;
>lift(value).prop : U
>lift(value) : Foo<U>
>lift : <U>(value: U | Foo<U>) => Foo<U>
>value : U | Foo<U>
>prop : U
}

View File

@ -1,20 +0,0 @@
// This test is here to remind us of our current limits of type identity checking.
// Ideally all of the below declarations would be considered different (and thus errors)
// but they aren't because we erase type parameters to type any and don't check that
// constraints are identical.
var x: {
<T extends Date>(x: T): T;
};
var x: {
<T extends number>(x: T): T;
};
var x: {
<T>(x: T): T;
};
var x: {
<T>(x: any): any;
};

View File

@ -1,9 +0,0 @@
// Regression test for #5861
interface Foo<T> { prop: T; }
declare function lift<U>(value: U | Foo<U>): Foo<U>;
function unlift<U>(value: U | Foo<U>): U {
return lift(value).prop;
}

View File

@ -1,72 +0,0 @@
// Repro from #2264
interface Y { 'i am a very certain type': Y }
var y: Y = <Y>undefined;
function destructure<a, r>(
something: a | Y,
haveValue: (value: a) => r,
haveY: (value: Y) => r
): r {
return something === y ? haveY(y) : haveValue(<a>something);
}
var value = Math.random() > 0.5 ? 'hey!' : <Y>undefined;
var result = destructure(value, text => 'string', y => 'other one'); // text: string, y: Y
// Repro from #4212
function isVoid<a>(value: void | a): value is void {
return undefined;
}
function isNonVoid<a>(value: void | a) : value is a {
return undefined;
}
function foo1<a>(value: void|a): void {
if (isVoid(value)) {
value; // value is void
} else {
value; // value is a
}
}
function baz1<a>(value: void|a): void {
if (isNonVoid(value)) {
value; // value is a
} else {
value; // value is void
}
}
// Repro from #5417
type Maybe<T> = T | void;
function get<U>(x: U | void): U {
return null; // just an example
}
let foo: Maybe<string>;
get(foo).toUpperCase(); // Ok
// Repro from #5456
interface Man {
walks: boolean;
}
interface Bear {
roars: boolean;
}
interface Pig {
oinks: boolean;
}
declare function pigify<T>(y: T & Bear): T & Pig;
declare var mbp: Man & Bear;
pigify(mbp).oinks; // OK, mbp is treated as Pig
pigify(mbp).walks; // Ok, mbp is treated as Man

View File

@ -1,23 +0,0 @@
declare function f1<T>(x: T | string): T;
var a1: string;
var b1: string | string[];
var c1: string[] | string;
var d1: string | { name: string };
var e1: number | string | boolean;
f1(a1); // string
f1(b1); // string[]
f1(c1); // string[]
f1(d1); // { name: string }
f1(e1); // number | boolean
declare function f2<T>(x: T & { name: string }): T;
var a2: string & { name: string };
var b2: { name: string } & string[];
var c2: string & { name: string } & number;
var d2: string & { name: string } & number & { name: string };
f2(a2); // string
f2(b2); // string[]
f2(c2); // string & number
f2(d2); // string & number