Skip to content

Always fully compute variance structurally #48080

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 7 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
152 changes: 95 additions & 57 deletions src/compiler/checker.ts

Large diffs are not rendered by default.

44 changes: 21 additions & 23 deletions src/compiler/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5227,7 +5227,6 @@ namespace ts {
pattern?: DestructuringPattern; // Destructuring pattern represented by type (if any)
aliasSymbol?: Symbol; // Alias associated with type
aliasTypeArguments?: readonly Type[]; // Alias type arguments (if any)
/* @internal */ aliasTypeArgumentsContainsMarker?: boolean; // Alias type arguments (if any)
/* @internal */
permissiveInstantiation?: Type; // Instantiation with type parameters mapped to wildcard type
/* @internal */
Expand Down Expand Up @@ -5306,22 +5305,21 @@ namespace ts {
ObjectLiteralPatternWithComputedProperties = 1 << 9, // Object literal pattern with computed properties
ReverseMapped = 1 << 10, // Object contains a property from a reverse-mapped type
JsxAttributes = 1 << 11, // Jsx attributes type
MarkerType = 1 << 12, // Marker type used for variance probing
JSLiteral = 1 << 13, // Object type declared in JS - disables errors on read/write of nonexisting members
FreshLiteral = 1 << 14, // Fresh object literal
ArrayLiteral = 1 << 15, // Originates in an array literal
JSLiteral = 1 << 12, // Object type declared in JS - disables errors on read/write of nonexisting members
FreshLiteral = 1 << 13, // Fresh object literal
ArrayLiteral = 1 << 14, // Originates in an array literal
/* @internal */
PrimitiveUnion = 1 << 16, // Union of only primitive types
PrimitiveUnion = 1 << 15, // Union of only primitive types
/* @internal */
ContainsWideningType = 1 << 17, // Type is or contains undefined or null widening type
ContainsWideningType = 1 << 16, // Type is or contains undefined or null widening type
/* @internal */
ContainsObjectOrArrayLiteral = 1 << 18, // Type is or contains object literal type
ContainsObjectOrArrayLiteral = 1 << 17, // Type is or contains object literal type
/* @internal */
NonInferrableType = 1 << 19, // Type is or contains anyFunctionType or silentNeverType
NonInferrableType = 1 << 18, // Type is or contains anyFunctionType or silentNeverType
/* @internal */
CouldContainTypeVariablesComputed = 1 << 20, // CouldContainTypeVariables flag has been computed
CouldContainTypeVariablesComputed = 1 << 19, // CouldContainTypeVariables flag has been computed
/* @internal */
CouldContainTypeVariables = 1 << 21, // Type could contain a type variable
CouldContainTypeVariables = 1 << 20, // Type could contain a type variable

ClassOrInterface = Class | Interface,
/* @internal */
Expand All @@ -5333,36 +5331,36 @@ namespace ts {
ObjectTypeKindMask = ClassOrInterface | Reference | Tuple | Anonymous | Mapped | ReverseMapped | EvolvingArray,

// Flags that require TypeFlags.Object
ContainsSpread = 1 << 22, // Object literal contains spread operation
ObjectRestType = 1 << 23, // Originates in object rest declaration
InstantiationExpressionType = 1 << 24, // Originates in instantiation expression
ContainsSpread = 1 << 21, // Object literal contains spread operation
ObjectRestType = 1 << 22, // Originates in object rest declaration
InstantiationExpressionType = 1 << 23, // Originates in instantiation expression
/* @internal */
IsClassInstanceClone = 1 << 25, // Type is a clone of a class instance type
IsClassInstanceClone = 1 << 24, // Type is a clone of a class instance type
// Flags that require TypeFlags.Object and ObjectFlags.Reference
/* @internal */
IdenticalBaseTypeCalculated = 1 << 26, // has had `getSingleBaseForNonAugmentingSubtype` invoked on it already
IdenticalBaseTypeCalculated = 1 << 25, // has had `getSingleBaseForNonAugmentingSubtype` invoked on it already
/* @internal */
IdenticalBaseTypeExists = 1 << 27, // has a defined cachedEquivalentBaseType member
IdenticalBaseTypeExists = 1 << 26, // has a defined cachedEquivalentBaseType member

// Flags that require TypeFlags.UnionOrIntersection or TypeFlags.Substitution
/* @internal */
IsGenericTypeComputed = 1 << 22, // IsGenericObjectType flag has been computed
IsGenericTypeComputed = 1 << 21, // IsGenericObjectType flag has been computed
/* @internal */
IsGenericObjectType = 1 << 23, // Union or intersection contains generic object type
IsGenericObjectType = 1 << 22, // Union or intersection contains generic object type
/* @internal */
IsGenericIndexType = 1 << 24, // Union or intersection contains generic index type
IsGenericIndexType = 1 << 23, // Union or intersection contains generic index type
/* @internal */
IsGenericType = IsGenericObjectType | IsGenericIndexType,

// Flags that require TypeFlags.Union
/* @internal */
ContainsIntersections = 1 << 25, // Union contains intersections
ContainsIntersections = 1 << 24, // Union contains intersections

// Flags that require TypeFlags.Intersection
/* @internal */
IsNeverIntersectionComputed = 1 << 25, // IsNeverLike flag has been computed
IsNeverIntersectionComputed = 1 << 24, // IsNeverLike flag has been computed
/* @internal */
IsNeverIntersection = 1 << 26, // Intersection reduces to never
IsNeverIntersection = 1 << 25, // Intersection reduces to never
}

/* @internal */
Expand Down
13 changes: 6 additions & 7 deletions tests/baselines/reference/api/tsserverlibrary.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2654,14 +2654,13 @@ declare namespace ts {
ObjectLiteralPatternWithComputedProperties = 512,
ReverseMapped = 1024,
JsxAttributes = 2048,
MarkerType = 4096,
JSLiteral = 8192,
FreshLiteral = 16384,
ArrayLiteral = 32768,
JSLiteral = 4096,
FreshLiteral = 8192,
ArrayLiteral = 16384,
ClassOrInterface = 3,
ContainsSpread = 4194304,
ObjectRestType = 8388608,
InstantiationExpressionType = 16777216,
ContainsSpread = 2097152,
ObjectRestType = 4194304,
InstantiationExpressionType = 8388608,
}
export interface ObjectType extends Type {
objectFlags: ObjectFlags;
Expand Down
13 changes: 6 additions & 7 deletions tests/baselines/reference/api/typescript.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2654,14 +2654,13 @@ declare namespace ts {
ObjectLiteralPatternWithComputedProperties = 512,
ReverseMapped = 1024,
JsxAttributes = 2048,
MarkerType = 4096,
JSLiteral = 8192,
FreshLiteral = 16384,
ArrayLiteral = 32768,
JSLiteral = 4096,
FreshLiteral = 8192,
ArrayLiteral = 16384,
ClassOrInterface = 3,
ContainsSpread = 4194304,
ObjectRestType = 8388608,
InstantiationExpressionType = 16777216,
ContainsSpread = 2097152,
ObjectRestType = 4194304,
InstantiationExpressionType = 8388608,
}
export interface ObjectType extends Type {
objectFlags: ObjectFlags;
Expand Down
4 changes: 2 additions & 2 deletions tests/baselines/reference/bivariantInferences.symbols
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,8 @@ declare const b: (string | number)[] | null[] | undefined[] | {}[];

let x = a.equalsShallow(b);
>x : Symbol(x, Decl(bivariantInferences.ts, 9, 3))
>a.equalsShallow : Symbol(Array.equalsShallow, Decl(bivariantInferences.ts, 2, 20), Decl(bivariantInferences.ts, 2, 20), Decl(bivariantInferences.ts, 2, 20), Decl(bivariantInferences.ts, 2, 20))
>a.equalsShallow : Symbol(Array.equalsShallow, Decl(bivariantInferences.ts, 2, 20))
>a : Symbol(a, Decl(bivariantInferences.ts, 6, 13))
>equalsShallow : Symbol(Array.equalsShallow, Decl(bivariantInferences.ts, 2, 20), Decl(bivariantInferences.ts, 2, 20), Decl(bivariantInferences.ts, 2, 20), Decl(bivariantInferences.ts, 2, 20))
>equalsShallow : Symbol(Array.equalsShallow, Decl(bivariantInferences.ts, 2, 20))
>b : Symbol(b, Decl(bivariantInferences.ts, 7, 13))

4 changes: 2 additions & 2 deletions tests/baselines/reference/bivariantInferences.types
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,8 @@ declare const b: (string | number)[] | null[] | undefined[] | {}[];
let x = a.equalsShallow(b);
>x : boolean
>a.equalsShallow(b) : boolean
>a.equalsShallow : (<T>(this: readonly T[], other: readonly T[]) => boolean) | (<T>(this: readonly T[], other: readonly T[]) => boolean) | (<T>(this: readonly T[], other: readonly T[]) => boolean) | (<T>(this: readonly T[], other: readonly T[]) => boolean)
>a.equalsShallow : <T>(this: readonly T[], other: readonly T[]) => boolean
>a : (string | number)[] | null[] | undefined[] | {}[]
>equalsShallow : (<T>(this: readonly T[], other: readonly T[]) => boolean) | (<T>(this: readonly T[], other: readonly T[]) => boolean) | (<T>(this: readonly T[], other: readonly T[]) => boolean) | (<T>(this: readonly T[], other: readonly T[]) => boolean)
>equalsShallow : <T>(this: readonly T[], other: readonly T[]) => boolean
>b : (string | number)[] | null[] | undefined[] | {}[]

Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
tests/cases/compiler/checkOrderDependenceGenericAssignability.ts(21,1): error TS2322: Type 'Parent1<unknown>' is not assignable to type 'Parent1<string>'.
Type 'unknown' is not assignable to type 'string'.
tests/cases/compiler/checkOrderDependenceGenericAssignability.ts(45,1): error TS2322: Type 'Parent2<unknown>' is not assignable to type 'Parent2<string>'.
Type 'unknown' is not assignable to type 'string'.
tests/cases/compiler/checkOrderDependenceGenericAssignability.ts(62,1): error TS2322: Type 'Child3<unknown>' is not assignable to type 'Child3<string>'.
Type 'unknown' is not assignable to type 'string'.
tests/cases/compiler/checkOrderDependenceGenericAssignability.ts(68,1): error TS2322: Type 'Parent3<unknown>' is not assignable to type 'Parent3<string>'.
Type 'unknown' is not assignable to type 'string'.


==== tests/cases/compiler/checkOrderDependenceGenericAssignability.ts (4 errors) ====
// Repro from #44572 with interface types

interface Parent1<A> {
child: Child1<A>;
parent: Parent1<A>;
}

interface Child1<A, B = unknown> extends Parent1<A> {
readonly a: A;
readonly b: B;
}

function fn1<A>(inp: Child1<A>) {
const a: Child1<unknown> = inp;
}

declare let pu1: Parent1<unknown>;
declare let ps1: Parent1<string>;

pu1 = ps1; // Ok
ps1 = pu1; // Error expected
~~~
!!! error TS2322: Type 'Parent1<unknown>' is not assignable to type 'Parent1<string>'.
!!! error TS2322: Type 'unknown' is not assignable to type 'string'.

// Repro from #44572 with aliased object types

type Parent2<A> = {
child: Child2<A>;
parent: Parent2<A>;
}

type Child2<A, B = unknown> = {
child: Child2<A>;
parent: Parent2<A>;
readonly a: A;
readonly b: B;
}

function fn2<A>(inp: Child2<A>) {
const a: Child2<unknown> = inp;
}

declare let pu2: Parent2<unknown>;
declare let ps2: Parent2<string>;

pu2 = ps2; // Ok
ps2 = pu2; // Error expected
~~~
!!! error TS2322: Type 'Parent2<unknown>' is not assignable to type 'Parent2<string>'.
!!! error TS2322: Type 'unknown' is not assignable to type 'string'.

// Simpler repro for same issue

interface Parent3<A> {
child: Child3<A[]>;
parent: Parent3<A>;
}

interface Child3<A> extends Parent3<A> {
readonly a: A;
}

declare let cu3: Child3<unknown>;
declare let cs3: Child3<string>;

cu3 = cs3; // Ok
cs3 = cu3; // Error expected
~~~
!!! error TS2322: Type 'Child3<unknown>' is not assignable to type 'Child3<string>'.
!!! error TS2322: Type 'unknown' is not assignable to type 'string'.

declare let pu3: Parent3<unknown>;
declare let ps3: Parent3<string>;

pu3 = ps3; // Ok
ps3 = pu3; // Error expected
~~~
!!! error TS2322: Type 'Parent3<unknown>' is not assignable to type 'Parent3<string>'.
!!! error TS2322: Type 'unknown' is not assignable to type 'string'.

Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
//// [checkOrderDependenceGenericAssignability.ts]
// Repro from #44572 with interface types

interface Parent1<A> {
child: Child1<A>;
parent: Parent1<A>;
}

interface Child1<A, B = unknown> extends Parent1<A> {
readonly a: A;
readonly b: B;
}

function fn1<A>(inp: Child1<A>) {
const a: Child1<unknown> = inp;
}

declare let pu1: Parent1<unknown>;
declare let ps1: Parent1<string>;

pu1 = ps1; // Ok
ps1 = pu1; // Error expected

// Repro from #44572 with aliased object types

type Parent2<A> = {
child: Child2<A>;
parent: Parent2<A>;
}

type Child2<A, B = unknown> = {
child: Child2<A>;
parent: Parent2<A>;
readonly a: A;
readonly b: B;
}

function fn2<A>(inp: Child2<A>) {
const a: Child2<unknown> = inp;
}

declare let pu2: Parent2<unknown>;
declare let ps2: Parent2<string>;

pu2 = ps2; // Ok
ps2 = pu2; // Error expected

// Simpler repro for same issue

interface Parent3<A> {
child: Child3<A[]>;
parent: Parent3<A>;
}

interface Child3<A> extends Parent3<A> {
readonly a: A;
}

declare let cu3: Child3<unknown>;
declare let cs3: Child3<string>;

cu3 = cs3; // Ok
cs3 = cu3; // Error expected

declare let pu3: Parent3<unknown>;
declare let ps3: Parent3<string>;

pu3 = ps3; // Ok
ps3 = pu3; // Error expected


//// [checkOrderDependenceGenericAssignability.js]
"use strict";
// Repro from #44572 with interface types
function fn1(inp) {
var a = inp;
}
pu1 = ps1; // Ok
ps1 = pu1; // Error expected
function fn2(inp) {
var a = inp;
}
pu2 = ps2; // Ok
ps2 = pu2; // Error expected
cu3 = cs3; // Ok
cs3 = cu3; // Error expected
pu3 = ps3; // Ok
ps3 = pu3; // Error expected
Loading