Refactor widening

This commit is contained in:
Ron Buckton 2017-10-20 22:52:20 -07:00
parent 55e63a8288
commit 3341e07e67
10 changed files with 1036 additions and 30 deletions

View file

@ -5479,8 +5479,8 @@ namespace ts {
* Indicates whether a declaration name is definitely late-bindable.
* A declaration name is only late-bindable if:
* - It is a `ComputedPropertyName`.
* - Its expression is either an `Identifier` or is a `PropertyAccessExpression` consisting only of
* other `PropertyAccessExpression` or `Identifier` nodes.
* - Its expression is an `Identifier` or either a `PropertyAccessExpression` an
* `ElementAccessExpression` consisting only of these same three types of nodes.
* - The type of its expression is a string or numeric literal type, or is a `unique symbol` type.
*/
function isLateBindableName(node: DeclarationName): node is LateBoundName {
@ -8299,13 +8299,6 @@ namespace ts {
return links.resolvedType;
}
function getWidenedTypeOfUniqueESSymbolType(type: Type): Type {
return type.flags & TypeFlags.UniqueESSymbol ? esSymbolType :
type.flags & TypeFlags.Union ? getUnionType(sameMap((<UnionType>type).types, getWidenedTypeOfUniqueESSymbolType)) :
type.flags & TypeFlags.Intersection ? getIntersectionType(sameMap((<IntersectionType>type).types, getWidenedTypeOfUniqueESSymbolType)) :
type;
}
function createUniqueESSymbolType(symbol: Symbol) {
const type = <UniqueESSymbolType>createType(TypeFlags.UniqueESSymbol);
type.symbol = symbol;
@ -10569,12 +10562,67 @@ namespace ts {
type;
}
function getWidenedLiteralLikeMapper(wideningFlags: TypeFlags) {
return !(wideningFlags & TypeFlags.UniqueESSymbol) ? getWidenedLiteralType :
!(wideningFlags & TypeFlags.WidenableLiteral) ? getWidenedUniqueESSymbolType :
getWidenedLiteralLikeType;
}
/**
* Widens string literal, number literal, boolean literal, enum literal, and unique symbol
* types, as well as unions of the same.
*
* We don't always want to widen literals in all of the same places we widen unique symbol
* types, and vice versa. However, there are some cases where we do widen both sets of
* types at the same time.
*
* In general, this function should not be called directly. Instead it should be called
* through either `getWidenedLiteralType` (which does not widen unique symbol types),
* `getWidenedUniqueESSymbolType` (which only widenes unique symbol types), or
* `getWidenedLiteralLikeType` (which widens both).
*/
function getWidenedLiteralLikeTypeWorker(type: Type, wideningFlags: TypeFlags): Type {
return type.flags & wideningFlags & TypeFlags.EnumLiteral ? getBaseTypeOfEnumLiteralType(<LiteralType>type) :
type.flags & wideningFlags & TypeFlags.StringLiteral && type.flags & TypeFlags.FreshLiteral ? stringType :
type.flags & wideningFlags & TypeFlags.NumberLiteral && type.flags & TypeFlags.FreshLiteral ? numberType :
type.flags & wideningFlags & TypeFlags.BooleanLiteral ? booleanType :
type.flags & wideningFlags & TypeFlags.UniqueESSymbol ? esSymbolType :
type.flags & TypeFlags.Union ? getUnionType(sameMap((<UnionType>type).types, getWidenedLiteralLikeMapper(wideningFlags))) :
type;
}
/**
* Widens string literal, number literal, boolean literal, enum literal, and unique symbol
* types, as well as unions of the same.
*/
function getWidenedLiteralLikeType(type: Type): Type {
return getWidenedLiteralLikeTypeWorker(type, TypeFlags.WidenableLiteralLike);
}
/**
* Widens string literal, number literal, boolean literal, and enum literal types, as well
* as unions of the same.
*/
function getWidenedLiteralType(type: Type): Type {
return type.flags & TypeFlags.EnumLiteral ? getBaseTypeOfEnumLiteralType(<LiteralType>type) :
type.flags & TypeFlags.StringLiteral && type.flags & TypeFlags.FreshLiteral ? stringType :
type.flags & TypeFlags.NumberLiteral && type.flags & TypeFlags.FreshLiteral ? numberType :
type.flags & TypeFlags.BooleanLiteral ? booleanType :
type.flags & TypeFlags.Union ? getUnionType(sameMap((<UnionType>type).types, getWidenedLiteralType)) :
return getWidenedLiteralLikeTypeWorker(type, TypeFlags.WidenableLiteral);
}
/**
* Widens unique symbol types and unions of unique symbol types.
*/
function getWidenedUniqueESSymbolType(type: Type): Type {
return getWidenedLiteralLikeTypeWorker(type, TypeFlags.UniqueESSymbol);
}
/**
* Widens a literal-like type when the contextual type is not literal-like.
*/
function getWidenedLiteralLikeTypeForContextualType(type: Type, contextualType: Type) {
const widenLiterals = !isLiteralContextualType(contextualType);
const widenSymbols = !isUniqueESSymbolContextualType(contextualType);
return widenLiterals && widenSymbols ? getWidenedLiteralLikeType(type) :
widenLiterals ? getWidenedLiteralType(type) :
widenSymbols ? getWidenedUniqueESSymbolType(type) :
type;
}
@ -11341,7 +11389,8 @@ namespace ts {
}
}
}
return getWidenedTypeOfUniqueESSymbolType(inferredType);
return getWidenedUniqueESSymbolType(inferredType);
}
function getDefaultTypeArgumentType(isInJavaScriptFile: boolean): Type {
@ -13986,7 +14035,7 @@ namespace ts {
else {
const elementContextualType = getContextualTypeForElementExpression(contextualType, index);
const type = checkExpressionForMutableLocation(e, checkMode, elementContextualType);
elementTypes.push(getWidenedTypeOfUniqueESSymbolType(type));
elementTypes.push(type);
}
hasSpreadElement = hasSpreadElement || e.kind === SyntaxKind.SpreadElement;
}
@ -17426,7 +17475,7 @@ namespace ts {
}
// widen 'unique symbol' types when we infer the return type.
type = getWidenedTypeOfUniqueESSymbolType(type);
type = getWidenedUniqueESSymbolType(type);
}
else {
let types: Type[];
@ -17462,7 +17511,7 @@ namespace ts {
type = getUnionType(types, /*subtypeReduction*/ true);
// widen 'unique symbol' types when we infer the return type.
type = getWidenedTypeOfUniqueESSymbolType(type);
type = getWidenedUniqueESSymbolType(type);
if (functionFlags & FunctionFlags.Generator) { // AsyncGenerator function or Generator function
type = functionFlags & FunctionFlags.Async
@ -18592,13 +18641,17 @@ namespace ts {
return false;
}
function isUniqueESSymbolContextualType(contextualType: Type) {
return contextualType ? maybeTypeOfKind(contextualType, TypeFlags.UniqueESSymbol) : false;
}
function checkExpressionForMutableLocation(node: Expression, checkMode: CheckMode, contextualType?: Type): Type {
if (arguments.length === 2) {
contextualType = getContextualType(node);
}
const type = checkExpression(node, checkMode);
const shouldWiden = isTypeAssertion(node) || isLiteralContextualType(contextualType);
return shouldWiden ? type : getWidenedLiteralType(type);
return isTypeAssertion(node) ? type :
getWidenedLiteralLikeTypeForContextualType(type, contextualType);
}
function checkPropertyAssignment(node: PropertyAssignment, checkMode?: CheckMode): Type {
@ -24392,8 +24445,7 @@ namespace ts {
function isLiteralDynamicName(name: ComputedPropertyName) {
name = getParseTreeNode(name, isComputedPropertyName);
if (name) {
const nameType = checkComputedPropertyName(name);
return (nameType.flags & TypeFlags.StringOrNumberLiteralOrUnique) !== 0;
return isLateBindableName(name);
}
return false;
}

View file

@ -3246,8 +3246,8 @@ namespace ts {
/* @internal */
Nullable = Undefined | Null,
Literal = StringLiteral | NumberLiteral | BooleanLiteral | UniqueESSymbol,
Unit = Literal | Nullable,
Literal = StringLiteral | NumberLiteral | BooleanLiteral,
Unit = Literal | UniqueESSymbol | Nullable,
StringOrNumberLiteral = StringLiteral | NumberLiteral,
/* @internal */
StringOrNumberLiteralOrUnique = StringOrNumberLiteral | UniqueESSymbol,
@ -3257,7 +3257,7 @@ namespace ts {
/* @internal */
Intrinsic = Any | String | Number | Boolean | BooleanLiteral | ESSymbol | Void | Undefined | Null | Never | NonPrimitive,
/* @internal */
Primitive = String | Number | Boolean | Enum | EnumLiteral | ESSymbol | Void | Undefined | Null | Literal,
Primitive = String | Number | Boolean | Enum | EnumLiteral | ESSymbol | Void | Undefined | Null | Literal | UniqueESSymbol,
StringLike = String | StringLiteral | Index,
NumberLike = Number | NumberLiteral | Enum,
BooleanLike = Boolean | BooleanLiteral,
@ -3275,7 +3275,10 @@ namespace ts {
/* @internal */
RequiresWidening = ContainsWideningType | ContainsObjectLiteral,
/* @internal */
PropagatingFlags = ContainsWideningType | ContainsObjectLiteral | ContainsAnyFunctionType
PropagatingFlags = ContainsWideningType | ContainsObjectLiteral | ContainsAnyFunctionType,
WidenableLiteral = Literal | EnumLiteral,
WidenableLiteralLike = WidenableLiteral | UniqueESSymbol,
}
export type DestructuringPattern = BindingPattern | ObjectLiteralExpression | ArrayLiteralExpression;

View file

@ -135,7 +135,20 @@ export const o1_c4 = o1[c4];
export const o1_c5 = o1[c5];
export const o1_s2 = o1[s2];
export const o2: T0 = o1;
export const o2: T0 = o1;
// recursive declarations
declare const rI: RI;
interface RI {
x: "a";
[rI.x]: "b";
}
declare const rC: RC;
declare class RC {
x: "a";
[rC.x]: "b";
}
//// [module.js]
"use strict";

View file

@ -442,3 +442,35 @@ export const o2: T0 = o1;
>T0 : Symbol(T0, Decl(main.ts, 0, 20))
>o1 : Symbol(o1, Decl(main.ts, 101, 12))
// recursive declarations
declare const rI: RI;
>rI : Symbol(rI, Decl(main.ts, 115, 13))
>RI : Symbol(RI, Decl(main.ts, 115, 21))
interface RI {
>RI : Symbol(RI, Decl(main.ts, 115, 21))
x: "a";
>x : Symbol(RI.x, Decl(main.ts, 116, 14))
[rI.x]: "b";
>rI.x : Symbol(RI.x, Decl(main.ts, 116, 14))
>rI : Symbol(rI, Decl(main.ts, 115, 13))
>x : Symbol(RI.x, Decl(main.ts, 116, 14))
}
declare const rC: RC;
>rC : Symbol(rC, Decl(main.ts, 121, 13))
>RC : Symbol(RC, Decl(main.ts, 121, 21))
declare class RC {
>RC : Symbol(RC, Decl(main.ts, 121, 21))
x: "a";
>x : Symbol(RC.x, Decl(main.ts, 122, 18))
[rC.x]: "b";
>rC.x : Symbol(RC.x, Decl(main.ts, 122, 18))
>rC : Symbol(rC, Decl(main.ts, 121, 13))
>x : Symbol(RC.x, Decl(main.ts, 122, 18))
}

View file

@ -518,3 +518,35 @@ export const o2: T0 = o1;
>T0 : T0
>o1 : { [c4]: number; [c5]: string; [s2]: boolean; }
// recursive declarations
declare const rI: RI;
>rI : RI
>RI : RI
interface RI {
>RI : RI
x: "a";
>x : "a"
[rI.x]: "b";
>rI.x : "a"
>rI : RI
>x : "a"
}
declare const rC: RC;
>rC : RC
>RC : RC
declare class RC {
>RC : RC
x: "a";
>x : "a"
[rC.x]: "b";
>rC.x : "a"
>rC : RC
>x : "a"
}

View file

@ -111,7 +111,91 @@ const constInitToLReadonlyNestedTypeWithIndexedAccess: L["nested"]["readonlyNest
// type argument inference
const promiseForConstCall = Promise.resolve(constCall);
const arrayOfConstCall = [constCall];
const arrayOfConstCall = [constCall];
// unique symbol widening in expressions
declare const s: unique symbol;
declare namespace N { const s: unique symbol; }
declare const o: { [s]: "a", [N.s]: "b" };
declare function f<T>(x: T): T;
declare function g(x: typeof s): void;
declare function g(x: typeof N.s): void;
// widening positions
// argument inference
f(s);
f(N.s);
f(N["s"]);
// array literal elements
[s];
[N.s];
[N["s"]];
// property assignments
const o2 = {
a: s,
b: N.s,
c: N["s"]
};
// property initializers
class C0 {
static readonly a = s;
static readonly b = N.s;
static readonly c = N["s"];
static d = s;
static e = N.s;
static f = N["s"];
readonly a = s;
readonly b = N.s;
readonly c = N["s"];
d = s;
e = N.s;
f = N["s"];
}
// non-widening positions
// element access
o[s];
o[N.s];
o[N["s"]];
// arguments (no-inference)
f<typeof s>(s);
f<typeof N.s>(N.s);
f<typeof N.s>(N["s"]);
g(s);
g(N.s);
g(N["s"]);
// falsy expressions
s || "";
N.s || "";
N["s"] || "";
// conditionals
Math.random() * 2 ? s : "a";
Math.random() * 2 ? N.s : "a";
Math.random() * 2 ? N["s"] : "a";
// computed property names
({
[s]: "a",
[N.s]: "b",
});
class C1 {
static [s]: "a";
static [N.s]: "b";
[s]: "a";
[N.s]: "b";
}
//// [uniqueSymbols.js]
// declarations with call initializer
@ -192,6 +276,65 @@ const constInitToLReadonlyNestedTypeWithIndexedAccess = l.nested.readonlyNestedT
// type argument inference
const promiseForConstCall = Promise.resolve(constCall);
const arrayOfConstCall = [constCall];
// widening positions
// argument inference
f(s);
f(N.s);
f(N["s"]);
// array literal elements
[s];
[N.s];
[N["s"]];
// property assignments
const o2 = {
a: s,
b: N.s,
c: N["s"]
};
// property initializers
class C0 {
constructor() {
this.a = s;
this.b = N.s;
this.c = N["s"];
this.d = s;
this.e = N.s;
this.f = N["s"];
}
}
C0.a = s;
C0.b = N.s;
C0.c = N["s"];
C0.d = s;
C0.e = N.s;
C0.f = N["s"];
// non-widening positions
// element access
o[s];
o[N.s];
o[N["s"]];
// arguments (no-inference)
f(s);
f(N.s);
f(N["s"]);
g(s);
g(N.s);
g(N["s"]);
// falsy expressions
s || "";
N.s || "";
N["s"] || "";
// conditionals
Math.random() * 2 ? s : "a";
Math.random() * 2 ? N.s : "a";
Math.random() * 2 ? N["s"] : "a";
// computed property names
({
[s]: "a",
[N.s]: "b",
});
class C1 {
}
//// [uniqueSymbols.d.ts]
@ -273,3 +416,39 @@ declare const constInitToLReadonlyTypeWithIndexedAccess: L["readonlyType"];
declare const constInitToLReadonlyNestedTypeWithIndexedAccess: L["nested"]["readonlyNestedType"];
declare const promiseForConstCall: Promise<symbol>;
declare const arrayOfConstCall: symbol[];
declare const s: unique symbol;
declare namespace N {
const s: unique symbol;
}
declare const o: {
[s]: "a";
[N.s]: "b";
};
declare function f<T>(x: T): T;
declare function g(x: typeof s): void;
declare function g(x: typeof N.s): void;
declare const o2: {
a: symbol;
b: symbol;
c: symbol;
};
declare class C0 {
static readonly a: symbol;
static readonly b: symbol;
static readonly c: symbol;
static d: symbol;
static e: symbol;
static f: symbol;
readonly a: symbol;
readonly b: symbol;
readonly c: symbol;
d: symbol;
e: symbol;
f: symbol;
}
declare class C1 {
static [s]: "a";
static [N.s]: "b";
[s]: "a";
[N.s]: "b";
}

View file

@ -396,3 +396,275 @@ const arrayOfConstCall = [constCall];
>arrayOfConstCall : Symbol(arrayOfConstCall, Decl(uniqueSymbols.ts, 112, 5))
>constCall : Symbol(constCall, Decl(uniqueSymbols.ts, 1, 5))
// unique symbol widening in expressions
declare const s: unique symbol;
>s : Symbol(s, Decl(uniqueSymbols.ts, 115, 13))
declare namespace N { const s: unique symbol; }
>N : Symbol(N, Decl(uniqueSymbols.ts, 115, 31))
>s : Symbol(s, Decl(uniqueSymbols.ts, 116, 27))
declare const o: { [s]: "a", [N.s]: "b" };
>o : Symbol(o, Decl(uniqueSymbols.ts, 117, 13))
>s : Symbol(s, Decl(uniqueSymbols.ts, 115, 13))
>N.s : Symbol(N.s, Decl(uniqueSymbols.ts, 116, 27))
>N : Symbol(N, Decl(uniqueSymbols.ts, 115, 31))
>s : Symbol(N.s, Decl(uniqueSymbols.ts, 116, 27))
declare function f<T>(x: T): T;
>f : Symbol(f, Decl(uniqueSymbols.ts, 117, 42))
>T : Symbol(T, Decl(uniqueSymbols.ts, 118, 19))
>x : Symbol(x, Decl(uniqueSymbols.ts, 118, 22))
>T : Symbol(T, Decl(uniqueSymbols.ts, 118, 19))
>T : Symbol(T, Decl(uniqueSymbols.ts, 118, 19))
declare function g(x: typeof s): void;
>g : Symbol(g, Decl(uniqueSymbols.ts, 118, 31), Decl(uniqueSymbols.ts, 119, 38))
>x : Symbol(x, Decl(uniqueSymbols.ts, 119, 19))
>s : Symbol(s, Decl(uniqueSymbols.ts, 115, 13))
declare function g(x: typeof N.s): void;
>g : Symbol(g, Decl(uniqueSymbols.ts, 118, 31), Decl(uniqueSymbols.ts, 119, 38))
>x : Symbol(x, Decl(uniqueSymbols.ts, 120, 19))
>N.s : Symbol(N.s, Decl(uniqueSymbols.ts, 116, 27))
>N : Symbol(N, Decl(uniqueSymbols.ts, 115, 31))
>s : Symbol(N.s, Decl(uniqueSymbols.ts, 116, 27))
// widening positions
// argument inference
f(s);
>f : Symbol(f, Decl(uniqueSymbols.ts, 117, 42))
>s : Symbol(s, Decl(uniqueSymbols.ts, 115, 13))
f(N.s);
>f : Symbol(f, Decl(uniqueSymbols.ts, 117, 42))
>N.s : Symbol(N.s, Decl(uniqueSymbols.ts, 116, 27))
>N : Symbol(N, Decl(uniqueSymbols.ts, 115, 31))
>s : Symbol(N.s, Decl(uniqueSymbols.ts, 116, 27))
f(N["s"]);
>f : Symbol(f, Decl(uniqueSymbols.ts, 117, 42))
>N : Symbol(N, Decl(uniqueSymbols.ts, 115, 31))
>"s" : Symbol(N.s, Decl(uniqueSymbols.ts, 116, 27))
// array literal elements
[s];
>s : Symbol(s, Decl(uniqueSymbols.ts, 115, 13))
[N.s];
>N.s : Symbol(N.s, Decl(uniqueSymbols.ts, 116, 27))
>N : Symbol(N, Decl(uniqueSymbols.ts, 115, 31))
>s : Symbol(N.s, Decl(uniqueSymbols.ts, 116, 27))
[N["s"]];
>N : Symbol(N, Decl(uniqueSymbols.ts, 115, 31))
>"s" : Symbol(N.s, Decl(uniqueSymbols.ts, 116, 27))
// property assignments
const o2 = {
>o2 : Symbol(o2, Decl(uniqueSymbols.ts, 134, 5))
a: s,
>a : Symbol(a, Decl(uniqueSymbols.ts, 134, 12))
>s : Symbol(s, Decl(uniqueSymbols.ts, 115, 13))
b: N.s,
>b : Symbol(b, Decl(uniqueSymbols.ts, 135, 9))
>N.s : Symbol(N.s, Decl(uniqueSymbols.ts, 116, 27))
>N : Symbol(N, Decl(uniqueSymbols.ts, 115, 31))
>s : Symbol(N.s, Decl(uniqueSymbols.ts, 116, 27))
c: N["s"]
>c : Symbol(c, Decl(uniqueSymbols.ts, 136, 11))
>N : Symbol(N, Decl(uniqueSymbols.ts, 115, 31))
>"s" : Symbol(N.s, Decl(uniqueSymbols.ts, 116, 27))
};
// property initializers
class C0 {
>C0 : Symbol(C0, Decl(uniqueSymbols.ts, 138, 2))
static readonly a = s;
>a : Symbol(C0.a, Decl(uniqueSymbols.ts, 141, 10))
>s : Symbol(s, Decl(uniqueSymbols.ts, 115, 13))
static readonly b = N.s;
>b : Symbol(C0.b, Decl(uniqueSymbols.ts, 142, 26))
>N.s : Symbol(N.s, Decl(uniqueSymbols.ts, 116, 27))
>N : Symbol(N, Decl(uniqueSymbols.ts, 115, 31))
>s : Symbol(N.s, Decl(uniqueSymbols.ts, 116, 27))
static readonly c = N["s"];
>c : Symbol(C0.c, Decl(uniqueSymbols.ts, 143, 28))
>N : Symbol(N, Decl(uniqueSymbols.ts, 115, 31))
>"s" : Symbol(N.s, Decl(uniqueSymbols.ts, 116, 27))
static d = s;
>d : Symbol(C0.d, Decl(uniqueSymbols.ts, 144, 31))
>s : Symbol(s, Decl(uniqueSymbols.ts, 115, 13))
static e = N.s;
>e : Symbol(C0.e, Decl(uniqueSymbols.ts, 146, 17))
>N.s : Symbol(N.s, Decl(uniqueSymbols.ts, 116, 27))
>N : Symbol(N, Decl(uniqueSymbols.ts, 115, 31))
>s : Symbol(N.s, Decl(uniqueSymbols.ts, 116, 27))
static f = N["s"];
>f : Symbol(C0.f, Decl(uniqueSymbols.ts, 147, 19))
>N : Symbol(N, Decl(uniqueSymbols.ts, 115, 31))
>"s" : Symbol(N.s, Decl(uniqueSymbols.ts, 116, 27))
readonly a = s;
>a : Symbol(C0.a, Decl(uniqueSymbols.ts, 148, 22))
>s : Symbol(s, Decl(uniqueSymbols.ts, 115, 13))
readonly b = N.s;
>b : Symbol(C0.b, Decl(uniqueSymbols.ts, 150, 19))
>N.s : Symbol(N.s, Decl(uniqueSymbols.ts, 116, 27))
>N : Symbol(N, Decl(uniqueSymbols.ts, 115, 31))
>s : Symbol(N.s, Decl(uniqueSymbols.ts, 116, 27))
readonly c = N["s"];
>c : Symbol(C0.c, Decl(uniqueSymbols.ts, 151, 21))
>N : Symbol(N, Decl(uniqueSymbols.ts, 115, 31))
>"s" : Symbol(N.s, Decl(uniqueSymbols.ts, 116, 27))
d = s;
>d : Symbol(C0.d, Decl(uniqueSymbols.ts, 152, 24))
>s : Symbol(s, Decl(uniqueSymbols.ts, 115, 13))
e = N.s;
>e : Symbol(C0.e, Decl(uniqueSymbols.ts, 154, 10))
>N.s : Symbol(N.s, Decl(uniqueSymbols.ts, 116, 27))
>N : Symbol(N, Decl(uniqueSymbols.ts, 115, 31))
>s : Symbol(N.s, Decl(uniqueSymbols.ts, 116, 27))
f = N["s"];
>f : Symbol(C0.f, Decl(uniqueSymbols.ts, 155, 12))
>N : Symbol(N, Decl(uniqueSymbols.ts, 115, 31))
>"s" : Symbol(N.s, Decl(uniqueSymbols.ts, 116, 27))
}
// non-widening positions
// element access
o[s];
>o : Symbol(o, Decl(uniqueSymbols.ts, 117, 13))
>s : Symbol(s, Decl(uniqueSymbols.ts, 115, 13))
o[N.s];
>o : Symbol(o, Decl(uniqueSymbols.ts, 117, 13))
>N.s : Symbol(N.s, Decl(uniqueSymbols.ts, 116, 27))
>N : Symbol(N, Decl(uniqueSymbols.ts, 115, 31))
>s : Symbol(N.s, Decl(uniqueSymbols.ts, 116, 27))
o[N["s"]];
>o : Symbol(o, Decl(uniqueSymbols.ts, 117, 13))
>N : Symbol(N, Decl(uniqueSymbols.ts, 115, 31))
>"s" : Symbol(N.s, Decl(uniqueSymbols.ts, 116, 27))
// arguments (no-inference)
f<typeof s>(s);
>f : Symbol(f, Decl(uniqueSymbols.ts, 117, 42))
>s : Symbol(s, Decl(uniqueSymbols.ts, 115, 13))
>s : Symbol(s, Decl(uniqueSymbols.ts, 115, 13))
f<typeof N.s>(N.s);
>f : Symbol(f, Decl(uniqueSymbols.ts, 117, 42))
>N.s : Symbol(N.s, Decl(uniqueSymbols.ts, 116, 27))
>N : Symbol(N, Decl(uniqueSymbols.ts, 115, 31))
>s : Symbol(N.s, Decl(uniqueSymbols.ts, 116, 27))
>N.s : Symbol(N.s, Decl(uniqueSymbols.ts, 116, 27))
>N : Symbol(N, Decl(uniqueSymbols.ts, 115, 31))
>s : Symbol(N.s, Decl(uniqueSymbols.ts, 116, 27))
f<typeof N.s>(N["s"]);
>f : Symbol(f, Decl(uniqueSymbols.ts, 117, 42))
>N.s : Symbol(N.s, Decl(uniqueSymbols.ts, 116, 27))
>N : Symbol(N, Decl(uniqueSymbols.ts, 115, 31))
>s : Symbol(N.s, Decl(uniqueSymbols.ts, 116, 27))
>N : Symbol(N, Decl(uniqueSymbols.ts, 115, 31))
>"s" : Symbol(N.s, Decl(uniqueSymbols.ts, 116, 27))
g(s);
>g : Symbol(g, Decl(uniqueSymbols.ts, 118, 31), Decl(uniqueSymbols.ts, 119, 38))
>s : Symbol(s, Decl(uniqueSymbols.ts, 115, 13))
g(N.s);
>g : Symbol(g, Decl(uniqueSymbols.ts, 118, 31), Decl(uniqueSymbols.ts, 119, 38))
>N.s : Symbol(N.s, Decl(uniqueSymbols.ts, 116, 27))
>N : Symbol(N, Decl(uniqueSymbols.ts, 115, 31))
>s : Symbol(N.s, Decl(uniqueSymbols.ts, 116, 27))
g(N["s"]);
>g : Symbol(g, Decl(uniqueSymbols.ts, 118, 31), Decl(uniqueSymbols.ts, 119, 38))
>N : Symbol(N, Decl(uniqueSymbols.ts, 115, 31))
>"s" : Symbol(N.s, Decl(uniqueSymbols.ts, 116, 27))
// falsy expressions
s || "";
>s : Symbol(s, Decl(uniqueSymbols.ts, 115, 13))
N.s || "";
>N.s : Symbol(N.s, Decl(uniqueSymbols.ts, 116, 27))
>N : Symbol(N, Decl(uniqueSymbols.ts, 115, 31))
>s : Symbol(N.s, Decl(uniqueSymbols.ts, 116, 27))
N["s"] || "";
>N : Symbol(N, Decl(uniqueSymbols.ts, 115, 31))
>"s" : Symbol(N.s, Decl(uniqueSymbols.ts, 116, 27))
// conditionals
Math.random() * 2 ? s : "a";
>Math.random : Symbol(Math.random, Decl(lib.es5.d.ts, --, --))
>Math : Symbol(Math, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --), Decl(lib.es2015.core.d.ts, --, --))
>random : Symbol(Math.random, Decl(lib.es5.d.ts, --, --))
>s : Symbol(s, Decl(uniqueSymbols.ts, 115, 13))
Math.random() * 2 ? N.s : "a";
>Math.random : Symbol(Math.random, Decl(lib.es5.d.ts, --, --))
>Math : Symbol(Math, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --), Decl(lib.es2015.core.d.ts, --, --))
>random : Symbol(Math.random, Decl(lib.es5.d.ts, --, --))
>N.s : Symbol(N.s, Decl(uniqueSymbols.ts, 116, 27))
>N : Symbol(N, Decl(uniqueSymbols.ts, 115, 31))
>s : Symbol(N.s, Decl(uniqueSymbols.ts, 116, 27))
Math.random() * 2 ? N["s"] : "a";
>Math.random : Symbol(Math.random, Decl(lib.es5.d.ts, --, --))
>Math : Symbol(Math, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --), Decl(lib.es2015.core.d.ts, --, --))
>random : Symbol(Math.random, Decl(lib.es5.d.ts, --, --))
>N : Symbol(N, Decl(uniqueSymbols.ts, 115, 31))
>"s" : Symbol(N.s, Decl(uniqueSymbols.ts, 116, 27))
// computed property names
({
[s]: "a",
>s : Symbol(s, Decl(uniqueSymbols.ts, 115, 13))
[N.s]: "b",
>N.s : Symbol(N.s, Decl(uniqueSymbols.ts, 116, 27))
>N : Symbol(N, Decl(uniqueSymbols.ts, 115, 31))
>s : Symbol(N.s, Decl(uniqueSymbols.ts, 116, 27))
});
class C1 {
>C1 : Symbol(C1, Decl(uniqueSymbols.ts, 188, 3))
static [s]: "a";
>s : Symbol(s, Decl(uniqueSymbols.ts, 115, 13))
static [N.s]: "b";
>N.s : Symbol(N.s, Decl(uniqueSymbols.ts, 116, 27))
>N : Symbol(N, Decl(uniqueSymbols.ts, 115, 31))
>s : Symbol(N.s, Decl(uniqueSymbols.ts, 116, 27))
[s]: "a";
>s : Symbol(s, Decl(uniqueSymbols.ts, 115, 13))
[N.s]: "b";
>N.s : Symbol(N.s, Decl(uniqueSymbols.ts, 116, 27))
>N : Symbol(N, Decl(uniqueSymbols.ts, 115, 31))
>s : Symbol(N.s, Decl(uniqueSymbols.ts, 116, 27))
}

View file

@ -414,3 +414,329 @@ const arrayOfConstCall = [constCall];
>[constCall] : symbol[]
>constCall : unique symbol
// unique symbol widening in expressions
declare const s: unique symbol;
>s : unique symbol
declare namespace N { const s: unique symbol; }
>N : typeof N
>s : unique symbol
declare const o: { [s]: "a", [N.s]: "b" };
>o : { [s]: "a"; [N.s]: "b"; }
>s : unique symbol
>N.s : unique symbol
>N : typeof N
>s : unique symbol
declare function f<T>(x: T): T;
>f : <T>(x: T) => T
>T : T
>x : T
>T : T
>T : T
declare function g(x: typeof s): void;
>g : { (x: unique symbol): void; (x: unique symbol): void; }
>x : unique symbol
>s : unique symbol
declare function g(x: typeof N.s): void;
>g : { (x: unique symbol): void; (x: unique symbol): void; }
>x : unique symbol
>N.s : unique symbol
>N : typeof N
>s : unique symbol
// widening positions
// argument inference
f(s);
>f(s) : symbol
>f : <T>(x: T) => T
>s : unique symbol
f(N.s);
>f(N.s) : symbol
>f : <T>(x: T) => T
>N.s : unique symbol
>N : typeof N
>s : unique symbol
f(N["s"]);
>f(N["s"]) : symbol
>f : <T>(x: T) => T
>N["s"] : unique symbol
>N : typeof N
>"s" : "s"
// array literal elements
[s];
>[s] : symbol[]
>s : unique symbol
[N.s];
>[N.s] : symbol[]
>N.s : unique symbol
>N : typeof N
>s : unique symbol
[N["s"]];
>[N["s"]] : symbol[]
>N["s"] : unique symbol
>N : typeof N
>"s" : "s"
// property assignments
const o2 = {
>o2 : { a: symbol; b: symbol; c: symbol; }
>{ a: s, b: N.s, c: N["s"]} : { a: symbol; b: symbol; c: symbol; }
a: s,
>a : symbol
>s : unique symbol
b: N.s,
>b : symbol
>N.s : unique symbol
>N : typeof N
>s : unique symbol
c: N["s"]
>c : symbol
>N["s"] : unique symbol
>N : typeof N
>"s" : "s"
};
// property initializers
class C0 {
>C0 : C0
static readonly a = s;
>a : symbol
>s : unique symbol
static readonly b = N.s;
>b : symbol
>N.s : unique symbol
>N : typeof N
>s : unique symbol
static readonly c = N["s"];
>c : symbol
>N["s"] : unique symbol
>N : typeof N
>"s" : "s"
static d = s;
>d : symbol
>s : unique symbol
static e = N.s;
>e : symbol
>N.s : unique symbol
>N : typeof N
>s : unique symbol
static f = N["s"];
>f : symbol
>N["s"] : unique symbol
>N : typeof N
>"s" : "s"
readonly a = s;
>a : symbol
>s : unique symbol
readonly b = N.s;
>b : symbol
>N.s : unique symbol
>N : typeof N
>s : unique symbol
readonly c = N["s"];
>c : symbol
>N["s"] : unique symbol
>N : typeof N
>"s" : "s"
d = s;
>d : symbol
>s : unique symbol
e = N.s;
>e : symbol
>N.s : unique symbol
>N : typeof N
>s : unique symbol
f = N["s"];
>f : symbol
>N["s"] : unique symbol
>N : typeof N
>"s" : "s"
}
// non-widening positions
// element access
o[s];
>o[s] : "a"
>o : { [s]: "a"; [N.s]: "b"; }
>s : unique symbol
o[N.s];
>o[N.s] : "b"
>o : { [s]: "a"; [N.s]: "b"; }
>N.s : unique symbol
>N : typeof N
>s : unique symbol
o[N["s"]];
>o[N["s"]] : "b"
>o : { [s]: "a"; [N.s]: "b"; }
>N["s"] : unique symbol
>N : typeof N
>"s" : "s"
// arguments (no-inference)
f<typeof s>(s);
>f<typeof s>(s) : unique symbol
>f : <T>(x: T) => T
>s : unique symbol
>s : unique symbol
f<typeof N.s>(N.s);
>f<typeof N.s>(N.s) : unique symbol
>f : <T>(x: T) => T
>N.s : unique symbol
>N : typeof N
>s : unique symbol
>N.s : unique symbol
>N : typeof N
>s : unique symbol
f<typeof N.s>(N["s"]);
>f<typeof N.s>(N["s"]) : unique symbol
>f : <T>(x: T) => T
>N.s : unique symbol
>N : typeof N
>s : unique symbol
>N["s"] : unique symbol
>N : typeof N
>"s" : "s"
g(s);
>g(s) : void
>g : { (x: unique symbol): void; (x: unique symbol): void; }
>s : unique symbol
g(N.s);
>g(N.s) : void
>g : { (x: unique symbol): void; (x: unique symbol): void; }
>N.s : unique symbol
>N : typeof N
>s : unique symbol
g(N["s"]);
>g(N["s"]) : void
>g : { (x: unique symbol): void; (x: unique symbol): void; }
>N["s"] : unique symbol
>N : typeof N
>"s" : "s"
// falsy expressions
s || "";
>s || "" : unique symbol | ""
>s : unique symbol
>"" : ""
N.s || "";
>N.s || "" : unique symbol | ""
>N.s : unique symbol
>N : typeof N
>s : unique symbol
>"" : ""
N["s"] || "";
>N["s"] || "" : unique symbol | ""
>N["s"] : unique symbol
>N : typeof N
>"s" : "s"
>"" : ""
// conditionals
Math.random() * 2 ? s : "a";
>Math.random() * 2 ? s : "a" : unique symbol | "a"
>Math.random() * 2 : number
>Math.random() : number
>Math.random : () => number
>Math : Math
>random : () => number
>2 : 2
>s : unique symbol
>"a" : "a"
Math.random() * 2 ? N.s : "a";
>Math.random() * 2 ? N.s : "a" : unique symbol | "a"
>Math.random() * 2 : number
>Math.random() : number
>Math.random : () => number
>Math : Math
>random : () => number
>2 : 2
>N.s : unique symbol
>N : typeof N
>s : unique symbol
>"a" : "a"
Math.random() * 2 ? N["s"] : "a";
>Math.random() * 2 ? N["s"] : "a" : unique symbol | "a"
>Math.random() * 2 : number
>Math.random() : number
>Math.random : () => number
>Math : Math
>random : () => number
>2 : 2
>N["s"] : unique symbol
>N : typeof N
>"s" : "s"
>"a" : "a"
// computed property names
({
>({ [s]: "a", [N.s]: "b",}) : { [s]: string; [N.s]: string; }
>{ [s]: "a", [N.s]: "b",} : { [s]: string; [N.s]: string; }
[s]: "a",
>s : unique symbol
>"a" : "a"
[N.s]: "b",
>N.s : unique symbol
>N : typeof N
>s : unique symbol
>"b" : "b"
});
class C1 {
>C1 : C1
static [s]: "a";
>s : unique symbol
static [N.s]: "b";
>N.s : unique symbol
>N : typeof N
>s : unique symbol
[s]: "a";
>s : unique symbol
[N.s]: "b";
>N.s : unique symbol
>N : typeof N
>s : unique symbol
}

View file

@ -137,4 +137,17 @@ export const o1_c4 = o1[c4];
export const o1_c5 = o1[c5];
export const o1_s2 = o1[s2];
export const o2: T0 = o1;
export const o2: T0 = o1;
// recursive declarations
declare const rI: RI;
interface RI {
x: "a";
[rI.x]: "b";
}
declare const rC: RC;
declare class RC {
x: "a";
[rC.x]: "b";
}

View file

@ -114,4 +114,88 @@ const constInitToLReadonlyNestedTypeWithIndexedAccess: L["nested"]["readonlyNest
// type argument inference
const promiseForConstCall = Promise.resolve(constCall);
const arrayOfConstCall = [constCall];
const arrayOfConstCall = [constCall];
// unique symbol widening in expressions
declare const s: unique symbol;
declare namespace N { const s: unique symbol; }
declare const o: { [s]: "a", [N.s]: "b" };
declare function f<T>(x: T): T;
declare function g(x: typeof s): void;
declare function g(x: typeof N.s): void;
// widening positions
// argument inference
f(s);
f(N.s);
f(N["s"]);
// array literal elements
[s];
[N.s];
[N["s"]];
// property assignments
const o2 = {
a: s,
b: N.s,
c: N["s"]
};
// property initializers
class C0 {
static readonly a = s;
static readonly b = N.s;
static readonly c = N["s"];
static d = s;
static e = N.s;
static f = N["s"];
readonly a = s;
readonly b = N.s;
readonly c = N["s"];
d = s;
e = N.s;
f = N["s"];
}
// non-widening positions
// element access
o[s];
o[N.s];
o[N["s"]];
// arguments (no-inference)
f<typeof s>(s);
f<typeof N.s>(N.s);
f<typeof N.s>(N["s"]);
g(s);
g(N.s);
g(N["s"]);
// falsy expressions
s || "";
N.s || "";
N["s"] || "";
// conditionals
Math.random() * 2 ? s : "a";
Math.random() * 2 ? N.s : "a";
Math.random() * 2 ? N["s"] : "a";
// computed property names
({
[s]: "a",
[N.s]: "b",
});
class C1 {
static [s]: "a";
static [N.s]: "b";
[s]: "a";
[N.s]: "b";
}