Skip to content

Commit

Permalink
Do not materialize optional undefined properties inside actual types
Browse files Browse the repository at this point in the history
  • Loading branch information
weswigham committed Nov 29, 2018
1 parent 52a46c6 commit e7a4b10
Show file tree
Hide file tree
Showing 13 changed files with 103,198 additions and 199 deletions.
402 changes: 255 additions & 147 deletions src/compiler/checker.ts

Large diffs are not rendered by default.

29 changes: 19 additions & 10 deletions src/compiler/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3890,7 +3890,9 @@ namespace ts {
/* @internal */
EmptyObject = ContainsAnyFunctionType,
/* @internal */
ConstructionFlags = NonWideningType | Wildcard | EmptyObject,
AllFresh = EnumLiteral,
/* @internal */
ConstructionFlags = NonWideningType | Wildcard | EmptyObject | AllFresh,
// The following flag is used for different purposes by maybeTypeOfKind
/* @internal */
GenericMappedType = ContainsWideningType
Expand Down Expand Up @@ -3988,6 +3990,8 @@ namespace ts {
/* @internal */ constructSignatures?: ReadonlyArray<Signature>; // Construct signatures of type
/* @internal */ stringIndexInfo?: IndexInfo; // String indexing info
/* @internal */ numberIndexInfo?: IndexInfo; // Numeric indexing info
/* @internal */ regularType?: this;
/* @internal */ freshType?: this;
}

/** Class and interface types (ObjectFlags.Class and ObjectFlags.Interface). */
Expand Down Expand Up @@ -4071,9 +4075,22 @@ namespace ts {
couldContainTypeVariables: boolean;
}

/* @internal */
export const enum UnionFlags {
PrimitiveOnly = 1 << 0,
FreshObjectsOnly = 1 << 1,
WidenedFreshObjectsOnly = 1 << 2,
}

export interface UnionType extends UnionOrIntersectionType {
/* @internal */
primitiveTypesOnly: boolean;
unionFlags: UnionFlags;
/* @internal */
propertyNameCache?: UnderscoreEscapedMap<true>; // Cache of possible property names
/* @internal */
freshType?: this; // Pointer back to the original `FreshObjectsOnly` union for `WidenedFreshObjectsOnly` unions
/* @internal */
regularType?: this; // Pointer to the widened union for `FreshObjectsOnly` unions, if it has been made
}

export interface IntersectionType extends UnionOrIntersectionType {
Expand Down Expand Up @@ -4122,14 +4139,6 @@ namespace ts {
constructSignatures: ReadonlyArray<Signature>; // Construct signatures of type
}

/* @internal */
// Object literals are initially marked fresh. Freshness disappears following an assignment,
// before a type assertion, or when an object literal's type is widened. The regular
// version of a fresh type is identical except for the TypeFlags.FreshObjectLiteral flag.
export interface FreshObjectLiteralType extends ResolvedType {
regularType: ResolvedType; // Regular version of fresh type
}

// Just a place to cache element types of iterables and iterators
/* @internal */
export interface IterableOrIteratorType extends ObjectType, UnionType {
Expand Down
1 change: 1 addition & 0 deletions src/compiler/utilities.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ namespace ts {
export const externalHelpersModuleNameText = "tslib";

export const defaultMaximumTruncationLength = 160;
export const defaultHardCapTrunctionLength = 100000; // Trunction limit used even when `noErrorTruncation` is on to avoid OOM when printing huge types

export function getDeclarationOfKind<T extends Declaration>(symbol: Symbol, kind: T["kind"]): T | undefined {
const declarations = symbol.declarations;
Expand Down
3 changes: 2 additions & 1 deletion src/harness/harness.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1107,7 +1107,8 @@ namespace Harness {
{ name: "symlink", type: "string" },
{ name: "link", type: "string" },
// Emitted js baseline will print full paths for every output file
{ name: "fullEmitPaths", type: "boolean" }
{ name: "fullEmitPaths", type: "boolean" },
{ name: "skipTypeAndSymbol", type: "boolean" }
];

let optionsIndex: ts.Map<ts.CommandLineOption>;
Expand Down
3 changes: 3 additions & 0 deletions src/testRunner/compilerRunner.ts
Original file line number Diff line number Diff line change
Expand Up @@ -246,6 +246,9 @@ class CompilerTest {
}

public verifyTypesAndSymbols() {
if (this.harnessSettings.skipTypeAndSymbol) {
return;
}
if (this.fileName.indexOf("APISample") >= 0) {
return;
}
Expand Down
68,593 changes: 68,593 additions & 0 deletions tests/baselines/reference/complexArrayLiteral.js

Large diffs are not rendered by default.

10 changes: 5 additions & 5 deletions tests/baselines/reference/conditionalTypeDoesntSpinForever.types
Original file line number Diff line number Diff line change
Expand Up @@ -449,22 +449,22 @@ export enum PubSubRecordIsStoredInRedisAsA {
>{} : {}

buildNameFieldConstructor(soFar),
>buildNameFieldConstructor(soFar) : { name?: undefined; } | { name: <TYPE>(instance?: TYPE) => BuildPubSubRecordType<SO_FAR & { name: TYPE; }>; }
>buildNameFieldConstructor(soFar) : {} | { name: <TYPE>(instance?: TYPE) => BuildPubSubRecordType<SO_FAR & { name: TYPE; }>; }
>buildNameFieldConstructor : <SO_FAR>(soFar: SO_FAR) => { name?: undefined; } | { name: <TYPE>(instance?: TYPE) => BuildPubSubRecordType<SO_FAR & { name: TYPE; }>; }
>soFar : SO_FAR

buildIdentifierFieldConstructor(soFar),
>buildIdentifierFieldConstructor(soFar) : { identifier?: undefined; } | { identifier: <TYPE>(instance?: TYPE) => BuildPubSubRecordType<SO_FAR & { identifier: TYPE; }>; }
>buildIdentifierFieldConstructor(soFar) : {} | { identifier: <TYPE>(instance?: TYPE) => BuildPubSubRecordType<SO_FAR & { identifier: TYPE; }>; }
>buildIdentifierFieldConstructor : <SO_FAR>(soFar: SO_FAR) => { identifier?: undefined; } | { identifier: <TYPE>(instance?: TYPE) => BuildPubSubRecordType<SO_FAR & { identifier: TYPE; }>; }
>soFar : SO_FAR

buildRecordFieldConstructor(soFar),
>buildRecordFieldConstructor(soFar) : { record?: undefined; } | { record: <TYPE>(instance?: TYPE) => BuildPubSubRecordType<SO_FAR & { record: TYPE; }>; }
>buildRecordFieldConstructor(soFar) : {} | { record: <TYPE>(instance?: TYPE) => BuildPubSubRecordType<SO_FAR & { record: TYPE; }>; }
>buildRecordFieldConstructor : <SO_FAR>(soFar: SO_FAR) => { record?: undefined; } | { record: <TYPE>(instance?: TYPE) => BuildPubSubRecordType<SO_FAR & { record: TYPE; }>; }
>soFar : SO_FAR

buildStoredAsConstructor(soFar),
>buildStoredAsConstructor(soFar) : { storedAsJsonEncodedRedisString?: undefined; storedAsRedisHash?: undefined; } | { storedAsJsonEncodedRedisString: () => BuildPubSubRecordType<SO_FAR & { storedAs: PubSubRecordIsStoredInRedisAsA.jsonEncodedRedisString; }>; storedAsRedisHash: () => BuildPubSubRecordType<SO_FAR & { storedAs: PubSubRecordIsStoredInRedisAsA.redisHash; }>; }
>buildStoredAsConstructor(soFar) : {} | { storedAsJsonEncodedRedisString: () => BuildPubSubRecordType<SO_FAR & { storedAs: PubSubRecordIsStoredInRedisAsA.jsonEncodedRedisString; }>; storedAsRedisHash: () => BuildPubSubRecordType<SO_FAR & { storedAs: PubSubRecordIsStoredInRedisAsA.redisHash; }>; }
>buildStoredAsConstructor : <SO_FAR>(soFar: SO_FAR) => { storedAsJsonEncodedRedisString?: undefined; storedAsRedisHash?: undefined; } | { storedAsJsonEncodedRedisString: () => BuildPubSubRecordType<SO_FAR & { storedAs: PubSubRecordIsStoredInRedisAsA.jsonEncodedRedisString; }>; storedAsRedisHash: () => BuildPubSubRecordType<SO_FAR & { storedAs: PubSubRecordIsStoredInRedisAsA.redisHash; }>; }
>soFar : SO_FAR

Expand All @@ -474,7 +474,7 @@ export enum PubSubRecordIsStoredInRedisAsA {
>soFar : SO_FAR

buildType(soFar)
>buildType(soFar) : { type?: undefined; fields?: undefined; hasField?: undefined; } | { type: SO_FAR; fields: () => Set<keyof SO_FAR>; hasField: (fieldName: string | number | symbol) => boolean; }
>buildType(soFar) : {} | { type: SO_FAR; fields: () => Set<keyof SO_FAR>; hasField: (fieldName: string | number | symbol) => boolean; }
>buildType : <SO_FAR>(soFar: SO_FAR) => { type?: undefined; fields?: undefined; hasField?: undefined; } | { type: SO_FAR; fields: () => Set<keyof SO_FAR>; hasField: (fieldName: string | number | symbol) => boolean; }
>soFar : SO_FAR

Expand Down

This file was deleted.

10 changes: 5 additions & 5 deletions tests/baselines/reference/objectLiteralNormalization.errors.txt
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@ tests/cases/conformance/expressions/objectLiterals/objectLiteralNormalization.ts
tests/cases/conformance/expressions/objectLiterals/objectLiteralNormalization.ts(9,1): error TS2322: Type '{ c: true; }' is not assignable to type '{ a: number; b?: undefined; c?: undefined; } | { a: number; b: string; c?: undefined; } | { a: number; b: string; c: boolean; }'.
Type '{ c: true; }' is missing the following properties from type '{ a: number; b: string; c: boolean; }': a, b
tests/cases/conformance/expressions/objectLiterals/objectLiteralNormalization.ts(17,1): error TS2322: Type '{ a: string; b: number; }' is not assignable to type '{ a: number; b: number; } | { a: string; b?: undefined; } | { a?: undefined; b?: undefined; }'.
Type '{ a: string; b: number; }' is not assignable to type '{ a?: undefined; b?: undefined; }'.
Type '{ a: string; b: number; }' is not assignable to type '{ a: number; b: number; }'.
Types of property 'a' are incompatible.
Type 'string' is not assignable to type 'undefined'.
Type 'string' is not assignable to type 'number'.
tests/cases/conformance/expressions/objectLiterals/objectLiteralNormalization.ts(18,1): error TS2322: Type '{ a: number; }' is not assignable to type '{ a: number; b: number; } | { a: string; b?: undefined; } | { a?: undefined; b?: undefined; }'.
Property 'b' is missing in type '{ a: number; }' but required in type '{ a: number; b: number; }'.

Expand All @@ -21,7 +21,7 @@ tests/cases/conformance/expressions/objectLiterals/objectLiteralNormalization.ts
a1 = { a: 0, b: 0 }; // Error
~
!!! error TS2322: Type 'number' is not assignable to type 'string | undefined'.
!!! related TS6500 tests/cases/conformance/expressions/objectLiterals/objectLiteralNormalization.ts:2:47: The expected type comes from property 'b' which is declared here on type '{ a: number; b?: undefined; c?: undefined; } | { a: number; b: string; c?: undefined; } | { a: number; b: string; c: boolean; }'
!!! related TS6500 tests/cases/conformance/expressions/objectLiterals/objectLiteralNormalization.ts:2:29: The expected type comes from property 'b' which is declared here on type '{ a: number; b?: undefined; c?: undefined; } | { a: number; b: string; c?: undefined; } | { a: number; b: string; c: boolean; }'
a1 = { b: "y" }; // Error
~~
!!! error TS2322: Type '{ b: string; }' is not assignable to type '{ a: number; b?: undefined; c?: undefined; } | { a: number; b: string; c?: undefined; } | { a: number; b: string; c: boolean; }'.
Expand All @@ -40,9 +40,9 @@ tests/cases/conformance/expressions/objectLiterals/objectLiteralNormalization.ts
a2 = { a: "def", b: 20 }; // Error
~~
!!! error TS2322: Type '{ a: string; b: number; }' is not assignable to type '{ a: number; b: number; } | { a: string; b?: undefined; } | { a?: undefined; b?: undefined; }'.
!!! error TS2322: Type '{ a: string; b: number; }' is not assignable to type '{ a?: undefined; b?: undefined; }'.
!!! error TS2322: Type '{ a: string; b: number; }' is not assignable to type '{ a: number; b: number; }'.
!!! error TS2322: Types of property 'a' are incompatible.
!!! error TS2322: Type 'string' is not assignable to type 'undefined'.
!!! error TS2322: Type 'string' is not assignable to type 'number'.
a2 = { a: 1 }; // Error
~~
!!! error TS2322: Type '{ a: number; }' is not assignable to type '{ a: number; b: number; } | { a: string; b?: undefined; } | { a?: undefined; b?: undefined; }'.
Expand Down
32 changes: 16 additions & 16 deletions tests/baselines/reference/objectLiteralNormalization.symbols
Original file line number Diff line number Diff line change
Expand Up @@ -15,14 +15,14 @@ a1.a; // number
>a : Symbol(a, Decl(objectLiteralNormalization.ts, 1, 11), Decl(objectLiteralNormalization.ts, 1, 21), Decl(objectLiteralNormalization.ts, 1, 39))

a1.b; // string | undefined
>a1.b : Symbol(b, Decl(objectLiteralNormalization.ts, 1, 45), Decl(objectLiteralNormalization.ts, 1, 27), Decl(objectLiteralNormalization.ts, 1, 45))
>a1.b : Symbol(b, Decl(objectLiteralNormalization.ts, 1, 27), Decl(objectLiteralNormalization.ts, 1, 45))
>a1 : Symbol(a1, Decl(objectLiteralNormalization.ts, 1, 3))
>b : Symbol(b, Decl(objectLiteralNormalization.ts, 1, 45), Decl(objectLiteralNormalization.ts, 1, 27), Decl(objectLiteralNormalization.ts, 1, 45))
>b : Symbol(b, Decl(objectLiteralNormalization.ts, 1, 27), Decl(objectLiteralNormalization.ts, 1, 45))

a1.c; // boolean | undefined
>a1.c : Symbol(c, Decl(objectLiteralNormalization.ts, 1, 53), Decl(objectLiteralNormalization.ts, 1, 53))
>a1.c : Symbol(c, Decl(objectLiteralNormalization.ts, 1, 53))
>a1 : Symbol(a1, Decl(objectLiteralNormalization.ts, 1, 3))
>c : Symbol(c, Decl(objectLiteralNormalization.ts, 1, 53), Decl(objectLiteralNormalization.ts, 1, 53))
>c : Symbol(c, Decl(objectLiteralNormalization.ts, 1, 53))

a1 = { a: 1 };
>a1 : Symbol(a1, Decl(objectLiteralNormalization.ts, 1, 3))
Expand All @@ -48,14 +48,14 @@ let a2 = [{ a: 1, b: 2 }, { a: "abc" }, {}][0];
>a : Symbol(a, Decl(objectLiteralNormalization.ts, 10, 27))

a2.a; // string | number | undefined
>a2.a : Symbol(a, Decl(objectLiteralNormalization.ts, 10, 11), Decl(objectLiteralNormalization.ts, 10, 27), Decl(objectLiteralNormalization.ts, 10, 27))
>a2.a : Symbol(a, Decl(objectLiteralNormalization.ts, 10, 11), Decl(objectLiteralNormalization.ts, 10, 27))
>a2 : Symbol(a2, Decl(objectLiteralNormalization.ts, 10, 3))
>a : Symbol(a, Decl(objectLiteralNormalization.ts, 10, 11), Decl(objectLiteralNormalization.ts, 10, 27), Decl(objectLiteralNormalization.ts, 10, 27))
>a : Symbol(a, Decl(objectLiteralNormalization.ts, 10, 11), Decl(objectLiteralNormalization.ts, 10, 27))

a2.b; // number | undefined
>a2.b : Symbol(b, Decl(objectLiteralNormalization.ts, 10, 17), Decl(objectLiteralNormalization.ts, 1, 45))
>a2.b : Symbol(b, Decl(objectLiteralNormalization.ts, 10, 17))
>a2 : Symbol(a2, Decl(objectLiteralNormalization.ts, 10, 3))
>b : Symbol(b, Decl(objectLiteralNormalization.ts, 10, 17), Decl(objectLiteralNormalization.ts, 1, 45))
>b : Symbol(b, Decl(objectLiteralNormalization.ts, 10, 17))

a2 = { a: 10, b: 20 };
>a2 : Symbol(a2, Decl(objectLiteralNormalization.ts, 10, 3))
Expand Down Expand Up @@ -144,32 +144,32 @@ d1.pos;
>pos : Symbol(pos, Decl(objectLiteralNormalization.ts, 33, 22), Decl(objectLiteralNormalization.ts, 33, 58))

d1.pos.x;
>d1.pos.x : Symbol(x, Decl(objectLiteralNormalization.ts, 33, 29), Decl(objectLiteralNormalization.ts, 33, 29))
>d1.pos.x : Symbol(x, Decl(objectLiteralNormalization.ts, 33, 29))
>d1.pos : Symbol(pos, Decl(objectLiteralNormalization.ts, 33, 22), Decl(objectLiteralNormalization.ts, 33, 58))
>d1 : Symbol(d1, Decl(objectLiteralNormalization.ts, 33, 3))
>pos : Symbol(pos, Decl(objectLiteralNormalization.ts, 33, 22), Decl(objectLiteralNormalization.ts, 33, 58))
>x : Symbol(x, Decl(objectLiteralNormalization.ts, 33, 29), Decl(objectLiteralNormalization.ts, 33, 29))
>x : Symbol(x, Decl(objectLiteralNormalization.ts, 33, 29))

d1.pos.y;
>d1.pos.y : Symbol(y, Decl(objectLiteralNormalization.ts, 33, 35), Decl(objectLiteralNormalization.ts, 33, 35))
>d1.pos.y : Symbol(y, Decl(objectLiteralNormalization.ts, 33, 35))
>d1.pos : Symbol(pos, Decl(objectLiteralNormalization.ts, 33, 22), Decl(objectLiteralNormalization.ts, 33, 58))
>d1 : Symbol(d1, Decl(objectLiteralNormalization.ts, 33, 3))
>pos : Symbol(pos, Decl(objectLiteralNormalization.ts, 33, 22), Decl(objectLiteralNormalization.ts, 33, 58))
>y : Symbol(y, Decl(objectLiteralNormalization.ts, 33, 35), Decl(objectLiteralNormalization.ts, 33, 35))
>y : Symbol(y, Decl(objectLiteralNormalization.ts, 33, 35))

d1.pos.a;
>d1.pos.a : Symbol(a, Decl(objectLiteralNormalization.ts, 10, 27), Decl(objectLiteralNormalization.ts, 33, 73))
>d1.pos.a : Symbol(a, Decl(objectLiteralNormalization.ts, 33, 73))
>d1.pos : Symbol(pos, Decl(objectLiteralNormalization.ts, 33, 22), Decl(objectLiteralNormalization.ts, 33, 58))
>d1 : Symbol(d1, Decl(objectLiteralNormalization.ts, 33, 3))
>pos : Symbol(pos, Decl(objectLiteralNormalization.ts, 33, 22), Decl(objectLiteralNormalization.ts, 33, 58))
>a : Symbol(a, Decl(objectLiteralNormalization.ts, 10, 27), Decl(objectLiteralNormalization.ts, 33, 73))
>a : Symbol(a, Decl(objectLiteralNormalization.ts, 33, 73))

d1.pos.b;
>d1.pos.b : Symbol(b, Decl(objectLiteralNormalization.ts, 1, 45), Decl(objectLiteralNormalization.ts, 33, 86))
>d1.pos.b : Symbol(b, Decl(objectLiteralNormalization.ts, 33, 86))
>d1.pos : Symbol(pos, Decl(objectLiteralNormalization.ts, 33, 22), Decl(objectLiteralNormalization.ts, 33, 58))
>d1 : Symbol(d1, Decl(objectLiteralNormalization.ts, 33, 3))
>pos : Symbol(pos, Decl(objectLiteralNormalization.ts, 33, 22), Decl(objectLiteralNormalization.ts, 33, 58))
>b : Symbol(b, Decl(objectLiteralNormalization.ts, 1, 45), Decl(objectLiteralNormalization.ts, 33, 86))
>b : Symbol(b, Decl(objectLiteralNormalization.ts, 33, 86))

declare function f<T>(...items: T[]): T;
>f : Symbol(f, Decl(objectLiteralNormalization.ts, 39, 9))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -66,11 +66,11 @@ ExpandoExpr.m = function(n: number) {
}
var n = (ExpandoExpr.prop.x || 0) + ExpandoExpr.m(12) + ExpandoExpr(101).length
>n : Symbol(n, Decl(typeFromPropertyAssignment29.ts, 7, 3), Decl(typeFromPropertyAssignment29.ts, 17, 3), Decl(typeFromPropertyAssignment29.ts, 45, 3), Decl(typeFromPropertyAssignment29.ts, 63, 3), Decl(typeFromPropertyAssignment29.ts, 73, 3) ... and 1 more)
>ExpandoExpr.prop.x : Symbol(x, Decl(typeFromPropertyAssignment29.ts, 12, 20))
>ExpandoExpr.prop.x : Symbol(x)
>ExpandoExpr.prop : Symbol(ExpandoExpr.prop, Decl(typeFromPropertyAssignment29.ts, 11, 1), Decl(typeFromPropertyAssignment29.ts, 12, 27))
>ExpandoExpr : Symbol(ExpandoExpr, Decl(typeFromPropertyAssignment29.ts, 9, 5), Decl(typeFromPropertyAssignment29.ts, 11, 1))
>prop : Symbol(ExpandoExpr.prop, Decl(typeFromPropertyAssignment29.ts, 11, 1), Decl(typeFromPropertyAssignment29.ts, 12, 27))
>x : Symbol(x, Decl(typeFromPropertyAssignment29.ts, 12, 20))
>x : Symbol(x)
>ExpandoExpr.m : Symbol(ExpandoExpr.m, Decl(typeFromPropertyAssignment29.ts, 13, 28))
>ExpandoExpr : Symbol(ExpandoExpr, Decl(typeFromPropertyAssignment29.ts, 9, 5), Decl(typeFromPropertyAssignment29.ts, 11, 1))
>m : Symbol(ExpandoExpr.m, Decl(typeFromPropertyAssignment29.ts, 13, 28))
Expand Down
4 changes: 2 additions & 2 deletions tests/baselines/reference/typeFromPropertyAssignment29.types
Original file line number Diff line number Diff line change
Expand Up @@ -96,9 +96,9 @@ var n = (ExpandoExpr.prop.x || 0) + ExpandoExpr.m(12) + ExpandoExpr(101).length
>(ExpandoExpr.prop.x || 0) : 0
>ExpandoExpr.prop.x || 0 : 0
>ExpandoExpr.prop.x : undefined
>ExpandoExpr.prop : { y: string; x?: undefined; }
>ExpandoExpr.prop : { y: string; }
>ExpandoExpr : { (n: number): string; prop: { x: number; y?: undefined; } | { y: string; x?: undefined; }; m(n: number): number; }
>prop : { y: string; x?: undefined; }
>prop : { y: string; }
>x : undefined
>0 : 0
>ExpandoExpr.m(12) : number
Expand Down
Loading

0 comments on commit e7a4b10

Please sign in to comment.