From cf7b19a90d56804138e02f31ee85ed36aeb224dd Mon Sep 17 00:00:00 2001 From: TypeScript Bot Date: Fri, 31 May 2019 16:17:23 -0700 Subject: [PATCH] =?UTF-8?q?=F0=9F=A4=96=20Cherry-pick=20PR=20#31688=20into?= =?UTF-8?q?=20release-3.5=20(#31707)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Component commits: 20c928eb77 Propegate saved variance flags from cached comparisons f21903b7f4 Propegate variance a bit more selectively a007f5613f Add test c45f90f35c Remove now-redundant code b36246df02 Fix misspelling and remove unneeded branch --- src/compiler/checker.ts | 28 +++- .../identicalTypesNoDifferByCheckOrder.js | 55 ++++++++ ...identicalTypesNoDifferByCheckOrder.symbols | 127 ++++++++++++++++++ .../identicalTypesNoDifferByCheckOrder.types | 88 ++++++++++++ .../identicalTypesNoDifferByCheckOrder.ts | 38 ++++++ 5 files changed, 330 insertions(+), 6 deletions(-) create mode 100644 tests/baselines/reference/identicalTypesNoDifferByCheckOrder.js create mode 100644 tests/baselines/reference/identicalTypesNoDifferByCheckOrder.symbols create mode 100644 tests/baselines/reference/identicalTypesNoDifferByCheckOrder.types create mode 100644 tests/cases/compiler/identicalTypesNoDifferByCheckOrder.ts diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 85b3641f0041f..cc10d791f7c02 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -12981,6 +12981,18 @@ namespace ts { return result; } + function propagateSidebandVarianceFlags(typeArguments: readonly Type[], variances: VarianceFlags[]) { + for (let i = 0; i < variances.length; i++) { + const v = variances[i]; + if (v & VarianceFlags.Unmeasurable) { + instantiateType(typeArguments[i], reportUnmeasurableMarkers); + } + if (v & VarianceFlags.Unreliable) { + instantiateType(typeArguments[i], reportUnreliableMarkers); + } + } + } + // Determine if possibly recursive types are related. First, check if the result is already available in the global cache. // Second, check if we have already started a comparison of the given two types in which case we assume the result to be true. // Third, check if both types are part of deeply nested chains of generic type instantiations and if so assume the types are @@ -12998,6 +13010,16 @@ namespace ts { // as a failure, and should be updated as a reported failure by the bottom of this function. } else { + if (outofbandVarianceMarkerHandler) { + // We're in the middle of variance checking - integrate any unmeasurable/unreliable flags from this cached component + if (source.flags & (TypeFlags.Object | TypeFlags.Conditional) && source.aliasSymbol && + source.aliasTypeArguments && source.aliasSymbol === target.aliasSymbol) { + propagateSidebandVarianceFlags(source.aliasTypeArguments, getAliasVariances(source.aliasSymbol)); + } + if (getObjectFlags(source) & ObjectFlags.Reference && getObjectFlags(target) & ObjectFlags.Reference && (source).target === (target).target && length((source).typeArguments)) { + propagateSidebandVarianceFlags((source).typeArguments!, getVariances((source).target)); + } + } return related === RelationComparisonResult.Succeeded ? Ternary.True : Ternary.False; } } @@ -14070,12 +14092,6 @@ namespace ts { if (unreliable) { variance |= VarianceFlags.Unreliable; } - const covariantID = getRelationKey(typeWithSub, typeWithSuper, assignableRelation); - const contravariantID = getRelationKey(typeWithSuper, typeWithSub, assignableRelation); - // We delete the results of these checks, as we want them to actually be run, see the `Unmeasurable` variance we cache, - // And then fall back to a structural result. - assignableRelation.delete(covariantID); - assignableRelation.delete(contravariantID); } variances.push(variance); } diff --git a/tests/baselines/reference/identicalTypesNoDifferByCheckOrder.js b/tests/baselines/reference/identicalTypesNoDifferByCheckOrder.js new file mode 100644 index 0000000000000..a88b29ce254e6 --- /dev/null +++ b/tests/baselines/reference/identicalTypesNoDifferByCheckOrder.js @@ -0,0 +1,55 @@ +//// [identicalTypesNoDifferByCheckOrder.ts] +interface SomeProps { + x?: string; + y?: number; + renderAs?: FunctionComponent1 +} + +type SomePropsX = Required> & Omit; + +interface SomePropsClone { + x?: string; + y?: number; + renderAs?: FunctionComponent2 +} + +type SomePropsCloneX = Required> & Omit; + +type Validator = {(): boolean, opt?: T}; +type WeakValidationMap = {[K in keyof T]?: null extends T[K] ? Validator : Validator}; + +interface FunctionComponent1

