Only collect inferences which actually have inferences into the returnMapper (#30111)

This commit is contained in:
Wesley Wigham 2019-02-28 12:46:24 -08:00 committed by GitHub
parent 5ec5e0466d
commit a6a3ae00a6
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 189 additions and 2 deletions

View File

@ -10691,6 +10691,23 @@ namespace ts {
mapper;
}
function cloneInferredPartOfContext(context: InferenceContext): InferenceContext | undefined {
// Filter context to only those parameters which actually have inference candidates
const params = [];
const inferences = [];
for (let i = 0; i < context.typeParameters.length; i++) {
const info = context.inferences[i];
if (info.candidates || info.contraCandidates) {
params.push(context.typeParameters[i]);
inferences.push(info);
}
}
if (!params.length) {
return undefined;
}
return createInferenceContext(params, context.signature, context.flags | InferenceFlags.NoDefault, context.compareTypes, inferences);
}
function combineTypeMappers(mapper1: TypeMapper | undefined, mapper2: TypeMapper): TypeMapper;
function combineTypeMappers(mapper1: TypeMapper, mapper2: TypeMapper | undefined): TypeMapper;
function combineTypeMappers(mapper1: TypeMapper, mapper2: TypeMapper): TypeMapper {
@ -14900,7 +14917,7 @@ namespace ts {
// parameter should be instantiated to the empty object type.
inferredType = instantiateType(defaultType,
combineTypeMappers(
createBackreferenceMapper(context.signature!.typeParameters!, index),
createBackreferenceMapper(context.typeParameters, index),
context));
}
else {
@ -20069,7 +20086,7 @@ namespace ts {
inferTypes(context.inferences, inferenceSourceType, inferenceTargetType, InferencePriority.ReturnType);
// Create a type mapper for instantiating generic contextual types using the inferences made
// from the return type.
context.returnMapper = cloneTypeMapper(context);
context.returnMapper = cloneInferredPartOfContext(context);
}
}

View File

@ -0,0 +1,24 @@
//// [returnTypeInferenceNotTooBroad.ts]
type Signs = { kind: 'a'; a: 3; } | { kind: 'b'; b: 2; } | { kind: 'c'; c: 1; };
interface Opts<T> {
low?: number;
sign?: T
}
interface Wrapper<T> {
}
declare function sepsis<T extends Signs>(opts: Opts<T>): Wrapper<T>;
declare function unwrap<T>(w: Wrapper<T>): T;
export const y = sepsis({ low: 1, sign: { kind: 'a', a: 3 }});
// $ExpectType { kind: "a"; a: 3; }
export const yun = unwrap(y);
// $ExpectType { kind: "a"; a: 3; }
export const yone = unwrap(sepsis({ low: 1, sign: { kind: 'a', a: 3 }}));
//// [returnTypeInferenceNotTooBroad.js]
"use strict";
exports.__esModule = true;
exports.y = sepsis({ low: 1, sign: { kind: 'a', a: 3 } });
// $ExpectType { kind: "a"; a: 3; }
exports.yun = unwrap(exports.y);
// $ExpectType { kind: "a"; a: 3; }
exports.yone = unwrap(sepsis({ low: 1, sign: { kind: 'a', a: 3 } }));

View File

@ -0,0 +1,67 @@
=== tests/cases/compiler/returnTypeInferenceNotTooBroad.ts ===
type Signs = { kind: 'a'; a: 3; } | { kind: 'b'; b: 2; } | { kind: 'c'; c: 1; };
>Signs : Symbol(Signs, Decl(returnTypeInferenceNotTooBroad.ts, 0, 0))
>kind : Symbol(kind, Decl(returnTypeInferenceNotTooBroad.ts, 0, 14))
>a : Symbol(a, Decl(returnTypeInferenceNotTooBroad.ts, 0, 25))
>kind : Symbol(kind, Decl(returnTypeInferenceNotTooBroad.ts, 0, 37))
>b : Symbol(b, Decl(returnTypeInferenceNotTooBroad.ts, 0, 48))
>kind : Symbol(kind, Decl(returnTypeInferenceNotTooBroad.ts, 0, 60))
>c : Symbol(c, Decl(returnTypeInferenceNotTooBroad.ts, 0, 71))
interface Opts<T> {
>Opts : Symbol(Opts, Decl(returnTypeInferenceNotTooBroad.ts, 0, 80))
>T : Symbol(T, Decl(returnTypeInferenceNotTooBroad.ts, 1, 15))
low?: number;
>low : Symbol(Opts.low, Decl(returnTypeInferenceNotTooBroad.ts, 1, 19))
sign?: T
>sign : Symbol(Opts.sign, Decl(returnTypeInferenceNotTooBroad.ts, 2, 17))
>T : Symbol(T, Decl(returnTypeInferenceNotTooBroad.ts, 1, 15))
}
interface Wrapper<T> {
>Wrapper : Symbol(Wrapper, Decl(returnTypeInferenceNotTooBroad.ts, 4, 1))
>T : Symbol(T, Decl(returnTypeInferenceNotTooBroad.ts, 5, 18))
}
declare function sepsis<T extends Signs>(opts: Opts<T>): Wrapper<T>;
>sepsis : Symbol(sepsis, Decl(returnTypeInferenceNotTooBroad.ts, 6, 1))
>T : Symbol(T, Decl(returnTypeInferenceNotTooBroad.ts, 7, 24))
>Signs : Symbol(Signs, Decl(returnTypeInferenceNotTooBroad.ts, 0, 0))
>opts : Symbol(opts, Decl(returnTypeInferenceNotTooBroad.ts, 7, 41))
>Opts : Symbol(Opts, Decl(returnTypeInferenceNotTooBroad.ts, 0, 80))
>T : Symbol(T, Decl(returnTypeInferenceNotTooBroad.ts, 7, 24))
>Wrapper : Symbol(Wrapper, Decl(returnTypeInferenceNotTooBroad.ts, 4, 1))
>T : Symbol(T, Decl(returnTypeInferenceNotTooBroad.ts, 7, 24))
declare function unwrap<T>(w: Wrapper<T>): T;
>unwrap : Symbol(unwrap, Decl(returnTypeInferenceNotTooBroad.ts, 7, 68))
>T : Symbol(T, Decl(returnTypeInferenceNotTooBroad.ts, 8, 24))
>w : Symbol(w, Decl(returnTypeInferenceNotTooBroad.ts, 8, 27))
>Wrapper : Symbol(Wrapper, Decl(returnTypeInferenceNotTooBroad.ts, 4, 1))
>T : Symbol(T, Decl(returnTypeInferenceNotTooBroad.ts, 8, 24))
>T : Symbol(T, Decl(returnTypeInferenceNotTooBroad.ts, 8, 24))
export const y = sepsis({ low: 1, sign: { kind: 'a', a: 3 }});
>y : Symbol(y, Decl(returnTypeInferenceNotTooBroad.ts, 9, 12))
>sepsis : Symbol(sepsis, Decl(returnTypeInferenceNotTooBroad.ts, 6, 1))
>low : Symbol(low, Decl(returnTypeInferenceNotTooBroad.ts, 9, 25))
>sign : Symbol(sign, Decl(returnTypeInferenceNotTooBroad.ts, 9, 33))
>kind : Symbol(kind, Decl(returnTypeInferenceNotTooBroad.ts, 9, 41))
>a : Symbol(a, Decl(returnTypeInferenceNotTooBroad.ts, 9, 52))
// $ExpectType { kind: "a"; a: 3; }
export const yun = unwrap(y);
>yun : Symbol(yun, Decl(returnTypeInferenceNotTooBroad.ts, 11, 12))
>unwrap : Symbol(unwrap, Decl(returnTypeInferenceNotTooBroad.ts, 7, 68))
>y : Symbol(y, Decl(returnTypeInferenceNotTooBroad.ts, 9, 12))
// $ExpectType { kind: "a"; a: 3; }
export const yone = unwrap(sepsis({ low: 1, sign: { kind: 'a', a: 3 }}));
>yone : Symbol(yone, Decl(returnTypeInferenceNotTooBroad.ts, 13, 12))
>unwrap : Symbol(unwrap, Decl(returnTypeInferenceNotTooBroad.ts, 7, 68))
>sepsis : Symbol(sepsis, Decl(returnTypeInferenceNotTooBroad.ts, 6, 1))
>low : Symbol(low, Decl(returnTypeInferenceNotTooBroad.ts, 13, 35))
>sign : Symbol(sign, Decl(returnTypeInferenceNotTooBroad.ts, 13, 43))
>kind : Symbol(kind, Decl(returnTypeInferenceNotTooBroad.ts, 13, 51))
>a : Symbol(a, Decl(returnTypeInferenceNotTooBroad.ts, 13, 62))

View File

@ -0,0 +1,65 @@
=== tests/cases/compiler/returnTypeInferenceNotTooBroad.ts ===
type Signs = { kind: 'a'; a: 3; } | { kind: 'b'; b: 2; } | { kind: 'c'; c: 1; };
>Signs : Signs
>kind : "a"
>a : 3
>kind : "b"
>b : 2
>kind : "c"
>c : 1
interface Opts<T> {
low?: number;
>low : number
sign?: T
>sign : T
}
interface Wrapper<T> {
}
declare function sepsis<T extends Signs>(opts: Opts<T>): Wrapper<T>;
>sepsis : <T extends Signs>(opts: Opts<T>) => Wrapper<T>
>opts : Opts<T>
declare function unwrap<T>(w: Wrapper<T>): T;
>unwrap : <T>(w: Wrapper<T>) => T
>w : Wrapper<T>
export const y = sepsis({ low: 1, sign: { kind: 'a', a: 3 }});
>y : Wrapper<{ kind: "a"; a: 3; }>
>sepsis({ low: 1, sign: { kind: 'a', a: 3 }}) : Wrapper<{ kind: "a"; a: 3; }>
>sepsis : <T extends Signs>(opts: Opts<T>) => Wrapper<T>
>{ low: 1, sign: { kind: 'a', a: 3 }} : { low: number; sign: { kind: "a"; a: 3; }; }
>low : number
>1 : 1
>sign : { kind: "a"; a: 3; }
>{ kind: 'a', a: 3 } : { kind: "a"; a: 3; }
>kind : "a"
>'a' : "a"
>a : 3
>3 : 3
// $ExpectType { kind: "a"; a: 3; }
export const yun = unwrap(y);
>yun : { kind: "a"; a: 3; }
>unwrap(y) : { kind: "a"; a: 3; }
>unwrap : <T>(w: Wrapper<T>) => T
>y : Wrapper<{ kind: "a"; a: 3; }>
// $ExpectType { kind: "a"; a: 3; }
export const yone = unwrap(sepsis({ low: 1, sign: { kind: 'a', a: 3 }}));
>yone : { kind: "a"; a: 3; }
>unwrap(sepsis({ low: 1, sign: { kind: 'a', a: 3 }})) : { kind: "a"; a: 3; }
>unwrap : <T>(w: Wrapper<T>) => T
>sepsis({ low: 1, sign: { kind: 'a', a: 3 }}) : Wrapper<{ kind: "a"; a: 3; }>
>sepsis : <T extends Signs>(opts: Opts<T>) => Wrapper<T>
>{ low: 1, sign: { kind: 'a', a: 3 }} : { low: number; sign: { kind: "a"; a: 3; }; }
>low : number
>1 : 1
>sign : { kind: "a"; a: 3; }
>{ kind: 'a', a: 3 } : { kind: "a"; a: 3; }
>kind : "a"
>'a' : "a"
>a : 3
>3 : 3

View File

@ -0,0 +1,14 @@
type Signs = { kind: 'a'; a: 3; } | { kind: 'b'; b: 2; } | { kind: 'c'; c: 1; };
interface Opts<T> {
low?: number;
sign?: T
}
interface Wrapper<T> {
}
declare function sepsis<T extends Signs>(opts: Opts<T>): Wrapper<T>;
declare function unwrap<T>(w: Wrapper<T>): T;
export const y = sepsis({ low: 1, sign: { kind: 'a', a: 3 }});
// $ExpectType { kind: "a"; a: 3; }
export const yun = unwrap(y);
// $ExpectType { kind: "a"; a: 3; }
export const yone = unwrap(sepsis({ low: 1, sign: { kind: 'a', a: 3 }}));