diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index b764348cc6f10..c9ba83b15b9e4 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -18791,10 +18791,11 @@ namespace ts { // type references (which are intended by be compared structurally). Obtain the variance // information for the type parameters and relate the type arguments accordingly. const variances = getVariances((source as TypeReference).target); - // We return Ternary.Maybe for a recursive invocation of getVariances (signalled by emptyArray). This + // We return Ternary.Unknown for a recursive invocation of getVariances (signalled by emptyArray). This // effectively means we measure variance only from type parameter occurrences that aren't nested in // recursive instantiations of the generic type. if (variances === emptyArray) { + outofbandVarianceMarkerHandler!(/*onlyUnreliable*/ false); return Ternary.Unknown; } const varianceResult = relateVariances(getTypeArguments(source as TypeReference), getTypeArguments(target as TypeReference), variances, intersectionState); @@ -19756,7 +19757,7 @@ namespace ts { outofbandVarianceMarkerHandler = oldHandler; if (unmeasurable || unreliable) { if (unmeasurable) { - variance |= VarianceFlags.Unmeasurable; + variance = VarianceFlags.Unmeasurable; } if (unreliable) { variance |= VarianceFlags.Unreliable; diff --git a/tests/baselines/reference/checkOrderDependenceGenericAssignability.errors.txt b/tests/baselines/reference/checkOrderDependenceGenericAssignability.errors.txt new file mode 100644 index 0000000000000..c3b30a5f9aaab --- /dev/null +++ b/tests/baselines/reference/checkOrderDependenceGenericAssignability.errors.txt @@ -0,0 +1,35 @@ +tests/cases/compiler/checkOrderDependenceGenericAssignability.ts(24,7): error TS2322: Type 'Parent' is not assignable to type 'Parent'. + The types of 'child.a' are incompatible between these types. + Type 'unknown' is not assignable to type 'string'. + + +==== tests/cases/compiler/checkOrderDependenceGenericAssignability.ts (1 errors) ==== + // #44572 + + interface Parent { + child: Child | null; + parent: Parent | null; + } + + interface Child extends Parent { + readonly a: A; + // This field isn't necessary to the repro, but the + // type parameter is, so including it + readonly b: B; + } + + function fn(inp: Child) { + // This assignability check defeats the later one + const a: Child = inp; + } + + // Allowed initialization of pu + const pu: Parent = { child: { a: 0, b: 0, child: null, parent: null }, parent: null }; + + // Should error + const notString: Parent = pu; + ~~~~~~~~~ +!!! error TS2322: Type 'Parent' is not assignable to type 'Parent'. +!!! error TS2322: The types of 'child.a' are incompatible between these types. +!!! error TS2322: Type 'unknown' is not assignable to type 'string'. + \ No newline at end of file diff --git a/tests/baselines/reference/checkOrderDependenceGenericAssignability.js b/tests/baselines/reference/checkOrderDependenceGenericAssignability.js new file mode 100644 index 0000000000000..4dcb50ee44408 --- /dev/null +++ b/tests/baselines/reference/checkOrderDependenceGenericAssignability.js @@ -0,0 +1,37 @@ +//// [checkOrderDependenceGenericAssignability.ts] +// #44572 + +interface Parent { + child: Child | null; + parent: Parent | null; +} + +interface Child extends Parent { + readonly a: A; + // This field isn't necessary to the repro, but the + // type parameter is, so including it + readonly b: B; +} + +function fn(inp: Child) { + // This assignability check defeats the later one + const a: Child = inp; +} + +// Allowed initialization of pu +const pu: Parent = { child: { a: 0, b: 0, child: null, parent: null }, parent: null }; + +// Should error +const notString: Parent = pu; + + +//// [checkOrderDependenceGenericAssignability.js] +// #44572 +function fn(inp) { + // This assignability check defeats the later one + var a = inp; +} +// Allowed initialization of pu +var pu = { child: { a: 0, b: 0, child: null, parent: null }, parent: null }; +// Should error +var notString = pu; diff --git a/tests/baselines/reference/checkOrderDependenceGenericAssignability.symbols b/tests/baselines/reference/checkOrderDependenceGenericAssignability.symbols new file mode 100644 index 0000000000000..ad9be4689614f --- /dev/null +++ b/tests/baselines/reference/checkOrderDependenceGenericAssignability.symbols @@ -0,0 +1,67 @@ +=== tests/cases/compiler/checkOrderDependenceGenericAssignability.ts === +// #44572 + +interface Parent { +>Parent : Symbol(Parent, Decl(checkOrderDependenceGenericAssignability.ts, 0, 0)) +>A : Symbol(A, Decl(checkOrderDependenceGenericAssignability.ts, 2, 17)) + + child: Child | null; +>child : Symbol(Parent.child, Decl(checkOrderDependenceGenericAssignability.ts, 2, 21)) +>Child : Symbol(Child, Decl(checkOrderDependenceGenericAssignability.ts, 5, 1)) +>A : Symbol(A, Decl(checkOrderDependenceGenericAssignability.ts, 2, 17)) + + parent: Parent | null; +>parent : Symbol(Parent.parent, Decl(checkOrderDependenceGenericAssignability.ts, 3, 25)) +>Parent : Symbol(Parent, Decl(checkOrderDependenceGenericAssignability.ts, 0, 0)) +>A : Symbol(A, Decl(checkOrderDependenceGenericAssignability.ts, 2, 17)) +} + +interface Child extends Parent { +>Child : Symbol(Child, Decl(checkOrderDependenceGenericAssignability.ts, 5, 1)) +>A : Symbol(A, Decl(checkOrderDependenceGenericAssignability.ts, 7, 16)) +>B : Symbol(B, Decl(checkOrderDependenceGenericAssignability.ts, 7, 18)) +>Parent : Symbol(Parent, Decl(checkOrderDependenceGenericAssignability.ts, 0, 0)) +>A : Symbol(A, Decl(checkOrderDependenceGenericAssignability.ts, 7, 16)) + + readonly a: A; +>a : Symbol(Child.a, Decl(checkOrderDependenceGenericAssignability.ts, 7, 51)) +>A : Symbol(A, Decl(checkOrderDependenceGenericAssignability.ts, 7, 16)) + + // This field isn't necessary to the repro, but the + // type parameter is, so including it + readonly b: B; +>b : Symbol(Child.b, Decl(checkOrderDependenceGenericAssignability.ts, 8, 16)) +>B : Symbol(B, Decl(checkOrderDependenceGenericAssignability.ts, 7, 18)) +} + +function fn(inp: Child) { +>fn : Symbol(fn, Decl(checkOrderDependenceGenericAssignability.ts, 12, 1)) +>A : Symbol(A, Decl(checkOrderDependenceGenericAssignability.ts, 14, 12)) +>inp : Symbol(inp, Decl(checkOrderDependenceGenericAssignability.ts, 14, 15)) +>Child : Symbol(Child, Decl(checkOrderDependenceGenericAssignability.ts, 5, 1)) +>A : Symbol(A, Decl(checkOrderDependenceGenericAssignability.ts, 14, 12)) + + // This assignability check defeats the later one + const a: Child = inp; +>a : Symbol(a, Decl(checkOrderDependenceGenericAssignability.ts, 16, 7)) +>Child : Symbol(Child, Decl(checkOrderDependenceGenericAssignability.ts, 5, 1)) +>inp : Symbol(inp, Decl(checkOrderDependenceGenericAssignability.ts, 14, 15)) +} + +// Allowed initialization of pu +const pu: Parent = { child: { a: 0, b: 0, child: null, parent: null }, parent: null }; +>pu : Symbol(pu, Decl(checkOrderDependenceGenericAssignability.ts, 20, 5)) +>Parent : Symbol(Parent, Decl(checkOrderDependenceGenericAssignability.ts, 0, 0)) +>child : Symbol(child, Decl(checkOrderDependenceGenericAssignability.ts, 20, 29)) +>a : Symbol(a, Decl(checkOrderDependenceGenericAssignability.ts, 20, 38)) +>b : Symbol(b, Decl(checkOrderDependenceGenericAssignability.ts, 20, 44)) +>child : Symbol(child, Decl(checkOrderDependenceGenericAssignability.ts, 20, 50)) +>parent : Symbol(parent, Decl(checkOrderDependenceGenericAssignability.ts, 20, 63)) +>parent : Symbol(parent, Decl(checkOrderDependenceGenericAssignability.ts, 20, 79)) + +// Should error +const notString: Parent = pu; +>notString : Symbol(notString, Decl(checkOrderDependenceGenericAssignability.ts, 23, 5)) +>Parent : Symbol(Parent, Decl(checkOrderDependenceGenericAssignability.ts, 0, 0)) +>pu : Symbol(pu, Decl(checkOrderDependenceGenericAssignability.ts, 20, 5)) + diff --git a/tests/baselines/reference/checkOrderDependenceGenericAssignability.types b/tests/baselines/reference/checkOrderDependenceGenericAssignability.types new file mode 100644 index 0000000000000..5bbdeb742ac41 --- /dev/null +++ b/tests/baselines/reference/checkOrderDependenceGenericAssignability.types @@ -0,0 +1,55 @@ +=== tests/cases/compiler/checkOrderDependenceGenericAssignability.ts === +// #44572 + +interface Parent { + child: Child | null; +>child : Child +>null : null + + parent: Parent | null; +>parent : Parent +>null : null +} + +interface Child extends Parent { + readonly a: A; +>a : A + + // This field isn't necessary to the repro, but the + // type parameter is, so including it + readonly b: B; +>b : B +} + +function fn(inp: Child) { +>fn : (inp: Child) => void +>inp : Child + + // This assignability check defeats the later one + const a: Child = inp; +>a : Child +>inp : Child +} + +// Allowed initialization of pu +const pu: Parent = { child: { a: 0, b: 0, child: null, parent: null }, parent: null }; +>pu : Parent +>{ child: { a: 0, b: 0, child: null, parent: null }, parent: null } : { child: { a: number; b: number; child: null; parent: null; }; parent: null; } +>child : { a: number; b: number; child: null; parent: null; } +>{ a: 0, b: 0, child: null, parent: null } : { a: number; b: number; child: null; parent: null; } +>a : number +>0 : 0 +>b : number +>0 : 0 +>child : null +>null : null +>parent : null +>null : null +>parent : null +>null : null + +// Should error +const notString: Parent = pu; +>notString : Parent +>pu : Parent + diff --git a/tests/baselines/reference/objectTypeWithRecursiveWrappedProperty.errors.txt b/tests/baselines/reference/objectTypeWithRecursiveWrappedProperty.errors.txt index 582d7719a8976..e70e142573428 100644 --- a/tests/baselines/reference/objectTypeWithRecursiveWrappedProperty.errors.txt +++ b/tests/baselines/reference/objectTypeWithRecursiveWrappedProperty.errors.txt @@ -1,5 +1,6 @@ tests/cases/conformance/types/typeRelationships/recursiveTypes/objectTypeWithRecursiveWrappedProperty.ts(13,1): error TS2322: Type 'List' is not assignable to type 'List'. - Type 'string' is not assignable to type 'number'. + Types of property 'data' are incompatible. + Type 'string' is not assignable to type 'number'. ==== tests/cases/conformance/types/typeRelationships/recursiveTypes/objectTypeWithRecursiveWrappedProperty.ts (1 errors) ==== @@ -18,4 +19,5 @@ tests/cases/conformance/types/typeRelationships/recursiveTypes/objectTypeWithRec list1 = list3; // error ~~~~~ !!! error TS2322: Type 'List' is not assignable to type 'List'. -!!! error TS2322: Type 'string' is not assignable to type 'number'. \ No newline at end of file +!!! error TS2322: Types of property 'data' are incompatible. +!!! error TS2322: Type 'string' is not assignable to type 'number'. \ No newline at end of file diff --git a/tests/baselines/reference/objectTypeWithRecursiveWrappedProperty2.errors.txt b/tests/baselines/reference/objectTypeWithRecursiveWrappedProperty2.errors.txt index 6349a4528213a..a3905028d0dff 100644 --- a/tests/baselines/reference/objectTypeWithRecursiveWrappedProperty2.errors.txt +++ b/tests/baselines/reference/objectTypeWithRecursiveWrappedProperty2.errors.txt @@ -1,5 +1,6 @@ tests/cases/conformance/types/typeRelationships/recursiveTypes/objectTypeWithRecursiveWrappedProperty2.ts(13,1): error TS2322: Type 'List' is not assignable to type 'List'. - Type 'string' is not assignable to type 'number'. + Types of property 'data' are incompatible. + Type 'string' is not assignable to type 'number'. ==== tests/cases/conformance/types/typeRelationships/recursiveTypes/objectTypeWithRecursiveWrappedProperty2.ts (1 errors) ==== @@ -18,4 +19,5 @@ tests/cases/conformance/types/typeRelationships/recursiveTypes/objectTypeWithRec list1 = list3; // error ~~~~~ !!! error TS2322: Type 'List' is not assignable to type 'List'. -!!! error TS2322: Type 'string' is not assignable to type 'number'. \ No newline at end of file +!!! error TS2322: Types of property 'data' are incompatible. +!!! error TS2322: Type 'string' is not assignable to type 'number'. \ No newline at end of file diff --git a/tests/baselines/reference/varianceMeasurement.errors.txt b/tests/baselines/reference/varianceMeasurement.errors.txt index 4deb2d81e0b64..0869519529776 100644 --- a/tests/baselines/reference/varianceMeasurement.errors.txt +++ b/tests/baselines/reference/varianceMeasurement.errors.txt @@ -1,5 +1,11 @@ tests/cases/compiler/varianceMeasurement.ts(10,7): error TS2322: Type 'Foo1' is not assignable to type 'Foo1<"a">'. - Type 'string' is not assignable to type '"a"'. + Types of property 'x' are incompatible. + Type 'string' is not assignable to type '"a"'. +tests/cases/compiler/varianceMeasurement.ts(11,7): error TS2322: Type 'Foo1' is not assignable to type 'Foo1'. + The types of 'y.x' are incompatible between these types. + Type '(arg: string) => void' is not assignable to type '(arg: unknown) => void'. + Types of parameters 'arg' and 'arg' are incompatible. + Type 'unknown' is not assignable to type 'string'. tests/cases/compiler/varianceMeasurement.ts(21,7): error TS2322: Type 'Foo2' is not assignable to type 'Foo2<"a">'. Types of property 'x' are incompatible. Type 'string' is not assignable to type '"a"'. @@ -19,14 +25,17 @@ tests/cases/compiler/varianceMeasurement.ts(45,7): error TS2322: Type 'Foo4' is not assignable to type 'Fn'. - Type 'unknown' is not assignable to type 'string'. + The types returned by 'then(...)' are incompatible between these types. + Type 'Fn' is not assignable to type 'Fn'. + Types of parameters 'a' and 'a' are incompatible. + Type 'unknown' is not assignable to type 'string'. tests/cases/compiler/varianceMeasurement.ts(62,7): error TS2322: Type 'Fn' is not assignable to type 'Fn'. Type 'number' is not assignable to type '0'. tests/cases/compiler/varianceMeasurement.ts(75,7): error TS2322: Type 'C' is not assignable to type 'C'. Type 'number' is not assignable to type 'string'. -==== tests/cases/compiler/varianceMeasurement.ts (9 errors) ==== +==== tests/cases/compiler/varianceMeasurement.ts (10 errors) ==== // The type below should be invariant in T but is measured as covariant because // we don't analyze recursive references. @@ -39,8 +48,15 @@ tests/cases/compiler/varianceMeasurement.ts(75,7): error TS2322: Type 'C = f10; ~~~ !!! error TS2322: Type 'Foo1' is not assignable to type 'Foo1<"a">'. -!!! error TS2322: Type 'string' is not assignable to type '"a"'. +!!! error TS2322: Types of property 'x' are incompatible. +!!! error TS2322: Type 'string' is not assignable to type '"a"'. const f12: Foo1 = f10; + ~~~ +!!! error TS2322: Type 'Foo1' is not assignable to type 'Foo1'. +!!! error TS2322: The types of 'y.x' are incompatible between these types. +!!! error TS2322: Type '(arg: string) => void' is not assignable to type '(arg: unknown) => void'. +!!! error TS2322: Types of parameters 'arg' and 'arg' are incompatible. +!!! error TS2322: Type 'unknown' is not assignable to type 'string'. // The type below is invariant in T and is measured as such. @@ -112,7 +128,10 @@ tests/cases/compiler/varianceMeasurement.ts(75,7): error TS2322: Type 'C = fn; // Error ~~~ !!! error TS2322: Type 'Fn' is not assignable to type 'Fn'. -!!! error TS2322: Type 'unknown' is not assignable to type 'string'. +!!! error TS2322: The types returned by 'then(...)' are incompatible between these types. +!!! error TS2322: Type 'Fn' is not assignable to type 'Fn'. +!!! error TS2322: Types of parameters 'a' and 'a' are incompatible. +!!! error TS2322: Type 'unknown' is not assignable to type 'string'. const fn2: Fn<'a', number> = fn; // Covariant in B diff --git a/tests/cases/compiler/checkOrderDependenceGenericAssignability.ts b/tests/cases/compiler/checkOrderDependenceGenericAssignability.ts new file mode 100644 index 0000000000000..508b1f3d8406d --- /dev/null +++ b/tests/cases/compiler/checkOrderDependenceGenericAssignability.ts @@ -0,0 +1,24 @@ +// #44572 + +interface Parent { + child: Child | null; + parent: Parent | null; +} + +interface Child extends Parent { + readonly a: A; + // This field isn't necessary to the repro, but the + // type parameter is, so including it + readonly b: B; +} + +function fn(inp: Child) { + // This assignability check defeats the later one + const a: Child = inp; +} + +// Allowed initialization of pu +const pu: Parent = { child: { a: 0, b: 0, child: null, parent: null }, parent: null }; + +// Should error +const notString: Parent = pu;