Merge pull request #22850 from Microsoft/tupleTypeInference

Only make inferences from tuple types of right arity
This commit is contained in:
Anders Hejlsberg 2018-03-26 09:35:45 -07:00 committed by GitHub
commit d7df84d641
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 275 additions and 3 deletions

View File

@ -11603,6 +11603,13 @@ namespace ts {
return undefined;
}
function typesDefinitelyUnrelated(source: Type, target: Type) {
// Two tuple types with different arity are definitely unrelated.
// Two object types that each have a property that is unmatched in the other are definitely unrelated.
return isTupleType(source) && isTupleType(target) && getTypeReferenceArity(<TypeReference>source) !== getTypeReferenceArity(<TypeReference>target) ||
!!getUnmatchedProperty(source, target, /*requireOptionalProperties*/ false) && !!getUnmatchedProperty(target, source, /*requireOptionalProperties*/ false);
}
function getTypeFromInference(inference: InferenceInfo) {
return inference.candidates ? getUnionType(inference.candidates, UnionReduction.Subtype) :
inference.contraCandidates ? getIntersectionType(inference.contraCandidates) :
@ -11873,9 +11880,8 @@ namespace ts {
return;
}
}
// Infer from the members of source and target only if the two types are possibly related. We check
// in both directions because we may be inferring for a co-variant or a contra-variant position.
if (!getUnmatchedProperty(source, target, /*requireOptionalProperties*/ false) || !getUnmatchedProperty(target, source, /*requireOptionalProperties*/ false)) {
// Infer from the members of source and target only if the two types are possibly related
if (!typesDefinitelyUnrelated(source, target)) {
inferFromProperties(source, target);
inferFromSignatures(source, target, SignatureKind.Call);
inferFromSignatures(source, target, SignatureKind.Construct);

View File

@ -0,0 +1,35 @@
//// [tupleTypeInference2.ts]
// Repro from #22564
type A<R> = [R] | [R, string];
declare function f<T>(x: A<T>): T;
f([undefined, ''] as [never, string]); // T: never
f([undefined, ''] as [void, string]); // T: void
// Repro from #22563
type B<R, S> = [R] | [R, S];
declare function g<T, U>(f: B<T, U>): U;
g([[]] as [void[]]); // U: {}
type C<R, S> = [R[]] | [R[], S];
declare function h<T, U>(f: C<T, U>): U;
h([[]] as [void[]]); // U: {}
// Repro from #22562
type C2<R> = [R[]] | [R[], void];
declare function h2<T>(f: C2<T>): T;
h2([[]] as [never[]]); // T: never
h2([[]] as [void[]]); // T: void
//// [tupleTypeInference2.js]
"use strict";
// Repro from #22564
f([undefined, '']); // T: never
f([undefined, '']); // T: void
g([[]]); // U: {}
h([[]]); // U: {}
h2([[]]); // T: never
h2([[]]); // T: void

View File

@ -0,0 +1,91 @@
=== tests/cases/compiler/tupleTypeInference2.ts ===
// Repro from #22564
type A<R> = [R] | [R, string];
>A : Symbol(A, Decl(tupleTypeInference2.ts, 0, 0))
>R : Symbol(R, Decl(tupleTypeInference2.ts, 2, 7))
>R : Symbol(R, Decl(tupleTypeInference2.ts, 2, 7))
>R : Symbol(R, Decl(tupleTypeInference2.ts, 2, 7))
declare function f<T>(x: A<T>): T;
>f : Symbol(f, Decl(tupleTypeInference2.ts, 2, 30))
>T : Symbol(T, Decl(tupleTypeInference2.ts, 3, 19))
>x : Symbol(x, Decl(tupleTypeInference2.ts, 3, 22))
>A : Symbol(A, Decl(tupleTypeInference2.ts, 0, 0))
>T : Symbol(T, Decl(tupleTypeInference2.ts, 3, 19))
>T : Symbol(T, Decl(tupleTypeInference2.ts, 3, 19))
f([undefined, ''] as [never, string]); // T: never
>f : Symbol(f, Decl(tupleTypeInference2.ts, 2, 30))
>undefined : Symbol(undefined)
f([undefined, ''] as [void, string]); // T: void
>f : Symbol(f, Decl(tupleTypeInference2.ts, 2, 30))
>undefined : Symbol(undefined)
// Repro from #22563
type B<R, S> = [R] | [R, S];
>B : Symbol(B, Decl(tupleTypeInference2.ts, 5, 37))
>R : Symbol(R, Decl(tupleTypeInference2.ts, 9, 7))
>S : Symbol(S, Decl(tupleTypeInference2.ts, 9, 9))
>R : Symbol(R, Decl(tupleTypeInference2.ts, 9, 7))
>R : Symbol(R, Decl(tupleTypeInference2.ts, 9, 7))
>S : Symbol(S, Decl(tupleTypeInference2.ts, 9, 9))
declare function g<T, U>(f: B<T, U>): U;
>g : Symbol(g, Decl(tupleTypeInference2.ts, 9, 28))
>T : Symbol(T, Decl(tupleTypeInference2.ts, 10, 19))
>U : Symbol(U, Decl(tupleTypeInference2.ts, 10, 21))
>f : Symbol(f, Decl(tupleTypeInference2.ts, 10, 25))
>B : Symbol(B, Decl(tupleTypeInference2.ts, 5, 37))
>T : Symbol(T, Decl(tupleTypeInference2.ts, 10, 19))
>U : Symbol(U, Decl(tupleTypeInference2.ts, 10, 21))
>U : Symbol(U, Decl(tupleTypeInference2.ts, 10, 21))
g([[]] as [void[]]); // U: {}
>g : Symbol(g, Decl(tupleTypeInference2.ts, 9, 28))
type C<R, S> = [R[]] | [R[], S];
>C : Symbol(C, Decl(tupleTypeInference2.ts, 11, 20))
>R : Symbol(R, Decl(tupleTypeInference2.ts, 13, 7))
>S : Symbol(S, Decl(tupleTypeInference2.ts, 13, 9))
>R : Symbol(R, Decl(tupleTypeInference2.ts, 13, 7))
>R : Symbol(R, Decl(tupleTypeInference2.ts, 13, 7))
>S : Symbol(S, Decl(tupleTypeInference2.ts, 13, 9))
declare function h<T, U>(f: C<T, U>): U;
>h : Symbol(h, Decl(tupleTypeInference2.ts, 13, 32))
>T : Symbol(T, Decl(tupleTypeInference2.ts, 14, 19))
>U : Symbol(U, Decl(tupleTypeInference2.ts, 14, 21))
>f : Symbol(f, Decl(tupleTypeInference2.ts, 14, 25))
>C : Symbol(C, Decl(tupleTypeInference2.ts, 11, 20))
>T : Symbol(T, Decl(tupleTypeInference2.ts, 14, 19))
>U : Symbol(U, Decl(tupleTypeInference2.ts, 14, 21))
>U : Symbol(U, Decl(tupleTypeInference2.ts, 14, 21))
h([[]] as [void[]]); // U: {}
>h : Symbol(h, Decl(tupleTypeInference2.ts, 13, 32))
// Repro from #22562
type C2<R> = [R[]] | [R[], void];
>C2 : Symbol(C2, Decl(tupleTypeInference2.ts, 15, 20))
>R : Symbol(R, Decl(tupleTypeInference2.ts, 19, 8))
>R : Symbol(R, Decl(tupleTypeInference2.ts, 19, 8))
>R : Symbol(R, Decl(tupleTypeInference2.ts, 19, 8))
declare function h2<T>(f: C2<T>): T;
>h2 : Symbol(h2, Decl(tupleTypeInference2.ts, 19, 33))
>T : Symbol(T, Decl(tupleTypeInference2.ts, 20, 20))
>f : Symbol(f, Decl(tupleTypeInference2.ts, 20, 23))
>C2 : Symbol(C2, Decl(tupleTypeInference2.ts, 15, 20))
>T : Symbol(T, Decl(tupleTypeInference2.ts, 20, 20))
>T : Symbol(T, Decl(tupleTypeInference2.ts, 20, 20))
h2([[]] as [never[]]); // T: never
>h2 : Symbol(h2, Decl(tupleTypeInference2.ts, 19, 33))
h2([[]] as [void[]]); // T: void
>h2 : Symbol(h2, Decl(tupleTypeInference2.ts, 19, 33))

View File

@ -0,0 +1,115 @@
=== tests/cases/compiler/tupleTypeInference2.ts ===
// Repro from #22564
type A<R> = [R] | [R, string];
>A : A<R>
>R : R
>R : R
>R : R
declare function f<T>(x: A<T>): T;
>f : <T>(x: A<T>) => T
>T : T
>x : A<T>
>A : A<R>
>T : T
>T : T
f([undefined, ''] as [never, string]); // T: never
>f([undefined, ''] as [never, string]) : never
>f : <T>(x: A<T>) => T
>[undefined, ''] as [never, string] : [never, string]
>[undefined, ''] : [undefined, string]
>undefined : undefined
>'' : ""
f([undefined, ''] as [void, string]); // T: void
>f([undefined, ''] as [void, string]) : void
>f : <T>(x: A<T>) => T
>[undefined, ''] as [void, string] : [void, string]
>[undefined, ''] : [undefined, string]
>undefined : undefined
>'' : ""
// Repro from #22563
type B<R, S> = [R] | [R, S];
>B : B<R, S>
>R : R
>S : S
>R : R
>R : R
>S : S
declare function g<T, U>(f: B<T, U>): U;
>g : <T, U>(f: B<T, U>) => U
>T : T
>U : U
>f : B<T, U>
>B : B<R, S>
>T : T
>U : U
>U : U
g([[]] as [void[]]); // U: {}
>g([[]] as [void[]]) : {}
>g : <T, U>(f: B<T, U>) => U
>[[]] as [void[]] : [void[]]
>[[]] : [never[]]
>[] : never[]
type C<R, S> = [R[]] | [R[], S];
>C : C<R, S>
>R : R
>S : S
>R : R
>R : R
>S : S
declare function h<T, U>(f: C<T, U>): U;
>h : <T, U>(f: C<T, U>) => U
>T : T
>U : U
>f : C<T, U>
>C : C<R, S>
>T : T
>U : U
>U : U
h([[]] as [void[]]); // U: {}
>h([[]] as [void[]]) : {}
>h : <T, U>(f: C<T, U>) => U
>[[]] as [void[]] : [void[]]
>[[]] : [never[]]
>[] : never[]
// Repro from #22562
type C2<R> = [R[]] | [R[], void];
>C2 : C2<R>
>R : R
>R : R
>R : R
declare function h2<T>(f: C2<T>): T;
>h2 : <T>(f: C2<T>) => T
>T : T
>f : C2<T>
>C2 : C2<R>
>T : T
>T : T
h2([[]] as [never[]]); // T: never
>h2([[]] as [never[]]) : never
>h2 : <T>(f: C2<T>) => T
>[[]] as [never[]] : [never[]]
>[[]] : [never[]]
>[] : never[]
h2([[]] as [void[]]); // T: void
>h2([[]] as [void[]]) : void
>h2 : <T>(f: C2<T>) => T
>[[]] as [void[]] : [void[]]
>[[]] : [never[]]
>[] : never[]

View File

@ -0,0 +1,25 @@
// @strict: true
// Repro from #22564
type A<R> = [R] | [R, string];
declare function f<T>(x: A<T>): T;
f([undefined, ''] as [never, string]); // T: never
f([undefined, ''] as [void, string]); // T: void
// Repro from #22563
type B<R, S> = [R] | [R, S];
declare function g<T, U>(f: B<T, U>): U;
g([[]] as [void[]]); // U: {}
type C<R, S> = [R[]] | [R[], S];
declare function h<T, U>(f: C<T, U>): U;
h([[]] as [void[]]); // U: {}
// Repro from #22562
type C2<R> = [R[]] | [R[], void];
declare function h2<T>(f: C2<T>): T;
h2([[]] as [never[]]); // T: never
h2([[]] as [void[]]); // T: void