mirror of
https://github.com/microsoft/TypeScript.git
synced 2025-11-18 17:21:48 +00:00
Keep track of multiple current inference contexts (#51978)
* Keep track of multiple current inference contexts * Add regression test
This commit is contained in:
+20
-9
@@ -2069,8 +2069,9 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
|
||||
const contextualTypes: (Type | undefined)[] = [];
|
||||
let contextualTypeCount = 0;
|
||||
|
||||
let currentInferenceNode: Node | undefined;
|
||||
let currentInferenceContext: InferenceContext | undefined;
|
||||
const inferenceContextNodes: Node[] = [];
|
||||
const inferenceContexts: (InferenceContext | undefined)[] = [];
|
||||
let inferenceContextCount = 0;
|
||||
|
||||
const emptyStringType = getStringLiteralType("");
|
||||
const zeroType = getNumberLiteralType(0);
|
||||
@@ -28764,8 +28765,22 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
|
||||
return -1;
|
||||
}
|
||||
|
||||
function pushInferenceContext(node: Node, inferenceContext: InferenceContext | undefined) {
|
||||
inferenceContextNodes[inferenceContextCount] = node;
|
||||
inferenceContexts[inferenceContextCount] = inferenceContext;
|
||||
inferenceContextCount++;
|
||||
}
|
||||
|
||||
function popInferenceContext() {
|
||||
inferenceContextCount--;
|
||||
}
|
||||
|
||||
function getInferenceContext(node: Node) {
|
||||
return isNodeDescendantOf(node, currentInferenceNode) ? currentInferenceContext : undefined;
|
||||
for (let i = inferenceContextCount - 1; i >= 0; i--) {
|
||||
if (isNodeDescendantOf(node, inferenceContextNodes[i])) {
|
||||
return inferenceContexts[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function getContextualJsxElementAttributesType(node: JsxOpeningLikeElement, contextFlags: ContextFlags | undefined) {
|
||||
@@ -36022,10 +36037,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
|
||||
function checkExpressionWithContextualType(node: Expression, contextualType: Type, inferenceContext: InferenceContext | undefined, checkMode: CheckMode): Type {
|
||||
const contextNode = getContextNode(node);
|
||||
pushContextualType(contextNode, contextualType);
|
||||
const saveInferenceNode = currentInferenceNode;
|
||||
const saveInferenceContext = currentInferenceContext;
|
||||
currentInferenceNode = contextNode;
|
||||
currentInferenceContext = inferenceContext;
|
||||
pushInferenceContext(contextNode, inferenceContext);
|
||||
const type = checkExpression(node, checkMode | CheckMode.Contextual | (inferenceContext ? CheckMode.Inferential : 0));
|
||||
// In CheckMode.Inferential we collect intra-expression inference sites to process before fixing any type
|
||||
// parameters. This information is no longer needed after the call to checkExpression.
|
||||
@@ -36037,8 +36049,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
|
||||
// here would be to not mark contextually typed literals as fresh in the first place.
|
||||
const result = maybeTypeOfKind(type, TypeFlags.Literal) && isLiteralOfContextualType(type, instantiateContextualType(contextualType, node, /*contextFlags*/ undefined)) ?
|
||||
getRegularTypeOfLiteralType(type) : type;
|
||||
currentInferenceNode = saveInferenceNode;
|
||||
currentInferenceContext = saveInferenceContext;
|
||||
popInferenceContext();
|
||||
popContextualType();
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,36 @@
|
||||
//// [multipleInferenceContexts.ts]
|
||||
type ConstructorOptions<Data> =
|
||||
& ComponentOptionsProperties<Data>
|
||||
& ThisType<Instance<Data>>;
|
||||
|
||||
interface ComponentOptionsProperties<Data> {
|
||||
data: Data;
|
||||
render(): unknown;
|
||||
}
|
||||
|
||||
interface Instance<Data> {
|
||||
get<K extends keyof Data>(name: K): unknown;
|
||||
}
|
||||
|
||||
declare var Moon: {
|
||||
<Data>(options?: ConstructorOptions<Data>): Instance<Data>;
|
||||
};
|
||||
|
||||
const r2 = Moon({
|
||||
data: { msg: "" },
|
||||
render() {
|
||||
const h = (x: unknown) => x;
|
||||
return h(this.get("msg"));
|
||||
},
|
||||
});
|
||||
|
||||
|
||||
//// [multipleInferenceContexts.js]
|
||||
"use strict";
|
||||
var r2 = Moon({
|
||||
data: { msg: "" },
|
||||
render: function () {
|
||||
var h = function (x) { return x; };
|
||||
return h(this.get("msg"));
|
||||
},
|
||||
});
|
||||
@@ -0,0 +1,76 @@
|
||||
=== tests/cases/compiler/multipleInferenceContexts.ts ===
|
||||
type ConstructorOptions<Data> =
|
||||
>ConstructorOptions : Symbol(ConstructorOptions, Decl(multipleInferenceContexts.ts, 0, 0))
|
||||
>Data : Symbol(Data, Decl(multipleInferenceContexts.ts, 0, 24))
|
||||
|
||||
& ComponentOptionsProperties<Data>
|
||||
>ComponentOptionsProperties : Symbol(ComponentOptionsProperties, Decl(multipleInferenceContexts.ts, 2, 31))
|
||||
>Data : Symbol(Data, Decl(multipleInferenceContexts.ts, 0, 24))
|
||||
|
||||
& ThisType<Instance<Data>>;
|
||||
>ThisType : Symbol(ThisType, Decl(lib.es5.d.ts, --, --))
|
||||
>Instance : Symbol(Instance, Decl(multipleInferenceContexts.ts, 7, 1))
|
||||
>Data : Symbol(Data, Decl(multipleInferenceContexts.ts, 0, 24))
|
||||
|
||||
interface ComponentOptionsProperties<Data> {
|
||||
>ComponentOptionsProperties : Symbol(ComponentOptionsProperties, Decl(multipleInferenceContexts.ts, 2, 31))
|
||||
>Data : Symbol(Data, Decl(multipleInferenceContexts.ts, 4, 37))
|
||||
|
||||
data: Data;
|
||||
>data : Symbol(ComponentOptionsProperties.data, Decl(multipleInferenceContexts.ts, 4, 44))
|
||||
>Data : Symbol(Data, Decl(multipleInferenceContexts.ts, 4, 37))
|
||||
|
||||
render(): unknown;
|
||||
>render : Symbol(ComponentOptionsProperties.render, Decl(multipleInferenceContexts.ts, 5, 15))
|
||||
}
|
||||
|
||||
interface Instance<Data> {
|
||||
>Instance : Symbol(Instance, Decl(multipleInferenceContexts.ts, 7, 1))
|
||||
>Data : Symbol(Data, Decl(multipleInferenceContexts.ts, 9, 19))
|
||||
|
||||
get<K extends keyof Data>(name: K): unknown;
|
||||
>get : Symbol(Instance.get, Decl(multipleInferenceContexts.ts, 9, 26))
|
||||
>K : Symbol(K, Decl(multipleInferenceContexts.ts, 10, 8))
|
||||
>Data : Symbol(Data, Decl(multipleInferenceContexts.ts, 9, 19))
|
||||
>name : Symbol(name, Decl(multipleInferenceContexts.ts, 10, 30))
|
||||
>K : Symbol(K, Decl(multipleInferenceContexts.ts, 10, 8))
|
||||
}
|
||||
|
||||
declare var Moon: {
|
||||
>Moon : Symbol(Moon, Decl(multipleInferenceContexts.ts, 13, 11))
|
||||
|
||||
<Data>(options?: ConstructorOptions<Data>): Instance<Data>;
|
||||
>Data : Symbol(Data, Decl(multipleInferenceContexts.ts, 14, 5))
|
||||
>options : Symbol(options, Decl(multipleInferenceContexts.ts, 14, 11))
|
||||
>ConstructorOptions : Symbol(ConstructorOptions, Decl(multipleInferenceContexts.ts, 0, 0))
|
||||
>Data : Symbol(Data, Decl(multipleInferenceContexts.ts, 14, 5))
|
||||
>Instance : Symbol(Instance, Decl(multipleInferenceContexts.ts, 7, 1))
|
||||
>Data : Symbol(Data, Decl(multipleInferenceContexts.ts, 14, 5))
|
||||
|
||||
};
|
||||
|
||||
const r2 = Moon({
|
||||
>r2 : Symbol(r2, Decl(multipleInferenceContexts.ts, 17, 5))
|
||||
>Moon : Symbol(Moon, Decl(multipleInferenceContexts.ts, 13, 11))
|
||||
|
||||
data: { msg: "" },
|
||||
>data : Symbol(data, Decl(multipleInferenceContexts.ts, 17, 17))
|
||||
>msg : Symbol(msg, Decl(multipleInferenceContexts.ts, 18, 11))
|
||||
|
||||
render() {
|
||||
>render : Symbol(render, Decl(multipleInferenceContexts.ts, 18, 22))
|
||||
|
||||
const h = (x: unknown) => x;
|
||||
>h : Symbol(h, Decl(multipleInferenceContexts.ts, 20, 13))
|
||||
>x : Symbol(x, Decl(multipleInferenceContexts.ts, 20, 19))
|
||||
>x : Symbol(x, Decl(multipleInferenceContexts.ts, 20, 19))
|
||||
|
||||
return h(this.get("msg"));
|
||||
>h : Symbol(h, Decl(multipleInferenceContexts.ts, 20, 13))
|
||||
>this.get : Symbol(Instance.get, Decl(multipleInferenceContexts.ts, 9, 26))
|
||||
>this : Symbol(Instance, Decl(multipleInferenceContexts.ts, 7, 1))
|
||||
>get : Symbol(Instance.get, Decl(multipleInferenceContexts.ts, 9, 26))
|
||||
|
||||
},
|
||||
});
|
||||
|
||||
@@ -0,0 +1,62 @@
|
||||
=== tests/cases/compiler/multipleInferenceContexts.ts ===
|
||||
type ConstructorOptions<Data> =
|
||||
>ConstructorOptions : ConstructorOptions<Data>
|
||||
|
||||
& ComponentOptionsProperties<Data>
|
||||
& ThisType<Instance<Data>>;
|
||||
|
||||
interface ComponentOptionsProperties<Data> {
|
||||
data: Data;
|
||||
>data : Data
|
||||
|
||||
render(): unknown;
|
||||
>render : () => unknown
|
||||
}
|
||||
|
||||
interface Instance<Data> {
|
||||
get<K extends keyof Data>(name: K): unknown;
|
||||
>get : <K extends keyof Data>(name: K) => unknown
|
||||
>name : K
|
||||
}
|
||||
|
||||
declare var Moon: {
|
||||
>Moon : <Data>(options?: ConstructorOptions<Data> | undefined) => Instance<Data>
|
||||
|
||||
<Data>(options?: ConstructorOptions<Data>): Instance<Data>;
|
||||
>options : ConstructorOptions<Data> | undefined
|
||||
|
||||
};
|
||||
|
||||
const r2 = Moon({
|
||||
>r2 : Instance<{ msg: string; }>
|
||||
>Moon({ data: { msg: "" }, render() { const h = (x: unknown) => x; return h(this.get("msg")); },}) : Instance<{ msg: string; }>
|
||||
>Moon : <Data>(options?: ConstructorOptions<Data> | undefined) => Instance<Data>
|
||||
>{ data: { msg: "" }, render() { const h = (x: unknown) => x; return h(this.get("msg")); },} : { data: { msg: string; }; render(): unknown; }
|
||||
|
||||
data: { msg: "" },
|
||||
>data : { msg: string; }
|
||||
>{ msg: "" } : { msg: string; }
|
||||
>msg : string
|
||||
>"" : ""
|
||||
|
||||
render() {
|
||||
>render : () => unknown
|
||||
|
||||
const h = (x: unknown) => x;
|
||||
>h : (x: unknown) => unknown
|
||||
>(x: unknown) => x : (x: unknown) => unknown
|
||||
>x : unknown
|
||||
>x : unknown
|
||||
|
||||
return h(this.get("msg"));
|
||||
>h(this.get("msg")) : unknown
|
||||
>h : (x: unknown) => unknown
|
||||
>this.get("msg") : unknown
|
||||
>this.get : <K extends "msg">(name: K) => unknown
|
||||
>this : Instance<{ msg: string; }>
|
||||
>get : <K extends "msg">(name: K) => unknown
|
||||
>"msg" : "msg"
|
||||
|
||||
},
|
||||
});
|
||||
|
||||
@@ -0,0 +1,26 @@
|
||||
// @strict: true
|
||||
|
||||
type ConstructorOptions<Data> =
|
||||
& ComponentOptionsProperties<Data>
|
||||
& ThisType<Instance<Data>>;
|
||||
|
||||
interface ComponentOptionsProperties<Data> {
|
||||
data: Data;
|
||||
render(): unknown;
|
||||
}
|
||||
|
||||
interface Instance<Data> {
|
||||
get<K extends keyof Data>(name: K): unknown;
|
||||
}
|
||||
|
||||
declare var Moon: {
|
||||
<Data>(options?: ConstructorOptions<Data>): Instance<Data>;
|
||||
};
|
||||
|
||||
const r2 = Moon({
|
||||
data: { msg: "" },
|
||||
render() {
|
||||
const h = (x: unknown) => x;
|
||||
return h(this.get("msg"));
|
||||
},
|
||||
});
|
||||
Reference in New Issue
Block a user