{ + (props: P & { children?: unknown }): void; + propTypes?: WeakValidationMap

; +} + +interface FunctionComponent2

{ + (props: P & { children?: unknown }): void; + propTypes?: WeakValidationMap

; +} + +function needsComponentOfSomeProps3(...x: SomePropsClone[]): void {} +const comp3: FunctionComponent2 = null as any; +needsComponentOfSomeProps3({ renderAs: comp3 }); + +function needsComponentOfSomeProps2(...x: SomeProps[]): void {} +const comp2: FunctionComponent1 = null as any; +needsComponentOfSomeProps2({ renderAs: comp2 }); + +//// [identicalTypesNoDifferByCheckOrder.js] +function needsComponentOfSomeProps3() { + var x = []; + for (var _i = 0; _i < arguments.length; _i++) { + x[_i] = arguments[_i]; + } +} +var comp3 = null; +needsComponentOfSomeProps3({ renderAs: comp3 }); +function needsComponentOfSomeProps2() { + var x = []; + for (var _i = 0; _i < arguments.length; _i++) { + x[_i] = arguments[_i]; + } +} +var comp2 = null; +needsComponentOfSomeProps2({ renderAs: comp2 }); diff --git a/tests/baselines/reference/identicalTypesNoDifferByCheckOrder.symbols b/tests/baselines/reference/identicalTypesNoDifferByCheckOrder.symbols new file mode 100644 index 0000000000000..6850276d3408e --- /dev/null +++ b/tests/baselines/reference/identicalTypesNoDifferByCheckOrder.symbols @@ -0,0 +1,127 @@ +=== tests/cases/compiler/identicalTypesNoDifferByCheckOrder.ts === +interface SomeProps { +>SomeProps : Symbol(SomeProps, Decl(identicalTypesNoDifferByCheckOrder.ts, 0, 0)) + + x?: string; +>x : Symbol(SomeProps.x, Decl(identicalTypesNoDifferByCheckOrder.ts, 0, 21)) + + y?: number; +>y : Symbol(SomeProps.y, Decl(identicalTypesNoDifferByCheckOrder.ts, 1, 15)) + + renderAs?: FunctionComponent1 +>renderAs : Symbol(SomeProps.renderAs, Decl(identicalTypesNoDifferByCheckOrder.ts, 2, 15)) +>FunctionComponent1 : Symbol(FunctionComponent1, Decl(identicalTypesNoDifferByCheckOrder.ts, 17, 120)) +>SomeProps : Symbol(SomeProps, Decl(identicalTypesNoDifferByCheckOrder.ts, 0, 0)) +} + +type SomePropsX = Required> & Omit; +>SomePropsX : Symbol(SomePropsX, Decl(identicalTypesNoDifferByCheckOrder.ts, 4, 1)) +>Required : Symbol(Required, Decl(lib.es5.d.ts, --, --)) +>Pick : Symbol(Pick, Decl(lib.es5.d.ts, --, --)) +>SomeProps : Symbol(SomeProps, Decl(identicalTypesNoDifferByCheckOrder.ts, 0, 0)) +>Omit : Symbol(Omit, Decl(lib.es5.d.ts, --, --)) +>SomeProps : Symbol(SomeProps, Decl(identicalTypesNoDifferByCheckOrder.ts, 0, 0)) + +interface SomePropsClone { +>SomePropsClone : Symbol(SomePropsClone, Decl(identicalTypesNoDifferByCheckOrder.ts, 6, 72)) + + x?: string; +>x : Symbol(SomePropsClone.x, Decl(identicalTypesNoDifferByCheckOrder.ts, 8, 26)) + + y?: number; +>y : Symbol(SomePropsClone.y, Decl(identicalTypesNoDifferByCheckOrder.ts, 9, 15)) + + renderAs?: FunctionComponent2 +>renderAs : Symbol(SomePropsClone.renderAs, Decl(identicalTypesNoDifferByCheckOrder.ts, 10, 15)) +>FunctionComponent2 : Symbol(FunctionComponent2, Decl(identicalTypesNoDifferByCheckOrder.ts, 22, 1)) +>SomeProps : Symbol(SomeProps, Decl(identicalTypesNoDifferByCheckOrder.ts, 0, 0)) +} + +type SomePropsCloneX = Required> & Omit; +>SomePropsCloneX : Symbol(SomePropsCloneX, Decl(identicalTypesNoDifferByCheckOrder.ts, 12, 1)) +>Required : Symbol(Required, Decl(lib.es5.d.ts, --, --)) +>Pick : Symbol(Pick, Decl(lib.es5.d.ts, --, --)) +>SomePropsClone : Symbol(SomePropsClone, Decl(identicalTypesNoDifferByCheckOrder.ts, 6, 72)) +>Omit : Symbol(Omit, Decl(lib.es5.d.ts, --, --)) +>SomePropsClone : Symbol(SomePropsClone, Decl(identicalTypesNoDifferByCheckOrder.ts, 6, 72)) + +type Validator = {(): boolean, opt?: T}; +>Validator : Symbol(Validator, Decl(identicalTypesNoDifferByCheckOrder.ts, 14, 87)) +>T : Symbol(T, Decl(identicalTypesNoDifferByCheckOrder.ts, 16, 15)) +>opt : Symbol(opt, Decl(identicalTypesNoDifferByCheckOrder.ts, 16, 33)) +>T : Symbol(T, Decl(identicalTypesNoDifferByCheckOrder.ts, 16, 15)) + +type WeakValidationMap = {[K in keyof T]?: null extends T[K] ? Validator : Validator}; +>WeakValidationMap : Symbol(WeakValidationMap, Decl(identicalTypesNoDifferByCheckOrder.ts, 16, 43)) +>T : Symbol(T, Decl(identicalTypesNoDifferByCheckOrder.ts, 17, 23)) +>K : Symbol(K, Decl(identicalTypesNoDifferByCheckOrder.ts, 17, 30)) +>T : Symbol(T, Decl(identicalTypesNoDifferByCheckOrder.ts, 17, 23)) +>T : Symbol(T, Decl(identicalTypesNoDifferByCheckOrder.ts, 17, 23)) +>K : Symbol(K, Decl(identicalTypesNoDifferByCheckOrder.ts, 17, 30)) +>Validator : Symbol(Validator, Decl(identicalTypesNoDifferByCheckOrder.ts, 14, 87)) +>T : Symbol(T, Decl(identicalTypesNoDifferByCheckOrder.ts, 17, 23)) +>K : Symbol(K, Decl(identicalTypesNoDifferByCheckOrder.ts, 17, 30)) +>Validator : Symbol(Validator, Decl(identicalTypesNoDifferByCheckOrder.ts, 14, 87)) +>T : Symbol(T, Decl(identicalTypesNoDifferByCheckOrder.ts, 17, 23)) +>K : Symbol(K, Decl(identicalTypesNoDifferByCheckOrder.ts, 17, 30)) + +interface FunctionComponent1

