From 503fc0642e21a765942c0b9a2408d51887f46241 Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Sat, 3 Feb 2018 14:45:01 -0800 Subject: [PATCH 1/3] Fix unintended sharing of typeParameters property in SymbolLinks --- src/compiler/checker.ts | 4 ++-- src/compiler/types.ts | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 05da314a816..95af6b94747 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -8705,7 +8705,7 @@ namespace ts { const target = type.objectFlags & ObjectFlags.Instantiated ? type.target : type; const symbol = target.symbol; const links = getSymbolLinks(symbol); - let typeParameters = links.typeParameters; + let typeParameters = links.outerTypeParameters; if (!typeParameters) { // The first time an anonymous type is instantiated we compute and store a list of the type // parameters that are in scope (and therefore potentially referenced). For type literals that @@ -8716,7 +8716,7 @@ namespace ts { typeParameters = symbol.flags & SymbolFlags.TypeLiteral && !target.aliasTypeArguments ? filter(outerTypeParameters, tp => isTypeParameterPossiblyReferenced(tp, declaration)) : outerTypeParameters; - links.typeParameters = typeParameters; + links.outerTypeParameters = typeParameters; if (typeParameters.length) { links.instantiations = createMap(); links.instantiations.set(getTypeListId(typeParameters), target); diff --git a/src/compiler/types.ts b/src/compiler/types.ts index 0a1c49a93c3..829f45900d4 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -3312,6 +3312,7 @@ namespace ts { type?: Type; // Type of value symbol declaredType?: Type; // Type of class, interface, enum, type alias, or type parameter typeParameters?: TypeParameter[]; // Type parameters of type alias (undefined if non-generic) + outerTypeParameters?: TypeParameter[]; // Outer type parameters of anonymous object type inferredClassType?: Type; // Type of an inferred ES5 class instantiations?: Map; // Instantiations of generic type alias (undefined if non-generic) mapper?: TypeMapper; // Type mapper for instantiation alias From 21c397dd5a7a22b3fddbf21ec4168b343d58ab44 Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Sat, 3 Feb 2018 14:45:16 -0800 Subject: [PATCH 2/3] Add regression test --- .../compiler/typeAliasFunctionTypeSharedSymbol.ts | 12 ++++++++++++ 1 file changed, 12 insertions(+) create mode 100644 tests/cases/compiler/typeAliasFunctionTypeSharedSymbol.ts diff --git a/tests/cases/compiler/typeAliasFunctionTypeSharedSymbol.ts b/tests/cases/compiler/typeAliasFunctionTypeSharedSymbol.ts new file mode 100644 index 00000000000..de430c18bfe --- /dev/null +++ b/tests/cases/compiler/typeAliasFunctionTypeSharedSymbol.ts @@ -0,0 +1,12 @@ +// Repro from comment in #21496 + +function Mixin(Base: TBase) { + return class extends Base { + }; +} + +type Mixin = ReturnTypeOf + +type ReturnTypeOf = V extends (...args: any[])=>infer R ? R : never; + +type Crashes = number & Mixin; From 8ae5f630d483e48bcca6189d1e4215023d9eb132 Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Sat, 3 Feb 2018 14:45:25 -0800 Subject: [PATCH 3/3] Accept new baselines --- .../typeAliasFunctionTypeSharedSymbol.js | 36 +++++++++++++++++++ .../typeAliasFunctionTypeSharedSymbol.symbols | 33 +++++++++++++++++ .../typeAliasFunctionTypeSharedSymbol.types | 34 ++++++++++++++++++ 3 files changed, 103 insertions(+) create mode 100644 tests/baselines/reference/typeAliasFunctionTypeSharedSymbol.js create mode 100644 tests/baselines/reference/typeAliasFunctionTypeSharedSymbol.symbols create mode 100644 tests/baselines/reference/typeAliasFunctionTypeSharedSymbol.types diff --git a/tests/baselines/reference/typeAliasFunctionTypeSharedSymbol.js b/tests/baselines/reference/typeAliasFunctionTypeSharedSymbol.js new file mode 100644 index 00000000000..1de017c0ea2 --- /dev/null +++ b/tests/baselines/reference/typeAliasFunctionTypeSharedSymbol.js @@ -0,0 +1,36 @@ +//// [typeAliasFunctionTypeSharedSymbol.ts] +// Repro from comment in #21496 + +function Mixin(Base: TBase) { + return class extends Base { + }; +} + +type Mixin = ReturnTypeOf + +type ReturnTypeOf = V extends (...args: any[])=>infer R ? R : never; + +type Crashes = number & Mixin; + + +//// [typeAliasFunctionTypeSharedSymbol.js] +// Repro from comment in #21496 +var __extends = (this && this.__extends) || (function () { + var extendStatics = Object.setPrototypeOf || + ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || + function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; + return function (d, b) { + extendStatics(d, b); + function __() { this.constructor = d; } + d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); + }; +})(); +function Mixin(Base) { + return /** @class */ (function (_super) { + __extends(class_1, _super); + function class_1() { + return _super !== null && _super.apply(this, arguments) || this; + } + return class_1; + }(Base)); +} diff --git a/tests/baselines/reference/typeAliasFunctionTypeSharedSymbol.symbols b/tests/baselines/reference/typeAliasFunctionTypeSharedSymbol.symbols new file mode 100644 index 00000000000..b3e176f72ab --- /dev/null +++ b/tests/baselines/reference/typeAliasFunctionTypeSharedSymbol.symbols @@ -0,0 +1,33 @@ +=== tests/cases/compiler/typeAliasFunctionTypeSharedSymbol.ts === +// Repro from comment in #21496 + +function Mixin(Base: TBase) { +>Mixin : Symbol(Mixin, Decl(typeAliasFunctionTypeSharedSymbol.ts, 0, 0), Decl(typeAliasFunctionTypeSharedSymbol.ts, 5, 1)) +>TBase : Symbol(TBase, Decl(typeAliasFunctionTypeSharedSymbol.ts, 2, 15)) +>args : Symbol(args, Decl(typeAliasFunctionTypeSharedSymbol.ts, 2, 35)) +>Base : Symbol(Base, Decl(typeAliasFunctionTypeSharedSymbol.ts, 2, 57)) +>TBase : Symbol(TBase, Decl(typeAliasFunctionTypeSharedSymbol.ts, 2, 15)) + + return class extends Base { +>Base : Symbol(Base, Decl(typeAliasFunctionTypeSharedSymbol.ts, 2, 57)) + + }; +} + +type Mixin = ReturnTypeOf +>Mixin : Symbol(Mixin, Decl(typeAliasFunctionTypeSharedSymbol.ts, 0, 0), Decl(typeAliasFunctionTypeSharedSymbol.ts, 5, 1)) +>ReturnTypeOf : Symbol(ReturnTypeOf, Decl(typeAliasFunctionTypeSharedSymbol.ts, 7, 39)) +>Mixin : Symbol(Mixin, Decl(typeAliasFunctionTypeSharedSymbol.ts, 0, 0), Decl(typeAliasFunctionTypeSharedSymbol.ts, 5, 1)) + +type ReturnTypeOf = V extends (...args: any[])=>infer R ? R : never; +>ReturnTypeOf : Symbol(ReturnTypeOf, Decl(typeAliasFunctionTypeSharedSymbol.ts, 7, 39)) +>V : Symbol(V, Decl(typeAliasFunctionTypeSharedSymbol.ts, 9, 18)) +>V : Symbol(V, Decl(typeAliasFunctionTypeSharedSymbol.ts, 9, 18)) +>args : Symbol(args, Decl(typeAliasFunctionTypeSharedSymbol.ts, 9, 34)) +>R : Symbol(R, Decl(typeAliasFunctionTypeSharedSymbol.ts, 9, 56)) +>R : Symbol(R, Decl(typeAliasFunctionTypeSharedSymbol.ts, 9, 56)) + +type Crashes = number & Mixin; +>Crashes : Symbol(Crashes, Decl(typeAliasFunctionTypeSharedSymbol.ts, 9, 71)) +>Mixin : Symbol(Mixin, Decl(typeAliasFunctionTypeSharedSymbol.ts, 0, 0), Decl(typeAliasFunctionTypeSharedSymbol.ts, 5, 1)) + diff --git a/tests/baselines/reference/typeAliasFunctionTypeSharedSymbol.types b/tests/baselines/reference/typeAliasFunctionTypeSharedSymbol.types new file mode 100644 index 00000000000..9f69ad8f864 --- /dev/null +++ b/tests/baselines/reference/typeAliasFunctionTypeSharedSymbol.types @@ -0,0 +1,34 @@ +=== tests/cases/compiler/typeAliasFunctionTypeSharedSymbol.ts === +// Repro from comment in #21496 + +function Mixin(Base: TBase) { +>Mixin : {}>(Base: TBase) => { new (...args: any[]): (Anonymous class); prototype: Mixin.(Anonymous class); } & TBase +>TBase : TBase +>args : any[] +>Base : TBase +>TBase : TBase + + return class extends Base { +>class extends Base { } : { new (...args: any[]): (Anonymous class); prototype: Mixin.(Anonymous class); } & TBase +>Base : {} + + }; +} + +type Mixin = ReturnTypeOf +>Mixin : { new (...args: any[]): Mixin {}>.(Anonymous class); prototype: Mixin.(Anonymous class); } & (new (...args: any[]) => {}) +>ReturnTypeOf : ReturnTypeOf +>Mixin : {}>(Base: TBase) => { new (...args: any[]): (Anonymous class); prototype: Mixin.(Anonymous class); } & TBase + +type ReturnTypeOf = V extends (...args: any[])=>infer R ? R : never; +>ReturnTypeOf : ReturnTypeOf +>V : V +>V : V +>args : any[] +>R : R +>R : R + +type Crashes = number & Mixin; +>Crashes : Crashes +>Mixin : { new (...args: any[]): Mixin {}>.(Anonymous class); prototype: Mixin.(Anonymous class); } & (new (...args: any[]) => {}) +