Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix declaration emit for instantiation expressions. #60796

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 28 additions & 6 deletions src/compiler/checker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6147,8 +6147,15 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
},
serializeReturnTypeForSignature(syntacticContext, signatureDeclaration) {
const context = syntacticContext as NodeBuilderContext;
const signature = getSignatureFromDeclaration(signatureDeclaration);
const returnType = context.enclosingSymbolTypes.get(getSymbolId(getSymbolOfDeclaration(signatureDeclaration))) ?? instantiateType(getReturnTypeOfSignature(signature), context.mapper);
let signature = context.enclosingSymbolSignatures.get(getSymbolId(getSymbolOfDeclaration(signatureDeclaration)));
let returnType;
if (signature === undefined) {
signature = getSignatureFromDeclaration(signatureDeclaration);
returnType = instantiateType(getReturnTypeOfSignature(signature), context.mapper);
}
else {
returnType = getReturnTypeOfSignature(signature);
}
return serializeInferredReturnTypeForSignature(context, signature, returnType);
},
serializeTypeOfExpression(syntacticContext, expr) {
Expand Down Expand Up @@ -6252,8 +6259,8 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
if (symbol.flags & SymbolFlags.Accessor) {
type = node.kind === SyntaxKind.SetAccessor ? getWriteTypeOfSymbol(symbol) : getTypeOfAccessors(symbol);
}
else if (isValueSignatureDeclaration(node)) {
type = getReturnTypeOfSignature(getSignatureFromDeclaration(node));
else if (isFunctionLike(node)) {
type = getReturnTypeOfSignature(context.enclosingSymbolSignatures?.get(getSymbolId(symbol)) ?? getSignatureFromDeclaration(node));
}
else {
type = getTypeOfSymbol(symbol);
Expand Down Expand Up @@ -6387,6 +6394,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
typeParameterNamesByText: undefined,
typeParameterNamesByTextNextNameCount: undefined,
enclosingSymbolTypes: new Map(),
enclosingSymbolSignatures: new Map(),
mapper: undefined,
depth: 0,
couldUnfoldMore: false,
Expand All @@ -6401,7 +6409,20 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
}
return context.encounteredError ? undefined : resultingNode;
}

function addSymbolSignatureToContext(context: NodeBuilderContext, symbol: Symbol, signature: Signature) {
const id = getSymbolId(symbol);
const oldSignature = context.enclosingSymbolTypes.get(id);
context.enclosingSymbolSignatures.set(id, signature);
return restore;
function restore() {
if (oldSignature) {
context.enclosingSymbolTypes.set(id, oldSignature);
}
else {
context.enclosingSymbolTypes.delete(id);
}
}
}
function addSymbolTypeToContext(context: NodeBuilderContext, symbol: Symbol, type: Type) {
const id = getSymbolId(symbol);
const oldType = context.enclosingSymbolTypes.get(id);
Expand Down Expand Up @@ -8736,7 +8757,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
if (!(suppressAny && isTypeAny(returnType))) {
if (signature.declaration && !nodeIsSynthesized(signature.declaration)) {
const declarationSymbol = getSymbolOfDeclaration(signature.declaration);
const restore = addSymbolTypeToContext(context, declarationSymbol, returnType);
const restore = addSymbolSignatureToContext(context, declarationSymbol, signature);
returnTypeNode = syntacticNodeBuilder.serializeReturnTypeForSignature(signature.declaration, declarationSymbol, context);
restore();
}
Expand Down Expand Up @@ -53177,6 +53198,7 @@ interface NodeBuilderContext extends SyntacticTypeNodeBuilderContext {
remappedSymbolNames: Map<SymbolId, string> | undefined;
remappedSymbolReferences: Map<SymbolId, Symbol> | undefined;
enclosingSymbolTypes: Map<SymbolId, Type>;
enclosingSymbolSignatures: Map<SymbolId, Signature>;
reverseMappedStack: ReverseMappedSymbol[] | undefined;
bundled: boolean;
mapper: TypeMapper | undefined;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,147 @@
//// [tests/cases/compiler/declarationEmitInstantationExpressionNested.ts] ////

//// [declarationEmitInstantationExpressionNested.ts]
function outerFnExpression<K>(n: K) {
return function <T>(a: [T, K]): a is [T, K] {
return null!
}
}

export let nrFnFromFnExpression = outerFnExpression(1)<number>


function outerArrowFn<K>(n: K) {
return function <T>(a: [T, K]): a is [T, K] {
return null!
}
}

export let nrFnFromArrowFn = outerArrowFn(1)<number>

function outerObjectMethod<K>(n: K) {
return {
inner<T>(a: [T, K]): a is [T, K] {
return null!
}
}
}

export let nrFnFromObjectMethod = outerObjectMethod(1).inner<number>


function outerStaticClassMember<K>(n: K) {
return class {
static inner<T>(a: [T, K]): a is [T, K] {
return null!
}
}
}

export let nrFnFromStaticClassMember = outerStaticClassMember(1).inner<number>


function outerClassMethod<K>(n: K) {
return class {
inner<T>(a: [T, K]): a is [T, K] {
return null!
}
}
}

export let nrFnFromClassMethod = new (outerClassMethod(1))().inner<number>

function outerMethodSignature<K>(n: K) : {
inner<T>(a: [T, K]): a is [T, K]
} {
return null!
}

export let nrFnFromMethodSignature = outerMethodSignature(1).inner<number>



function outerFnSignature<K>(n: K) : {
<T>(a: [T, K]): a is [T, K]
} {
return null!
}

export let nrFnFromFnSignature = outerFnSignature(1)<number>



function outerFnType<K>(n: K) : <T>(a: [T, K]) => a is [T, K] {
return null!
}

export let nrFnFromFnType = outerFnType(1)<number>

//// [declarationEmitInstantationExpressionNested.js]
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.nrFnFromFnType = exports.nrFnFromFnSignature = exports.nrFnFromMethodSignature = exports.nrFnFromClassMethod = exports.nrFnFromStaticClassMember = exports.nrFnFromObjectMethod = exports.nrFnFromArrowFn = exports.nrFnFromFnExpression = void 0;
function outerFnExpression(n) {
return function (a) {
return null;
};
}
exports.nrFnFromFnExpression = (outerFnExpression(1));
function outerArrowFn(n) {
return function (a) {
return null;
};
}
exports.nrFnFromArrowFn = (outerArrowFn(1));
function outerObjectMethod(n) {
return {
inner: function (a) {
return null;
}
};
}
exports.nrFnFromObjectMethod = (outerObjectMethod(1).inner);
function outerStaticClassMember(n) {
return /** @class */ (function () {
function class_1() {
}
class_1.inner = function (a) {
return null;
};
return class_1;
}());
}
exports.nrFnFromStaticClassMember = (outerStaticClassMember(1).inner);
function outerClassMethod(n) {
return /** @class */ (function () {
function class_2() {
}
class_2.prototype.inner = function (a) {
return null;
};
return class_2;
}());
}
exports.nrFnFromClassMethod = (new (outerClassMethod(1))().inner);
function outerMethodSignature(n) {
return null;
}
exports.nrFnFromMethodSignature = (outerMethodSignature(1).inner);
function outerFnSignature(n) {
return null;
}
exports.nrFnFromFnSignature = (outerFnSignature(1));
function outerFnType(n) {
return null;
}
exports.nrFnFromFnType = (outerFnType(1));


//// [declarationEmitInstantationExpressionNested.d.ts]
export declare let nrFnFromFnExpression: (a: [number, number]) => a is [number, number];
export declare let nrFnFromArrowFn: (a: [number, number]) => a is [number, number];
export declare let nrFnFromObjectMethod: (a: [number, number]) => a is [number, number];
export declare let nrFnFromStaticClassMember: (a: [number, number]) => a is [number, number];
export declare let nrFnFromClassMethod: (a: [number, number]) => a is [number, number];
export declare let nrFnFromMethodSignature: (a: [number, number]) => a is [number, number];
export declare let nrFnFromFnSignature: (a: [number, number]) => a is [number, number];
export declare let nrFnFromFnType: (a: [number, number]) => a is [number, number];
Loading
Loading