{ +>FunctionComponent1 : Symbol(FunctionComponent1, Decl(identicalTypesNoDifferByCheckOrder.ts, 17, 120)) +>P : Symbol(P, Decl(identicalTypesNoDifferByCheckOrder.ts, 19, 29)) + + (props: P & { children?: unknown }): void; +>props : Symbol(props, Decl(identicalTypesNoDifferByCheckOrder.ts, 20, 5)) +>P : Symbol(P, Decl(identicalTypesNoDifferByCheckOrder.ts, 19, 29)) +>children : Symbol(children, Decl(identicalTypesNoDifferByCheckOrder.ts, 20, 17)) + + propTypes?: WeakValidationMap

; +>propTypes : Symbol(FunctionComponent1.propTypes, Decl(identicalTypesNoDifferByCheckOrder.ts, 20, 46)) +>WeakValidationMap : Symbol(WeakValidationMap, Decl(identicalTypesNoDifferByCheckOrder.ts, 16, 43)) +>P : Symbol(P, Decl(identicalTypesNoDifferByCheckOrder.ts, 19, 29)) +} + +interface FunctionComponent2

{ +>FunctionComponent2 : Symbol(FunctionComponent2, Decl(identicalTypesNoDifferByCheckOrder.ts, 22, 1)) +>P : Symbol(P, Decl(identicalTypesNoDifferByCheckOrder.ts, 24, 29)) + + (props: P & { children?: unknown }): void; +>props : Symbol(props, Decl(identicalTypesNoDifferByCheckOrder.ts, 25, 5)) +>P : Symbol(P, Decl(identicalTypesNoDifferByCheckOrder.ts, 24, 29)) +>children : Symbol(children, Decl(identicalTypesNoDifferByCheckOrder.ts, 25, 17)) + + propTypes?: WeakValidationMap

; +>propTypes : Symbol(FunctionComponent2.propTypes, Decl(identicalTypesNoDifferByCheckOrder.ts, 25, 46)) +>WeakValidationMap : Symbol(WeakValidationMap, Decl(identicalTypesNoDifferByCheckOrder.ts, 16, 43)) +>P : Symbol(P, Decl(identicalTypesNoDifferByCheckOrder.ts, 24, 29)) +} + +function needsComponentOfSomeProps3(...x: SomePropsClone[]): void {} +>needsComponentOfSomeProps3 : Symbol(needsComponentOfSomeProps3, Decl(identicalTypesNoDifferByCheckOrder.ts, 27, 1)) +>x : Symbol(x, Decl(identicalTypesNoDifferByCheckOrder.ts, 29, 36)) +>SomePropsClone : Symbol(SomePropsClone, Decl(identicalTypesNoDifferByCheckOrder.ts, 6, 72)) + +const comp3: FunctionComponent2 = null as any; +>comp3 : Symbol(comp3, Decl(identicalTypesNoDifferByCheckOrder.ts, 30, 5)) +>FunctionComponent2 : Symbol(FunctionComponent2, Decl(identicalTypesNoDifferByCheckOrder.ts, 22, 1)) +>SomePropsCloneX : Symbol(SomePropsCloneX, Decl(identicalTypesNoDifferByCheckOrder.ts, 12, 1)) + +needsComponentOfSomeProps3({ renderAs: comp3 }); +>needsComponentOfSomeProps3 : Symbol(needsComponentOfSomeProps3, Decl(identicalTypesNoDifferByCheckOrder.ts, 27, 1)) +>renderAs : Symbol(renderAs, Decl(identicalTypesNoDifferByCheckOrder.ts, 31, 28)) +>comp3 : Symbol(comp3, Decl(identicalTypesNoDifferByCheckOrder.ts, 30, 5)) + +function needsComponentOfSomeProps2(...x: SomeProps[]): void {} +>needsComponentOfSomeProps2 : Symbol(needsComponentOfSomeProps2, Decl(identicalTypesNoDifferByCheckOrder.ts, 31, 48)) +>x : Symbol(x, Decl(identicalTypesNoDifferByCheckOrder.ts, 33, 36)) +>SomeProps : Symbol(SomeProps, Decl(identicalTypesNoDifferByCheckOrder.ts, 0, 0)) + +const comp2: FunctionComponent1 = null as any; +>comp2 : Symbol(comp2, Decl(identicalTypesNoDifferByCheckOrder.ts, 34, 5)) +>FunctionComponent1 : Symbol(FunctionComponent1, Decl(identicalTypesNoDifferByCheckOrder.ts, 17, 120)) +>SomePropsX : Symbol(SomePropsX, Decl(identicalTypesNoDifferByCheckOrder.ts, 4, 1)) + +needsComponentOfSomeProps2({ renderAs: comp2 }); +>needsComponentOfSomeProps2 : Symbol(needsComponentOfSomeProps2, Decl(identicalTypesNoDifferByCheckOrder.ts, 31, 48)) +>renderAs : Symbol(renderAs, Decl(identicalTypesNoDifferByCheckOrder.ts, 35, 28)) +>comp2 : Symbol(comp2, Decl(identicalTypesNoDifferByCheckOrder.ts, 34, 5)) + diff --git a/tests/baselines/reference/identicalTypesNoDifferByCheckOrder.types b/tests/baselines/reference/identicalTypesNoDifferByCheckOrder.types new file mode 100644 index 0000000000000..e4c691c6b952f --- /dev/null +++ b/tests/baselines/reference/identicalTypesNoDifferByCheckOrder.types @@ -0,0 +1,88 @@ +=== tests/cases/compiler/identicalTypesNoDifferByCheckOrder.ts === +interface SomeProps { + x?: string; +>x : string | undefined + + y?: number; +>y : number | undefined + + renderAs?: FunctionComponent1 +>renderAs : FunctionComponent1 | undefined +} + +type SomePropsX = Required> & Omit; +>SomePropsX : SomePropsX + +interface SomePropsClone { + x?: string; +>x : string | undefined + + y?: number; +>y : number | undefined + + renderAs?: FunctionComponent2 +>renderAs : FunctionComponent2 | undefined +} + +type SomePropsCloneX = Required> & Omit; +>SomePropsCloneX : SomePropsCloneX + +type Validator = {(): boolean, opt?: T}; +>Validator : Validator +>opt : T | undefined + +type WeakValidationMap = {[K in keyof T]?: null extends T[K] ? Validator : Validator}; +>WeakValidationMap : WeakValidationMap +>null : null +>null : null + +interface FunctionComponent1

