Skip to content

Commit

Permalink
Cache widened types (#31586)
Browse files Browse the repository at this point in the history
* Cache widened types

* Fix lint
  • Loading branch information
weswigham committed May 28, 2019
1 parent 63b8c64 commit cd09cbb
Show file tree
Hide file tree
Showing 6 changed files with 386 additions and 9 deletions.
26 changes: 17 additions & 9 deletions src/compiler/checker.ts
Expand Up @@ -14740,26 +14740,34 @@ namespace ts {

function getWidenedTypeWithContext(type: Type, context: WideningContext | undefined): Type {
if (getObjectFlags(type) & ObjectFlags.RequiresWidening) {
if (context === undefined && type.widened) {
return type.widened;
}
let result: Type | undefined;
if (type.flags & TypeFlags.Nullable) {
return anyType;
result = anyType;
}
if (isObjectLiteralType(type)) {
return getWidenedTypeOfObjectLiteral(type, context);
else if (isObjectLiteralType(type)) {
result = getWidenedTypeOfObjectLiteral(type, context);
}
if (type.flags & TypeFlags.Union) {
else if (type.flags & TypeFlags.Union) {
const unionContext = context || createWideningContext(/*parent*/ undefined, /*propertyName*/ undefined, (<UnionType>type).types);
const widenedTypes = sameMap((<UnionType>type).types, t => t.flags & TypeFlags.Nullable ? t : getWidenedTypeWithContext(t, unionContext));
// Widening an empty object literal transitions from a highly restrictive type to
// a highly inclusive one. For that reason we perform subtype reduction here if the
// union includes empty object types (e.g. reducing {} | string to just {}).
return getUnionType(widenedTypes, some(widenedTypes, isEmptyObjectType) ? UnionReduction.Subtype : UnionReduction.Literal);
result = getUnionType(widenedTypes, some(widenedTypes, isEmptyObjectType) ? UnionReduction.Subtype : UnionReduction.Literal);
}
else if (type.flags & TypeFlags.Intersection) {
result = getIntersectionType(sameMap((<IntersectionType>type).types, getWidenedType));
}
if (type.flags & TypeFlags.Intersection) {
return getIntersectionType(sameMap((<IntersectionType>type).types, getWidenedType));
else if (isArrayType(type) || isTupleType(type)) {
result = createTypeReference((<TypeReference>type).target, sameMap((<TypeReference>type).typeArguments, getWidenedType));
}
if (isArrayType(type) || isTupleType(type)) {
return createTypeReference((<TypeReference>type).target, sameMap((<TypeReference>type).typeArguments, getWidenedType));
if (result && context === undefined) {
type.widened = result;
}
return result || type;
}
return type;
}
Expand Down
2 changes: 2 additions & 0 deletions src/compiler/types.ts
Expand Up @@ -4013,6 +4013,8 @@ namespace ts {
restrictiveInstantiation?: Type; // Instantiation with type parameters mapped to unconstrained form
/* @internal */
immediateBaseConstraint?: Type; // Immediate base constraint cache
/* @internal */
widened?: Type; // Cached widened form of the type
}

/* @internal */
Expand Down
115 changes: 115 additions & 0 deletions tests/baselines/reference/noImplicitThisBigThis.js
@@ -0,0 +1,115 @@
//// [noImplicitThisBigThis.ts]
// https://github.com/microsoft/TypeScript/issues/29902

function createObj() {
return {
func1() {
return this;
},
func2() {
return this;
},
func3() {
return this;
}
};
}

function createObjNoCrash() {
return {
func1() {
return this;
},
func2() {
return this;
},
func3() {
return this;
},
func4() {
return this;
},
func5() {
return this;
},
func6() {
return this;
},
func7() {
return this;
},
func8() {
return this;
},
func9() {
return this;
}
};
}


//// [noImplicitThisBigThis.js]
// https://github.com/microsoft/TypeScript/issues/29902
function createObj() {
return {
func1: function () {
return this;
},
func2: function () {
return this;
},
func3: function () {
return this;
}
};
}
function createObjNoCrash() {
return {
func1: function () {
return this;
},
func2: function () {
return this;
},
func3: function () {
return this;
},
func4: function () {
return this;
},
func5: function () {
return this;
},
func6: function () {
return this;
},
func7: function () {
return this;
},
func8: function () {
return this;
},
func9: function () {
return this;
}
};
}


//// [noImplicitThisBigThis.d.ts]
declare function createObj(): {
func1(): any;
func2(): any;
func3(): any;
};
declare function createObjNoCrash(): {
func1(): any;
func2(): any;
func3(): any;
func4(): any;
func5(): any;
func6(): any;
func7(): any;
func8(): any;
func9(): any;
};
99 changes: 99 additions & 0 deletions tests/baselines/reference/noImplicitThisBigThis.symbols
@@ -0,0 +1,99 @@
=== tests/cases/compiler/noImplicitThisBigThis.ts ===
// https://github.com/microsoft/TypeScript/issues/29902

function createObj() {
>createObj : Symbol(createObj, Decl(noImplicitThisBigThis.ts, 0, 0))

return {
func1() {
>func1 : Symbol(func1, Decl(noImplicitThisBigThis.ts, 3, 12))

return this;
>this : Symbol(__object, Decl(noImplicitThisBigThis.ts, 3, 10))

},
func2() {
>func2 : Symbol(func2, Decl(noImplicitThisBigThis.ts, 6, 10))

return this;
>this : Symbol(__object, Decl(noImplicitThisBigThis.ts, 3, 10))

},
func3() {
>func3 : Symbol(func3, Decl(noImplicitThisBigThis.ts, 9, 10))

return this;
>this : Symbol(__object, Decl(noImplicitThisBigThis.ts, 3, 10))
}
};
}

function createObjNoCrash() {
>createObjNoCrash : Symbol(createObjNoCrash, Decl(noImplicitThisBigThis.ts, 14, 1))

return {
func1() {
>func1 : Symbol(func1, Decl(noImplicitThisBigThis.ts, 17, 12))

return this;
>this : Symbol(__object, Decl(noImplicitThisBigThis.ts, 17, 10))

},
func2() {
>func2 : Symbol(func2, Decl(noImplicitThisBigThis.ts, 20, 10))

return this;
>this : Symbol(__object, Decl(noImplicitThisBigThis.ts, 17, 10))

},
func3() {
>func3 : Symbol(func3, Decl(noImplicitThisBigThis.ts, 23, 10))

return this;
>this : Symbol(__object, Decl(noImplicitThisBigThis.ts, 17, 10))

},
func4() {
>func4 : Symbol(func4, Decl(noImplicitThisBigThis.ts, 26, 10))

return this;
>this : Symbol(__object, Decl(noImplicitThisBigThis.ts, 17, 10))

},
func5() {
>func5 : Symbol(func5, Decl(noImplicitThisBigThis.ts, 29, 10))

return this;
>this : Symbol(__object, Decl(noImplicitThisBigThis.ts, 17, 10))

},
func6() {
>func6 : Symbol(func6, Decl(noImplicitThisBigThis.ts, 32, 10))

return this;
>this : Symbol(__object, Decl(noImplicitThisBigThis.ts, 17, 10))

},
func7() {
>func7 : Symbol(func7, Decl(noImplicitThisBigThis.ts, 35, 10))

return this;
>this : Symbol(__object, Decl(noImplicitThisBigThis.ts, 17, 10))

},
func8() {
>func8 : Symbol(func8, Decl(noImplicitThisBigThis.ts, 38, 10))

return this;
>this : Symbol(__object, Decl(noImplicitThisBigThis.ts, 17, 10))

},
func9() {
>func9 : Symbol(func9, Decl(noImplicitThisBigThis.ts, 41, 10))

return this;
>this : Symbol(__object, Decl(noImplicitThisBigThis.ts, 17, 10))
}
};
}

0 comments on commit cd09cbb

Please sign in to comment.