mirror of
https://github.com/microsoft/TypeScript.git
synced 2025-11-18 17:21:48 +00:00
Addressing feedback and adding regression tests
This commit is contained in:
@@ -3217,8 +3217,8 @@ module ts {
|
||||
return checkTypeRelatedTo(source, target, identityRelation, /*errorNode*/ undefined);
|
||||
}
|
||||
|
||||
function compareTypes(source: Type, target: Type): number {
|
||||
return checkTypeRelatedTo(source, target, identityRelation, /*errorNode*/ undefined) ? -1 : 0;
|
||||
function compareTypes(source: Type, target: Type): Ternary {
|
||||
return checkTypeRelatedTo(source, target, identityRelation, /*errorNode*/ undefined) ? Ternary.True : Ternary.False;
|
||||
}
|
||||
|
||||
function isTypeSubtypeOf(source: Type, target: Type): boolean {
|
||||
@@ -3270,7 +3270,7 @@ module ts {
|
||||
}
|
||||
addDiagnostic(createDiagnosticForNodeFromMessageChain(errorNode, errorInfo, program.getCompilerHost().getNewLine()));
|
||||
}
|
||||
return result !== 0;
|
||||
return result !== Ternary.False;
|
||||
|
||||
function reportError(message: DiagnosticMessage, arg0?: string, arg1?: string, arg2?: string): void {
|
||||
errorInfo = chainDiagnosticMessages(errorInfo, message, arg0, arg1, arg2);
|
||||
@@ -3418,11 +3418,13 @@ module ts {
|
||||
if (depth > 0) {
|
||||
for (var i = 0; i < depth; i++) {
|
||||
// If source and target are already being compared, consider them related with assumptions
|
||||
if (source === sourceStack[i] && target === targetStack[i]) return Ternary.Maybe;
|
||||
if (source === sourceStack[i] && target === targetStack[i]) {
|
||||
return Ternary.Maybe;
|
||||
}
|
||||
}
|
||||
if (depth === 100) {
|
||||
overflow = true;
|
||||
return 0;
|
||||
return Ternary.False;
|
||||
}
|
||||
}
|
||||
else {
|
||||
@@ -3766,7 +3768,7 @@ module ts {
|
||||
}
|
||||
|
||||
function isPropertyIdenticalTo(sourceProp: Symbol, targetProp: Symbol): boolean {
|
||||
return compareProperties(sourceProp, targetProp, compareTypes) !== 0;
|
||||
return compareProperties(sourceProp, targetProp, compareTypes) !== Ternary.False;
|
||||
}
|
||||
|
||||
function compareProperties(sourceProp: Symbol, targetProp: Symbol, compareTypes: (source: Type, target: Type) => Ternary): Ternary {
|
||||
@@ -3785,14 +3787,13 @@ module ts {
|
||||
if (getTargetSymbol(sourceProp) !== getTargetSymbol(targetProp)) {
|
||||
return Ternary.False;
|
||||
}
|
||||
return compareTypes(getTypeOfSymbol(sourceProp), getTypeOfSymbol(targetProp));
|
||||
}
|
||||
else {
|
||||
if (isOptionalProperty(sourceProp) !== isOptionalProperty(targetProp)) {
|
||||
return Ternary.False;
|
||||
}
|
||||
return compareTypes(getTypeOfSymbol(sourceProp), getTypeOfSymbol(targetProp));
|
||||
}
|
||||
return compareTypes(getTypeOfSymbol(sourceProp), getTypeOfSymbol(targetProp));
|
||||
}
|
||||
|
||||
function compareSignatures(source: Signature, target: Signature, compareReturnTypes: boolean, compareTypes: (s: Type, t: Type) => Ternary): Ternary {
|
||||
|
||||
@@ -5,7 +5,10 @@ module ts {
|
||||
// Ternary values are defined such that
|
||||
// x & y is False if either x or y is False.
|
||||
// x & y is Maybe if either x or y is Maybe, but neither x or y is False.
|
||||
// x & y is True if x and y are both True.
|
||||
// x & y is True if both x and y are True.
|
||||
// x | y is False if both x and y are False.
|
||||
// x | y is Maybe if either x or y is Maybe, but neither x or y is True.
|
||||
// x | y is True if either x or y is True.
|
||||
export enum Ternary {
|
||||
False = 0,
|
||||
Maybe = 1,
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
//// [checkInfiniteExpansionTermination.ts]
|
||||
// Regression test for #1002
|
||||
// Before fix this code would cause infinite loop
|
||||
|
||||
interface IObservable<T> {
|
||||
n: IObservable<T[]>; // Needed, must be T[]
|
||||
}
|
||||
|
||||
// Needed
|
||||
interface ISubject<T> extends IObservable<T> { }
|
||||
|
||||
interface Foo { x }
|
||||
interface Bar { y }
|
||||
|
||||
var values: IObservable<Foo>;
|
||||
var values2: ISubject<Bar>;
|
||||
values = values2;
|
||||
|
||||
|
||||
//// [checkInfiniteExpansionTermination.js]
|
||||
// Regression test for #1002
|
||||
// Before fix this code would cause infinite loop
|
||||
var values;
|
||||
var values2;
|
||||
values = values2;
|
||||
@@ -0,0 +1,44 @@
|
||||
=== tests/cases/compiler/checkInfiniteExpansionTermination.ts ===
|
||||
// Regression test for #1002
|
||||
// Before fix this code would cause infinite loop
|
||||
|
||||
interface IObservable<T> {
|
||||
>IObservable : IObservable<T>
|
||||
>T : T
|
||||
|
||||
n: IObservable<T[]>; // Needed, must be T[]
|
||||
>n : IObservable<T[]>
|
||||
>IObservable : IObservable<T>
|
||||
>T : T
|
||||
}
|
||||
|
||||
// Needed
|
||||
interface ISubject<T> extends IObservable<T> { }
|
||||
>ISubject : ISubject<T>
|
||||
>T : T
|
||||
>IObservable : IObservable<T>
|
||||
>T : T
|
||||
|
||||
interface Foo { x }
|
||||
>Foo : Foo
|
||||
>x : any
|
||||
|
||||
interface Bar { y }
|
||||
>Bar : Bar
|
||||
>y : any
|
||||
|
||||
var values: IObservable<Foo>;
|
||||
>values : IObservable<Foo>
|
||||
>IObservable : IObservable<T>
|
||||
>Foo : Foo
|
||||
|
||||
var values2: ISubject<Bar>;
|
||||
>values2 : ISubject<Bar>
|
||||
>ISubject : ISubject<T>
|
||||
>Bar : Bar
|
||||
|
||||
values = values2;
|
||||
>values = values2 : ISubject<Bar>
|
||||
>values : IObservable<Foo>
|
||||
>values2 : ISubject<Bar>
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
//// [checkInfiniteExpansionTermination2.ts]
|
||||
// Regression test for #1002
|
||||
// Before fix this code would cause infinite loop
|
||||
|
||||
interface IObservable<T> {
|
||||
n: IObservable<T[]>;
|
||||
}
|
||||
interface ISubject<T> extends IObservable<T> { }
|
||||
|
||||
declare function combineLatest<TOther>(x: IObservable<TOther>[]): void;
|
||||
declare function combineLatest(): void;
|
||||
|
||||
function fn<T>() {
|
||||
var values: ISubject<any>[] = [];
|
||||
// Hang when using <T>, but not <any>
|
||||
combineLatest<T>(values);
|
||||
}
|
||||
|
||||
|
||||
//// [checkInfiniteExpansionTermination2.js]
|
||||
// Regression test for #1002
|
||||
// Before fix this code would cause infinite loop
|
||||
function fn() {
|
||||
var values = [];
|
||||
// Hang when using <T>, but not <any>
|
||||
combineLatest(values);
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
=== tests/cases/compiler/checkInfiniteExpansionTermination2.ts ===
|
||||
// Regression test for #1002
|
||||
// Before fix this code would cause infinite loop
|
||||
|
||||
interface IObservable<T> {
|
||||
>IObservable : IObservable<T>
|
||||
>T : T
|
||||
|
||||
n: IObservable<T[]>;
|
||||
>n : IObservable<T[]>
|
||||
>IObservable : IObservable<T>
|
||||
>T : T
|
||||
}
|
||||
interface ISubject<T> extends IObservable<T> { }
|
||||
>ISubject : ISubject<T>
|
||||
>T : T
|
||||
>IObservable : IObservable<T>
|
||||
>T : T
|
||||
|
||||
declare function combineLatest<TOther>(x: IObservable<TOther>[]): void;
|
||||
>combineLatest : { <TOther>(x: IObservable<TOther>[]): void; (): void; }
|
||||
>TOther : TOther
|
||||
>x : IObservable<TOther>[]
|
||||
>IObservable : IObservable<T>
|
||||
>TOther : TOther
|
||||
|
||||
declare function combineLatest(): void;
|
||||
>combineLatest : { <TOther>(x: IObservable<TOther>[]): void; (): void; }
|
||||
|
||||
function fn<T>() {
|
||||
>fn : <T>() => void
|
||||
>T : T
|
||||
|
||||
var values: ISubject<any>[] = [];
|
||||
>values : ISubject<any>[]
|
||||
>ISubject : ISubject<T>
|
||||
>[] : undefined[]
|
||||
|
||||
// Hang when using <T>, but not <any>
|
||||
combineLatest<T>(values);
|
||||
>combineLatest<T>(values) : void
|
||||
>combineLatest : { <TOther>(x: IObservable<TOther>[]): void; (): void; }
|
||||
>T : T
|
||||
>values : ISubject<any>[]
|
||||
}
|
||||
|
||||
@@ -0,0 +1,45 @@
|
||||
tests/cases/compiler/typeComparisonCaching.ts(26,1): error TS2323: Type 'B' is not assignable to type 'A'.
|
||||
Types of property 's' are incompatible.
|
||||
Type 'number' is not assignable to type 'string'.
|
||||
tests/cases/compiler/typeComparisonCaching.ts(27,1): error TS2323: Type 'D' is not assignable to type 'C'.
|
||||
Types of property 'q' are incompatible.
|
||||
Type 'B' is not assignable to type 'A'.
|
||||
|
||||
|
||||
==== tests/cases/compiler/typeComparisonCaching.ts (2 errors) ====
|
||||
// Check that we only cache results of type comparisons that are free of assumptions
|
||||
|
||||
interface A {
|
||||
p: C;
|
||||
s: string;
|
||||
}
|
||||
|
||||
interface B {
|
||||
p: D;
|
||||
s: number;
|
||||
}
|
||||
|
||||
interface C {
|
||||
q: A;
|
||||
}
|
||||
|
||||
interface D {
|
||||
q: B;
|
||||
}
|
||||
|
||||
var a: A;
|
||||
var b: B;
|
||||
var c: C;
|
||||
var d: D;
|
||||
|
||||
a = b;
|
||||
~
|
||||
!!! error TS2323: Type 'B' is not assignable to type 'A'.
|
||||
!!! error TS2323: Types of property 's' are incompatible.
|
||||
!!! error TS2323: Type 'number' is not assignable to type 'string'.
|
||||
c = d; // Should not be allowed
|
||||
~
|
||||
!!! error TS2323: Type 'D' is not assignable to type 'C'.
|
||||
!!! error TS2323: Types of property 'q' are incompatible.
|
||||
!!! error TS2323: Type 'B' is not assignable to type 'A'.
|
||||
|
||||
@@ -0,0 +1,38 @@
|
||||
//// [typeComparisonCaching.ts]
|
||||
// Check that we only cache results of type comparisons that are free of assumptions
|
||||
|
||||
interface A {
|
||||
p: C;
|
||||
s: string;
|
||||
}
|
||||
|
||||
interface B {
|
||||
p: D;
|
||||
s: number;
|
||||
}
|
||||
|
||||
interface C {
|
||||
q: A;
|
||||
}
|
||||
|
||||
interface D {
|
||||
q: B;
|
||||
}
|
||||
|
||||
var a: A;
|
||||
var b: B;
|
||||
var c: C;
|
||||
var d: D;
|
||||
|
||||
a = b;
|
||||
c = d; // Should not be allowed
|
||||
|
||||
|
||||
//// [typeComparisonCaching.js]
|
||||
// Check that we only cache results of type comparisons that are free of assumptions
|
||||
var a;
|
||||
var b;
|
||||
var c;
|
||||
var d;
|
||||
a = b;
|
||||
c = d; // Should not be allowed
|
||||
@@ -0,0 +1,16 @@
|
||||
// Regression test for #1002
|
||||
// Before fix this code would cause infinite loop
|
||||
|
||||
interface IObservable<T> {
|
||||
n: IObservable<T[]>; // Needed, must be T[]
|
||||
}
|
||||
|
||||
// Needed
|
||||
interface ISubject<T> extends IObservable<T> { }
|
||||
|
||||
interface Foo { x }
|
||||
interface Bar { y }
|
||||
|
||||
var values: IObservable<Foo>;
|
||||
var values2: ISubject<Bar>;
|
||||
values = values2;
|
||||
@@ -0,0 +1,16 @@
|
||||
// Regression test for #1002
|
||||
// Before fix this code would cause infinite loop
|
||||
|
||||
interface IObservable<T> {
|
||||
n: IObservable<T[]>;
|
||||
}
|
||||
interface ISubject<T> extends IObservable<T> { }
|
||||
|
||||
declare function combineLatest<TOther>(x: IObservable<TOther>[]): void;
|
||||
declare function combineLatest(): void;
|
||||
|
||||
function fn<T>() {
|
||||
var values: ISubject<any>[] = [];
|
||||
// Hang when using <T>, but not <any>
|
||||
combineLatest<T>(values);
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
// Check that we only cache results of type comparisons that are free of assumptions
|
||||
|
||||
interface A {
|
||||
p: C;
|
||||
s: string;
|
||||
}
|
||||
|
||||
interface B {
|
||||
p: D;
|
||||
s: number;
|
||||
}
|
||||
|
||||
interface C {
|
||||
q: A;
|
||||
}
|
||||
|
||||
interface D {
|
||||
q: B;
|
||||
}
|
||||
|
||||
var a: A;
|
||||
var b: B;
|
||||
var c: C;
|
||||
var d: D;
|
||||
|
||||
a = b;
|
||||
c = d; // Should not be allowed
|
||||
Reference in New Issue
Block a user