{ + (props: P & { children?: unknown }): void; +>props : P & { children?: unknown; } +>children : unknown + + propTypes?: WeakValidationMap

; +>propTypes : WeakValidationMap

| undefined +} + +interface FunctionComponent2

{ + (props: P & { children?: unknown }): void; +>props : P & { children?: unknown; } +>children : unknown + + propTypes?: WeakValidationMap

; +>propTypes : WeakValidationMap

| undefined +} + +function needsComponentOfSomeProps3(...x: SomePropsClone[]): void {} +>needsComponentOfSomeProps3 : (...x: SomePropsClone[]) => void +>x : SomePropsClone[] + +const comp3: FunctionComponent2 = null as any; +>comp3 : FunctionComponent2 +>null as any : any +>null : null + +needsComponentOfSomeProps3({ renderAs: comp3 }); +>needsComponentOfSomeProps3({ renderAs: comp3 }) : void +>needsComponentOfSomeProps3 : (...x: SomePropsClone[]) => void +>{ renderAs: comp3 } : { renderAs: FunctionComponent2; } +>renderAs : FunctionComponent2 +>comp3 : FunctionComponent2 + +function needsComponentOfSomeProps2(...x: SomeProps[]): void {} +>needsComponentOfSomeProps2 : (...x: SomeProps[]) => void +>x : SomeProps[] + +const comp2: FunctionComponent1 = null as any; +>comp2 : FunctionComponent1 +>null as any : any +>null : null + +needsComponentOfSomeProps2({ renderAs: comp2 }); +>needsComponentOfSomeProps2({ renderAs: comp2 }) : void +>needsComponentOfSomeProps2 : (...x: SomeProps[]) => void +>{ renderAs: comp2 } : { renderAs: FunctionComponent1; } +>renderAs : FunctionComponent1 +>comp2 : FunctionComponent1 + diff --git a/tests/cases/compiler/identicalTypesNoDifferByCheckOrder.ts b/tests/cases/compiler/identicalTypesNoDifferByCheckOrder.ts new file mode 100644 index 0000000000000..fbdf373a407df --- /dev/null +++ b/tests/cases/compiler/identicalTypesNoDifferByCheckOrder.ts @@ -0,0 +1,38 @@ +// @strictNullChecks: true + +interface SomeProps { + x?: string; + y?: number; + renderAs?: FunctionComponent1 +} + +type SomePropsX = Required> & Omit; + +interface SomePropsClone { + x?: string; + y?: number; + renderAs?: FunctionComponent2 +} + +type SomePropsCloneX = Required> & Omit; + +type Validator = {(): boolean, opt?: T}; +type WeakValidationMap = {[K in keyof T]?: null extends T[K] ? Validator : Validator}; + +interface FunctionComponent1

{ + (props: P & { children?: unknown }): void; + propTypes?: WeakValidationMap

; +} + +interface FunctionComponent2

{ + (props: P & { children?: unknown }): void; + propTypes?: WeakValidationMap

; +} + +function needsComponentOfSomeProps3(...x: SomePropsClone[]): void {} +const comp3: FunctionComponent2 = null as any; +needsComponentOfSomeProps3({ renderAs: comp3 }); + +function needsComponentOfSomeProps2(...x: SomeProps[]): void {} +const comp2: FunctionComponent1 = null as any; +needsComponentOfSomeProps2({ renderAs: comp2 }); \ No newline at end of file