From b45cf0d694401aeec9023f731e5da7ad8e418f71 Mon Sep 17 00:00:00 2001 From: LowR Date: Fri, 8 Apr 2022 07:40:39 +0900 Subject: [PATCH] disentangle the meaning of `SymbolLinks.target` (#47098) --- src/compiler/checker.ts | 24 ++-- src/compiler/types.ts | 3 +- ...adExpressionContextualTypeWithNamespace.js | 84 ++++++++++++++ ...ressionContextualTypeWithNamespace.symbols | 97 +++++++++++++++++ ...xpressionContextualTypeWithNamespace.types | 103 ++++++++++++++++++ ...adExpressionContextualTypeWithNamespace.ts | 33 ++++++ 6 files changed, 331 insertions(+), 13 deletions(-) create mode 100644 tests/baselines/reference/spreadExpressionContextualTypeWithNamespace.js create mode 100644 tests/baselines/reference/spreadExpressionContextualTypeWithNamespace.symbols create mode 100644 tests/baselines/reference/spreadExpressionContextualTypeWithNamespace.types create mode 100644 tests/cases/compiler/spreadExpressionContextualTypeWithNamespace.ts diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 0f2b62bf493..9740d82d214 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -3116,27 +3116,27 @@ namespace ts { function resolveAlias(symbol: Symbol): Symbol { Debug.assert((symbol.flags & SymbolFlags.Alias) !== 0, "Should only get Alias here."); const links = getSymbolLinks(symbol); - if (!links.target) { - links.target = resolvingSymbol; + if (!links.aliasTarget) { + links.aliasTarget = resolvingSymbol; const node = getDeclarationOfAliasSymbol(symbol); if (!node) return Debug.fail(); const target = getTargetOfAliasDeclaration(node); - if (links.target === resolvingSymbol) { - links.target = target || unknownSymbol; + if (links.aliasTarget === resolvingSymbol) { + links.aliasTarget = target || unknownSymbol; } else { error(node, Diagnostics.Circular_definition_of_import_alias_0, symbolToString(symbol)); } } - else if (links.target === resolvingSymbol) { - links.target = unknownSymbol; + else if (links.aliasTarget === resolvingSymbol) { + links.aliasTarget = unknownSymbol; } - return links.target; + return links.aliasTarget; } function tryResolveAlias(symbol: Symbol): Symbol | undefined { const links = getSymbolLinks(symbol); - if (links.target !== resolvingSymbol) { + if (links.aliasTarget !== resolvingSymbol) { return resolveAlias(symbol); } @@ -31748,7 +31748,7 @@ namespace ts { const newSymbol = createSymbol(SymbolFlags.Alias, InternalSymbolName.Default); newSymbol.parent = originalSymbol; newSymbol.nameType = getStringLiteralType("default"); - newSymbol.target = resolveSymbol(symbol); + newSymbol.aliasTarget = resolveSymbol(symbol); memberTable.set(InternalSymbolName.Default, newSymbol); return createAnonymousType(anonymousSymbol, memberTable, emptyArray, emptyArray, emptyArray); } @@ -42271,11 +42271,11 @@ namespace ts { const { leftSpread, rightSpread, syntheticOrigin } = symbol as TransientSymbol; return leftSpread ? [leftSpread, rightSpread!] : syntheticOrigin ? [syntheticOrigin] - : singleElementArray(tryGetAliasTarget(symbol)); + : singleElementArray(tryGetTarget(symbol)); } return undefined; } - function tryGetAliasTarget(symbol: Symbol): Symbol | undefined { + function tryGetTarget(symbol: Symbol): Symbol | undefined { let target: Symbol | undefined; let next: Symbol | undefined = symbol; while (next = getSymbolLinks(next).target) { @@ -42527,7 +42527,7 @@ namespace ts { if (links?.referenced) { return true; } - const target = getSymbolLinks(symbol!).target; // TODO: GH#18217 + const target = getSymbolLinks(symbol!).aliasTarget; // TODO: GH#18217 if (target && getEffectiveModifierFlags(node) & ModifierFlags.Export && target.flags & SymbolFlags.Value && (shouldPreserveConstEnums(compilerOptions) || !isConstEnumOrConstEnumOnlyModule(target))) { diff --git a/src/compiler/types.ts b/src/compiler/types.ts index 2302c95322f..9ae7d10b07c 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -4943,7 +4943,8 @@ namespace ts { /* @internal */ export interface SymbolLinks { immediateTarget?: Symbol; // Immediate target of an alias. May be another alias. Do not access directly, use `checker.getImmediateAliasedSymbol` instead. - target?: Symbol; // Resolved (non-alias) target of an alias + aliasTarget?: Symbol, // Resolved (non-alias) target of an alias + target?: Symbol; // Original version of an instantiated symbol type?: Type; // Type of value symbol writeType?: Type; // Type of value symbol in write contexts nameType?: Type; // Type associated with a late-bound symbol diff --git a/tests/baselines/reference/spreadExpressionContextualTypeWithNamespace.js b/tests/baselines/reference/spreadExpressionContextualTypeWithNamespace.js new file mode 100644 index 00000000000..3357cc18ca8 --- /dev/null +++ b/tests/baselines/reference/spreadExpressionContextualTypeWithNamespace.js @@ -0,0 +1,84 @@ +//// [tests/cases/compiler/spreadExpressionContextualTypeWithNamespace.ts] //// + +//// [spreadExpressionContextualTypeWithNamespace_0.ts] +// Repro from #44179 with some modification + +function func() {} +class klass {} +const obj = { x: true }; + +export { func, klass, obj }; + +export function exportedDirectly() {} + +//// [spreadExpressionContextualTypeWithNamespace_1.ts] +import * as stuff from "./spreadExpressionContextualTypeWithNamespace_0"; + +stuff.func; +stuff.klass; +stuff.obj; +stuff.exportedDirectly; + +function getStuff() { + const thing = { ...stuff }; + thing.func; + thing.klass; + thing.obj; + thing.exportedDirectly; + return thing; +} + +getStuff().func; +getStuff().klass; +getStuff().obj; +getStuff().exportedDirectly; + + +//// [spreadExpressionContextualTypeWithNamespace_0.js] +"use strict"; +// Repro from #44179 with some modification +exports.__esModule = true; +exports.exportedDirectly = exports.obj = exports.klass = exports.func = void 0; +function func() { } +exports.func = func; +var klass = /** @class */ (function () { + function klass() { + } + return klass; +}()); +exports.klass = klass; +var obj = { x: true }; +exports.obj = obj; +function exportedDirectly() { } +exports.exportedDirectly = exportedDirectly; +//// [spreadExpressionContextualTypeWithNamespace_1.js] +"use strict"; +var __assign = (this && this.__assign) || function () { + __assign = Object.assign || function(t) { + for (var s, i = 1, n = arguments.length; i < n; i++) { + s = arguments[i]; + for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) + t[p] = s[p]; + } + return t; + }; + return __assign.apply(this, arguments); +}; +exports.__esModule = true; +var stuff = require("./spreadExpressionContextualTypeWithNamespace_0"); +stuff.func; +stuff.klass; +stuff.obj; +stuff.exportedDirectly; +function getStuff() { + var thing = __assign({}, stuff); + thing.func; + thing.klass; + thing.obj; + thing.exportedDirectly; + return thing; +} +getStuff().func; +getStuff().klass; +getStuff().obj; +getStuff().exportedDirectly; diff --git a/tests/baselines/reference/spreadExpressionContextualTypeWithNamespace.symbols b/tests/baselines/reference/spreadExpressionContextualTypeWithNamespace.symbols new file mode 100644 index 00000000000..2b0fff2ce95 --- /dev/null +++ b/tests/baselines/reference/spreadExpressionContextualTypeWithNamespace.symbols @@ -0,0 +1,97 @@ +=== tests/cases/compiler/spreadExpressionContextualTypeWithNamespace_0.ts === +// Repro from #44179 with some modification + +function func() {} +>func : Symbol(func, Decl(spreadExpressionContextualTypeWithNamespace_0.ts, 0, 0)) + +class klass {} +>klass : Symbol(klass, Decl(spreadExpressionContextualTypeWithNamespace_0.ts, 2, 18)) + +const obj = { x: true }; +>obj : Symbol(obj, Decl(spreadExpressionContextualTypeWithNamespace_0.ts, 4, 5)) +>x : Symbol(x, Decl(spreadExpressionContextualTypeWithNamespace_0.ts, 4, 13)) + +export { func, klass, obj }; +>func : Symbol(func, Decl(spreadExpressionContextualTypeWithNamespace_0.ts, 6, 8)) +>klass : Symbol(klass, Decl(spreadExpressionContextualTypeWithNamespace_0.ts, 6, 14)) +>obj : Symbol(obj, Decl(spreadExpressionContextualTypeWithNamespace_0.ts, 6, 21)) + +export function exportedDirectly() {} +>exportedDirectly : Symbol(exportedDirectly, Decl(spreadExpressionContextualTypeWithNamespace_0.ts, 6, 28)) + +=== tests/cases/compiler/spreadExpressionContextualTypeWithNamespace_1.ts === +import * as stuff from "./spreadExpressionContextualTypeWithNamespace_0"; +>stuff : Symbol(stuff, Decl(spreadExpressionContextualTypeWithNamespace_1.ts, 0, 6)) + +stuff.func; +>stuff.func : Symbol(stuff.func, Decl(spreadExpressionContextualTypeWithNamespace_0.ts, 6, 8)) +>stuff : Symbol(stuff, Decl(spreadExpressionContextualTypeWithNamespace_1.ts, 0, 6)) +>func : Symbol(stuff.func, Decl(spreadExpressionContextualTypeWithNamespace_0.ts, 6, 8)) + +stuff.klass; +>stuff.klass : Symbol(stuff.klass, Decl(spreadExpressionContextualTypeWithNamespace_0.ts, 6, 14)) +>stuff : Symbol(stuff, Decl(spreadExpressionContextualTypeWithNamespace_1.ts, 0, 6)) +>klass : Symbol(stuff.klass, Decl(spreadExpressionContextualTypeWithNamespace_0.ts, 6, 14)) + +stuff.obj; +>stuff.obj : Symbol(stuff.obj, Decl(spreadExpressionContextualTypeWithNamespace_0.ts, 6, 21)) +>stuff : Symbol(stuff, Decl(spreadExpressionContextualTypeWithNamespace_1.ts, 0, 6)) +>obj : Symbol(stuff.obj, Decl(spreadExpressionContextualTypeWithNamespace_0.ts, 6, 21)) + +stuff.exportedDirectly; +>stuff.exportedDirectly : Symbol(stuff.exportedDirectly, Decl(spreadExpressionContextualTypeWithNamespace_0.ts, 6, 28)) +>stuff : Symbol(stuff, Decl(spreadExpressionContextualTypeWithNamespace_1.ts, 0, 6)) +>exportedDirectly : Symbol(stuff.exportedDirectly, Decl(spreadExpressionContextualTypeWithNamespace_0.ts, 6, 28)) + +function getStuff() { +>getStuff : Symbol(getStuff, Decl(spreadExpressionContextualTypeWithNamespace_1.ts, 5, 23)) +>T : Symbol(T, Decl(spreadExpressionContextualTypeWithNamespace_1.ts, 7, 18)) + + const thing = { ...stuff }; +>thing : Symbol(thing, Decl(spreadExpressionContextualTypeWithNamespace_1.ts, 8, 7)) +>stuff : Symbol(stuff, Decl(spreadExpressionContextualTypeWithNamespace_1.ts, 0, 6)) + + thing.func; +>thing.func : Symbol(stuff.func, Decl(spreadExpressionContextualTypeWithNamespace_0.ts, 6, 8)) +>thing : Symbol(thing, Decl(spreadExpressionContextualTypeWithNamespace_1.ts, 8, 7)) +>func : Symbol(stuff.func, Decl(spreadExpressionContextualTypeWithNamespace_0.ts, 6, 8)) + + thing.klass; +>thing.klass : Symbol(stuff.klass, Decl(spreadExpressionContextualTypeWithNamespace_0.ts, 6, 14)) +>thing : Symbol(thing, Decl(spreadExpressionContextualTypeWithNamespace_1.ts, 8, 7)) +>klass : Symbol(stuff.klass, Decl(spreadExpressionContextualTypeWithNamespace_0.ts, 6, 14)) + + thing.obj; +>thing.obj : Symbol(stuff.obj, Decl(spreadExpressionContextualTypeWithNamespace_0.ts, 6, 21)) +>thing : Symbol(thing, Decl(spreadExpressionContextualTypeWithNamespace_1.ts, 8, 7)) +>obj : Symbol(stuff.obj, Decl(spreadExpressionContextualTypeWithNamespace_0.ts, 6, 21)) + + thing.exportedDirectly; +>thing.exportedDirectly : Symbol(stuff.exportedDirectly, Decl(spreadExpressionContextualTypeWithNamespace_0.ts, 6, 28)) +>thing : Symbol(thing, Decl(spreadExpressionContextualTypeWithNamespace_1.ts, 8, 7)) +>exportedDirectly : Symbol(stuff.exportedDirectly, Decl(spreadExpressionContextualTypeWithNamespace_0.ts, 6, 28)) + + return thing; +>thing : Symbol(thing, Decl(spreadExpressionContextualTypeWithNamespace_1.ts, 8, 7)) +} + +getStuff().func; +>getStuff().func : Symbol(stuff.func, Decl(spreadExpressionContextualTypeWithNamespace_0.ts, 6, 8)) +>getStuff : Symbol(getStuff, Decl(spreadExpressionContextualTypeWithNamespace_1.ts, 5, 23)) +>func : Symbol(stuff.func, Decl(spreadExpressionContextualTypeWithNamespace_0.ts, 6, 8)) + +getStuff().klass; +>getStuff().klass : Symbol(stuff.klass, Decl(spreadExpressionContextualTypeWithNamespace_0.ts, 6, 14)) +>getStuff : Symbol(getStuff, Decl(spreadExpressionContextualTypeWithNamespace_1.ts, 5, 23)) +>klass : Symbol(stuff.klass, Decl(spreadExpressionContextualTypeWithNamespace_0.ts, 6, 14)) + +getStuff().obj; +>getStuff().obj : Symbol(stuff.obj, Decl(spreadExpressionContextualTypeWithNamespace_0.ts, 6, 21)) +>getStuff : Symbol(getStuff, Decl(spreadExpressionContextualTypeWithNamespace_1.ts, 5, 23)) +>obj : Symbol(stuff.obj, Decl(spreadExpressionContextualTypeWithNamespace_0.ts, 6, 21)) + +getStuff().exportedDirectly; +>getStuff().exportedDirectly : Symbol(stuff.exportedDirectly, Decl(spreadExpressionContextualTypeWithNamespace_0.ts, 6, 28)) +>getStuff : Symbol(getStuff, Decl(spreadExpressionContextualTypeWithNamespace_1.ts, 5, 23)) +>exportedDirectly : Symbol(stuff.exportedDirectly, Decl(spreadExpressionContextualTypeWithNamespace_0.ts, 6, 28)) + diff --git a/tests/baselines/reference/spreadExpressionContextualTypeWithNamespace.types b/tests/baselines/reference/spreadExpressionContextualTypeWithNamespace.types new file mode 100644 index 00000000000..fd0caf3c8bc --- /dev/null +++ b/tests/baselines/reference/spreadExpressionContextualTypeWithNamespace.types @@ -0,0 +1,103 @@ +=== tests/cases/compiler/spreadExpressionContextualTypeWithNamespace_0.ts === +// Repro from #44179 with some modification + +function func() {} +>func : () => void + +class klass {} +>klass : klass + +const obj = { x: true }; +>obj : { x: boolean; } +>{ x: true } : { x: boolean; } +>x : boolean +>true : true + +export { func, klass, obj }; +>func : () => void +>klass : typeof klass +>obj : { x: boolean; } + +export function exportedDirectly() {} +>exportedDirectly : () => void + +=== tests/cases/compiler/spreadExpressionContextualTypeWithNamespace_1.ts === +import * as stuff from "./spreadExpressionContextualTypeWithNamespace_0"; +>stuff : typeof stuff + +stuff.func; +>stuff.func : () => void +>stuff : typeof stuff +>func : () => void + +stuff.klass; +>stuff.klass : typeof stuff.klass +>stuff : typeof stuff +>klass : typeof stuff.klass + +stuff.obj; +>stuff.obj : { x: boolean; } +>stuff : typeof stuff +>obj : { x: boolean; } + +stuff.exportedDirectly; +>stuff.exportedDirectly : () => void +>stuff : typeof stuff +>exportedDirectly : () => void + +function getStuff() { +>getStuff : () => { exportedDirectly(): void; func: () => void; klass: typeof stuff.klass; obj: { x: boolean; }; } + + const thing = { ...stuff }; +>thing : { exportedDirectly(): void; func: () => void; klass: typeof stuff.klass; obj: { x: boolean; }; } +>{ ...stuff } : { exportedDirectly(): void; func: () => void; klass: typeof stuff.klass; obj: { x: boolean; }; } +>stuff : typeof stuff + + thing.func; +>thing.func : () => void +>thing : { exportedDirectly(): void; func: () => void; klass: typeof stuff.klass; obj: { x: boolean; }; } +>func : () => void + + thing.klass; +>thing.klass : typeof stuff.klass +>thing : { exportedDirectly(): void; func: () => void; klass: typeof stuff.klass; obj: { x: boolean; }; } +>klass : typeof stuff.klass + + thing.obj; +>thing.obj : { x: boolean; } +>thing : { exportedDirectly(): void; func: () => void; klass: typeof stuff.klass; obj: { x: boolean; }; } +>obj : { x: boolean; } + + thing.exportedDirectly; +>thing.exportedDirectly : () => void +>thing : { exportedDirectly(): void; func: () => void; klass: typeof stuff.klass; obj: { x: boolean; }; } +>exportedDirectly : () => void + + return thing; +>thing : { exportedDirectly(): void; func: () => void; klass: typeof stuff.klass; obj: { x: boolean; }; } +} + +getStuff().func; +>getStuff().func : () => void +>getStuff() : { exportedDirectly(): void; func: () => void; klass: typeof stuff.klass; obj: { x: boolean; }; } +>getStuff : () => { exportedDirectly(): void; func: () => void; klass: typeof stuff.klass; obj: { x: boolean; }; } +>func : () => void + +getStuff().klass; +>getStuff().klass : typeof stuff.klass +>getStuff() : { exportedDirectly(): void; func: () => void; klass: typeof stuff.klass; obj: { x: boolean; }; } +>getStuff : () => { exportedDirectly(): void; func: () => void; klass: typeof stuff.klass; obj: { x: boolean; }; } +>klass : typeof stuff.klass + +getStuff().obj; +>getStuff().obj : { x: boolean; } +>getStuff() : { exportedDirectly(): void; func: () => void; klass: typeof stuff.klass; obj: { x: boolean; }; } +>getStuff : () => { exportedDirectly(): void; func: () => void; klass: typeof stuff.klass; obj: { x: boolean; }; } +>obj : { x: boolean; } + +getStuff().exportedDirectly; +>getStuff().exportedDirectly : () => void +>getStuff() : { exportedDirectly(): void; func: () => void; klass: typeof stuff.klass; obj: { x: boolean; }; } +>getStuff : () => { exportedDirectly(): void; func: () => void; klass: typeof stuff.klass; obj: { x: boolean; }; } +>exportedDirectly : () => void + diff --git a/tests/cases/compiler/spreadExpressionContextualTypeWithNamespace.ts b/tests/cases/compiler/spreadExpressionContextualTypeWithNamespace.ts new file mode 100644 index 00000000000..dec80cdca02 --- /dev/null +++ b/tests/cases/compiler/spreadExpressionContextualTypeWithNamespace.ts @@ -0,0 +1,33 @@ +// @filename: spreadExpressionContextualTypeWithNamespace_0.ts + +// Repro from #44179 with some modification + +function func() {} +class klass {} +const obj = { x: true }; + +export { func, klass, obj }; + +export function exportedDirectly() {} + +// @filename: spreadExpressionContextualTypeWithNamespace_1.ts +import * as stuff from "./spreadExpressionContextualTypeWithNamespace_0"; + +stuff.func; +stuff.klass; +stuff.obj; +stuff.exportedDirectly; + +function getStuff() { + const thing = { ...stuff }; + thing.func; + thing.klass; + thing.obj; + thing.exportedDirectly; + return thing; +} + +getStuff().func; +getStuff().klass; +getStuff().obj; +getStuff().exportedDirectly;