Merge pull request #19774 from Microsoft/fixInvariantGenericErrors
Fix invariant generic error elaboration logic
This commit is contained in:
commit
7a4808a89e
|
@ -9451,6 +9451,7 @@ namespace ts {
|
|||
|
||||
function structuredTypeRelatedTo(source: Type, target: Type, reportErrors: boolean): Ternary {
|
||||
let result: Ternary;
|
||||
let originalErrorInfo: DiagnosticMessageChain;
|
||||
const saveErrorInfo = errorInfo;
|
||||
if (target.flags & TypeFlags.TypeParameter) {
|
||||
// A source type { [P in keyof T]: X } is related to a target type T if X is related to T[P].
|
||||
|
@ -9530,6 +9531,7 @@ namespace ts {
|
|||
// if we have indexed access types with identical index types, see if relationship holds for
|
||||
// the two object types.
|
||||
if (result = isRelatedTo((<IndexedAccessType>source).objectType, (<IndexedAccessType>target).objectType, reportErrors)) {
|
||||
errorInfo = saveErrorInfo;
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
@ -9561,6 +9563,10 @@ namespace ts {
|
|||
if (!(reportErrors && some(variances, v => v === Variance.Invariant))) {
|
||||
return Ternary.False;
|
||||
}
|
||||
// We remember the original error information so we can restore it in case the structural
|
||||
// comparison unexpectedly succeeds. This can happen when the structural comparison result
|
||||
// is a Ternary.Maybe for example caused by the recursion depth limiter.
|
||||
originalErrorInfo = errorInfo;
|
||||
errorInfo = saveErrorInfo;
|
||||
}
|
||||
}
|
||||
|
@ -9599,8 +9605,11 @@ namespace ts {
|
|||
}
|
||||
}
|
||||
if (result) {
|
||||
errorInfo = saveErrorInfo;
|
||||
return result;
|
||||
if (!originalErrorInfo) {
|
||||
errorInfo = saveErrorInfo;
|
||||
return result;
|
||||
}
|
||||
errorInfo = originalErrorInfo;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,54 @@
|
|||
tests/cases/compiler/invariantGenericErrorElaboration.ts(3,7): error TS2322: Type 'Num' is not assignable to type 'Runtype<any>'.
|
||||
Types of property 'constraint' are incompatible.
|
||||
Type 'Constraint<Num>' is not assignable to type 'Constraint<Runtype<any>>'.
|
||||
Types of property 'constraint' are incompatible.
|
||||
Type 'Constraint<Constraint<Num>>' is not assignable to type 'Constraint<Constraint<Runtype<any>>>'.
|
||||
Types of property 'constraint' are incompatible.
|
||||
Type 'Constraint<Constraint<Constraint<Num>>>' is not assignable to type 'Constraint<Constraint<Constraint<Runtype<any>>>>'.
|
||||
Type 'Constraint<Constraint<Runtype<any>>>' is not assignable to type 'Constraint<Constraint<Num>>'.
|
||||
Types of property 'underlying' are incompatible.
|
||||
Type 'Constraint<Runtype<any>>' is not assignable to type 'Constraint<Num>'.
|
||||
tests/cases/compiler/invariantGenericErrorElaboration.ts(4,17): error TS2345: Argument of type '{ foo: Num; }' is not assignable to parameter of type '{ [_: string]: Runtype<any>; }'.
|
||||
Property 'foo' is incompatible with index signature.
|
||||
Type 'Num' is not assignable to type 'Runtype<any>'.
|
||||
|
||||
|
||||
==== tests/cases/compiler/invariantGenericErrorElaboration.ts (2 errors) ====
|
||||
// Repro from #19746
|
||||
|
||||
const wat: Runtype<any> = Num;
|
||||
~~~
|
||||
!!! error TS2322: Type 'Num' is not assignable to type 'Runtype<any>'.
|
||||
!!! error TS2322: Types of property 'constraint' are incompatible.
|
||||
!!! error TS2322: Type 'Constraint<Num>' is not assignable to type 'Constraint<Runtype<any>>'.
|
||||
!!! error TS2322: Types of property 'constraint' are incompatible.
|
||||
!!! error TS2322: Type 'Constraint<Constraint<Num>>' is not assignable to type 'Constraint<Constraint<Runtype<any>>>'.
|
||||
!!! error TS2322: Types of property 'constraint' are incompatible.
|
||||
!!! error TS2322: Type 'Constraint<Constraint<Constraint<Num>>>' is not assignable to type 'Constraint<Constraint<Constraint<Runtype<any>>>>'.
|
||||
!!! error TS2322: Type 'Constraint<Constraint<Runtype<any>>>' is not assignable to type 'Constraint<Constraint<Num>>'.
|
||||
!!! error TS2322: Types of property 'underlying' are incompatible.
|
||||
!!! error TS2322: Type 'Constraint<Runtype<any>>' is not assignable to type 'Constraint<Num>'.
|
||||
const Foo = Obj({ foo: Num })
|
||||
~~~~~~~~~~~~
|
||||
!!! error TS2345: Argument of type '{ foo: Num; }' is not assignable to parameter of type '{ [_: string]: Runtype<any>; }'.
|
||||
!!! error TS2345: Property 'foo' is incompatible with index signature.
|
||||
!!! error TS2345: Type 'Num' is not assignable to type 'Runtype<any>'.
|
||||
|
||||
interface Runtype<A> {
|
||||
constraint: Constraint<this>
|
||||
witness: A
|
||||
}
|
||||
|
||||
interface Num extends Runtype<number> {
|
||||
tag: 'number'
|
||||
}
|
||||
declare const Num: Num
|
||||
|
||||
interface Obj<O extends { [_ in string]: Runtype<any> }> extends Runtype<{[K in keyof O]: O[K]['witness'] }> {}
|
||||
declare function Obj<O extends { [_: string]: Runtype<any> }>(fields: O): Obj<O>;
|
||||
|
||||
interface Constraint<A extends Runtype<any>> extends Runtype<A['witness']> {
|
||||
underlying: A,
|
||||
check: (x: A['witness']) => void,
|
||||
}
|
||||
|
|
@ -0,0 +1,30 @@
|
|||
//// [invariantGenericErrorElaboration.ts]
|
||||
// Repro from #19746
|
||||
|
||||
const wat: Runtype<any> = Num;
|
||||
const Foo = Obj({ foo: Num })
|
||||
|
||||
interface Runtype<A> {
|
||||
constraint: Constraint<this>
|
||||
witness: A
|
||||
}
|
||||
|
||||
interface Num extends Runtype<number> {
|
||||
tag: 'number'
|
||||
}
|
||||
declare const Num: Num
|
||||
|
||||
interface Obj<O extends { [_ in string]: Runtype<any> }> extends Runtype<{[K in keyof O]: O[K]['witness'] }> {}
|
||||
declare function Obj<O extends { [_: string]: Runtype<any> }>(fields: O): Obj<O>;
|
||||
|
||||
interface Constraint<A extends Runtype<any>> extends Runtype<A['witness']> {
|
||||
underlying: A,
|
||||
check: (x: A['witness']) => void,
|
||||
}
|
||||
|
||||
|
||||
//// [invariantGenericErrorElaboration.js]
|
||||
"use strict";
|
||||
// Repro from #19746
|
||||
var wat = Num;
|
||||
var Foo = Obj({ foo: Num });
|
|
@ -0,0 +1,76 @@
|
|||
=== tests/cases/compiler/invariantGenericErrorElaboration.ts ===
|
||||
// Repro from #19746
|
||||
|
||||
const wat: Runtype<any> = Num;
|
||||
>wat : Symbol(wat, Decl(invariantGenericErrorElaboration.ts, 2, 5))
|
||||
>Runtype : Symbol(Runtype, Decl(invariantGenericErrorElaboration.ts, 3, 29))
|
||||
>Num : Symbol(Num, Decl(invariantGenericErrorElaboration.ts, 8, 1), Decl(invariantGenericErrorElaboration.ts, 13, 13))
|
||||
|
||||
const Foo = Obj({ foo: Num })
|
||||
>Foo : Symbol(Foo, Decl(invariantGenericErrorElaboration.ts, 3, 5))
|
||||
>Obj : Symbol(Obj, Decl(invariantGenericErrorElaboration.ts, 13, 22), Decl(invariantGenericErrorElaboration.ts, 15, 111))
|
||||
>foo : Symbol(foo, Decl(invariantGenericErrorElaboration.ts, 3, 17))
|
||||
>Num : Symbol(Num, Decl(invariantGenericErrorElaboration.ts, 8, 1), Decl(invariantGenericErrorElaboration.ts, 13, 13))
|
||||
|
||||
interface Runtype<A> {
|
||||
>Runtype : Symbol(Runtype, Decl(invariantGenericErrorElaboration.ts, 3, 29))
|
||||
>A : Symbol(A, Decl(invariantGenericErrorElaboration.ts, 5, 18))
|
||||
|
||||
constraint: Constraint<this>
|
||||
>constraint : Symbol(Runtype.constraint, Decl(invariantGenericErrorElaboration.ts, 5, 22))
|
||||
>Constraint : Symbol(Constraint, Decl(invariantGenericErrorElaboration.ts, 16, 81))
|
||||
|
||||
witness: A
|
||||
>witness : Symbol(Runtype.witness, Decl(invariantGenericErrorElaboration.ts, 6, 30))
|
||||
>A : Symbol(A, Decl(invariantGenericErrorElaboration.ts, 5, 18))
|
||||
}
|
||||
|
||||
interface Num extends Runtype<number> {
|
||||
>Num : Symbol(Num, Decl(invariantGenericErrorElaboration.ts, 8, 1), Decl(invariantGenericErrorElaboration.ts, 13, 13))
|
||||
>Runtype : Symbol(Runtype, Decl(invariantGenericErrorElaboration.ts, 3, 29))
|
||||
|
||||
tag: 'number'
|
||||
>tag : Symbol(Num.tag, Decl(invariantGenericErrorElaboration.ts, 10, 39))
|
||||
}
|
||||
declare const Num: Num
|
||||
>Num : Symbol(Num, Decl(invariantGenericErrorElaboration.ts, 8, 1), Decl(invariantGenericErrorElaboration.ts, 13, 13))
|
||||
>Num : Symbol(Num, Decl(invariantGenericErrorElaboration.ts, 8, 1), Decl(invariantGenericErrorElaboration.ts, 13, 13))
|
||||
|
||||
interface Obj<O extends { [_ in string]: Runtype<any> }> extends Runtype<{[K in keyof O]: O[K]['witness'] }> {}
|
||||
>Obj : Symbol(Obj, Decl(invariantGenericErrorElaboration.ts, 13, 22), Decl(invariantGenericErrorElaboration.ts, 15, 111))
|
||||
>O : Symbol(O, Decl(invariantGenericErrorElaboration.ts, 15, 14))
|
||||
>_ : Symbol(_, Decl(invariantGenericErrorElaboration.ts, 15, 27))
|
||||
>Runtype : Symbol(Runtype, Decl(invariantGenericErrorElaboration.ts, 3, 29))
|
||||
>Runtype : Symbol(Runtype, Decl(invariantGenericErrorElaboration.ts, 3, 29))
|
||||
>K : Symbol(K, Decl(invariantGenericErrorElaboration.ts, 15, 75))
|
||||
>O : Symbol(O, Decl(invariantGenericErrorElaboration.ts, 15, 14))
|
||||
>O : Symbol(O, Decl(invariantGenericErrorElaboration.ts, 15, 14))
|
||||
>K : Symbol(K, Decl(invariantGenericErrorElaboration.ts, 15, 75))
|
||||
|
||||
declare function Obj<O extends { [_: string]: Runtype<any> }>(fields: O): Obj<O>;
|
||||
>Obj : Symbol(Obj, Decl(invariantGenericErrorElaboration.ts, 13, 22), Decl(invariantGenericErrorElaboration.ts, 15, 111))
|
||||
>O : Symbol(O, Decl(invariantGenericErrorElaboration.ts, 16, 21))
|
||||
>_ : Symbol(_, Decl(invariantGenericErrorElaboration.ts, 16, 34))
|
||||
>Runtype : Symbol(Runtype, Decl(invariantGenericErrorElaboration.ts, 3, 29))
|
||||
>fields : Symbol(fields, Decl(invariantGenericErrorElaboration.ts, 16, 62))
|
||||
>O : Symbol(O, Decl(invariantGenericErrorElaboration.ts, 16, 21))
|
||||
>Obj : Symbol(Obj, Decl(invariantGenericErrorElaboration.ts, 13, 22), Decl(invariantGenericErrorElaboration.ts, 15, 111))
|
||||
>O : Symbol(O, Decl(invariantGenericErrorElaboration.ts, 16, 21))
|
||||
|
||||
interface Constraint<A extends Runtype<any>> extends Runtype<A['witness']> {
|
||||
>Constraint : Symbol(Constraint, Decl(invariantGenericErrorElaboration.ts, 16, 81))
|
||||
>A : Symbol(A, Decl(invariantGenericErrorElaboration.ts, 18, 21))
|
||||
>Runtype : Symbol(Runtype, Decl(invariantGenericErrorElaboration.ts, 3, 29))
|
||||
>Runtype : Symbol(Runtype, Decl(invariantGenericErrorElaboration.ts, 3, 29))
|
||||
>A : Symbol(A, Decl(invariantGenericErrorElaboration.ts, 18, 21))
|
||||
|
||||
underlying: A,
|
||||
>underlying : Symbol(Constraint.underlying, Decl(invariantGenericErrorElaboration.ts, 18, 76))
|
||||
>A : Symbol(A, Decl(invariantGenericErrorElaboration.ts, 18, 21))
|
||||
|
||||
check: (x: A['witness']) => void,
|
||||
>check : Symbol(Constraint.check, Decl(invariantGenericErrorElaboration.ts, 19, 16))
|
||||
>x : Symbol(x, Decl(invariantGenericErrorElaboration.ts, 20, 10))
|
||||
>A : Symbol(A, Decl(invariantGenericErrorElaboration.ts, 18, 21))
|
||||
}
|
||||
|
|
@ -0,0 +1,78 @@
|
|||
=== tests/cases/compiler/invariantGenericErrorElaboration.ts ===
|
||||
// Repro from #19746
|
||||
|
||||
const wat: Runtype<any> = Num;
|
||||
>wat : Runtype<any>
|
||||
>Runtype : Runtype<A>
|
||||
>Num : Num
|
||||
|
||||
const Foo = Obj({ foo: Num })
|
||||
>Foo : any
|
||||
>Obj({ foo: Num }) : any
|
||||
>Obj : <O extends { [_: string]: Runtype<any>; }>(fields: O) => Obj<O>
|
||||
>{ foo: Num } : { foo: Num; }
|
||||
>foo : Num
|
||||
>Num : Num
|
||||
|
||||
interface Runtype<A> {
|
||||
>Runtype : Runtype<A>
|
||||
>A : A
|
||||
|
||||
constraint: Constraint<this>
|
||||
>constraint : Constraint<this>
|
||||
>Constraint : Constraint<A>
|
||||
|
||||
witness: A
|
||||
>witness : A
|
||||
>A : A
|
||||
}
|
||||
|
||||
interface Num extends Runtype<number> {
|
||||
>Num : Num
|
||||
>Runtype : Runtype<A>
|
||||
|
||||
tag: 'number'
|
||||
>tag : "number"
|
||||
}
|
||||
declare const Num: Num
|
||||
>Num : Num
|
||||
>Num : Num
|
||||
|
||||
interface Obj<O extends { [_ in string]: Runtype<any> }> extends Runtype<{[K in keyof O]: O[K]['witness'] }> {}
|
||||
>Obj : Obj<O>
|
||||
>O : O
|
||||
>_ : _
|
||||
>Runtype : Runtype<A>
|
||||
>Runtype : Runtype<A>
|
||||
>K : K
|
||||
>O : O
|
||||
>O : O
|
||||
>K : K
|
||||
|
||||
declare function Obj<O extends { [_: string]: Runtype<any> }>(fields: O): Obj<O>;
|
||||
>Obj : <O extends { [_: string]: Runtype<any>; }>(fields: O) => Obj<O>
|
||||
>O : O
|
||||
>_ : string
|
||||
>Runtype : Runtype<A>
|
||||
>fields : O
|
||||
>O : O
|
||||
>Obj : Obj<O>
|
||||
>O : O
|
||||
|
||||
interface Constraint<A extends Runtype<any>> extends Runtype<A['witness']> {
|
||||
>Constraint : Constraint<A>
|
||||
>A : A
|
||||
>Runtype : Runtype<A>
|
||||
>Runtype : Runtype<A>
|
||||
>A : A
|
||||
|
||||
underlying: A,
|
||||
>underlying : A
|
||||
>A : A
|
||||
|
||||
check: (x: A['witness']) => void,
|
||||
>check : (x: A["witness"]) => void
|
||||
>x : A["witness"]
|
||||
>A : A
|
||||
}
|
||||
|
24
tests/cases/compiler/invariantGenericErrorElaboration.ts
Normal file
24
tests/cases/compiler/invariantGenericErrorElaboration.ts
Normal file
|
@ -0,0 +1,24 @@
|
|||
// @strict: true
|
||||
|
||||
// Repro from #19746
|
||||
|
||||
const wat: Runtype<any> = Num;
|
||||
const Foo = Obj({ foo: Num })
|
||||
|
||||
interface Runtype<A> {
|
||||
constraint: Constraint<this>
|
||||
witness: A
|
||||
}
|
||||
|
||||
interface Num extends Runtype<number> {
|
||||
tag: 'number'
|
||||
}
|
||||
declare const Num: Num
|
||||
|
||||
interface Obj<O extends { [_ in string]: Runtype<any> }> extends Runtype<{[K in keyof O]: O[K]['witness'] }> {}
|
||||
declare function Obj<O extends { [_: string]: Runtype<any> }>(fields: O): Obj<O>;
|
||||
|
||||
interface Constraint<A extends Runtype<any>> extends Runtype<A['witness']> {
|
||||
underlying: A,
|
||||
check: (x: A['witness']) => void,
|
||||
}
|
Loading…
Reference in a new issue