Remove circular default check

This commit is contained in:
Ron Buckton 2017-01-23 19:36:02 -08:00
parent fd228a93a7
commit 15232fe17c
10 changed files with 5211 additions and 1127 deletions

View file

@ -375,7 +375,6 @@ namespace ts {
ResolvedBaseConstructorType,
DeclaredType,
ResolvedReturnType,
ResolvedDefault
}
const builtinGlobals = createMap<Symbol>();
@ -2651,7 +2650,7 @@ namespace ts {
writeSpace(writer);
buildTypeDisplay(constraint, writer, enclosingDeclaration, flags, symbolStack);
}
const defaultType = getDefaultOfTypeParameter(tp);
const defaultType = getDefaultFromTypeParameter(tp);
if (defaultType) {
writeSpace(writer);
writePunctuation(writer, SyntaxKind.EqualsToken);
@ -3054,9 +3053,6 @@ namespace ts {
if (propertyName === TypeSystemPropertyName.ResolvedReturnType) {
return (<Signature>target).resolvedReturnType;
}
if (propertyName === TypeSystemPropertyName.ResolvedDefault) {
return (<TypeVariable>target).resolvedDefault;
}
Debug.fail("Unhandled TypeSystemPropertyName " + propertyName);
}
@ -4863,69 +4859,6 @@ namespace ts {
return typeParameter.default === noConstraintOrDefaultType ? undefined : typeParameter.default;
}
/**
* Gets the default type for a type parameter.
*
* If the type parameter is the result of an instantiation, this gets the instantiated
* default type of its target. If the type parameter has no default type, or if the default
* type circularly references the type parameter, `undefined` is returned.
*
* This function *does* perform a circularity check.
*/
function getDefaultOfTypeParameter(typeParameter: TypeParameter): Type | undefined {
return hasNonCircularDefault(typeParameter) ? getDefaultFromTypeParameter(typeParameter) : undefined;
}
/**
* Determines whether a type parameter has a non-circular default type.
*
* Note that this function also returns `true` if a type parameter *does not* have a
* default type.
*/
function hasNonCircularDefault(typeParameter: TypeParameter): boolean {
return getResolvedDefault(typeParameter) !== circularConstraintOrDefaultType;
}
/**
* Resolves the default type of a type parameter.
*
* If the type parameter has no default, the `noConstraintOrDefaultType` singleton is
* returned. If the type parameter has a circular default, the
* `circularConstraintOrDefaultType` singleton is returned.
*/
function getResolvedDefault(typeParameter: TypeParameter): Type {
if (!typeParameter.resolvedDefault) {
if (!pushTypeResolution(typeParameter, TypeSystemPropertyName.ResolvedDefault)) {
return circularConstraintOrDefaultType;
}
const defaultType = getDefaultFromTypeParameter(typeParameter);
const type = defaultType && getResolvedDefaultWorker(defaultType);
if (!popTypeResolution()) {
return typeParameter.resolvedDefault = circularConstraintOrDefaultType;
}
typeParameter.resolvedDefault = type || noConstraintOrDefaultType;
}
return typeParameter.resolvedDefault;
}
/**
* Recursively resolves the default type for a type.
*
* If the type is a union or intersection type and any of its constituents is a circular
* reference, the `circularConstraintOrDefaultType` singleton is returned.
*/
function getResolvedDefaultWorker(type: Type): Type {
if (type.flags & TypeFlags.TypeParameter) {
return getResolvedDefault(<TypeParameter>type);
}
if (type.flags & TypeFlags.UnionOrIntersection) {
const types = map((<UnionOrIntersectionType>type).types, getResolvedDefaultWorker);
return some(types, x => x === circularConstraintOrDefaultType) ? circularConstraintOrDefaultType :
type.flags & TypeFlags.Union ? getUnionType(types) : getIntersectionType(types);
}
return type;
}
/**
* For a type parameter, return the base constraint of the type parameter. For the string, number,
* boolean, and symbol primitive types, return the corresponding object types. Otherwise return the
@ -5241,20 +5174,23 @@ namespace ts {
typeArguments = [];
}
// Map an unsatisfied type parameter with a default type to the default type.
// Map an unsatisfied type parameter with a default type.
// If a type parameter does not have a default type, or if the default type
// is a circular reference, the empty object type is used.
// is a forward reference, the empty object type is used.
const mapper: TypeMapper = t => {
const i = indexOf(typeParameters, t);
return i >= 0
? typeArguments[i] || (typeArguments[i] =
instantiateType(getDefaultOfTypeParameter(typeParameters[i]), mapper) ||
emptyObjectType)
: t;
if (i >= typeArguments.length) {
return emptyObjectType;
}
if (i >= 0) {
return typeArguments[i];
}
return t;
};
for (let i = numTypeArguments; i < numTypeParameters; i++) {
instantiateType(typeParameters[i], mapper);
const defaultType = getDefaultFromTypeParameter(typeParameters[i]);
typeArguments[i] = defaultType ? instantiateType(defaultType, mapper) : emptyObjectType;
}
}
}
@ -9181,8 +9117,16 @@ namespace ts {
// succeeds, meaning there is no error for not having inference candidates. An
// inference error only occurs when there are *conflicting* candidates, i.e.
// candidates with no common supertype.
const defaultType = getDefaultOfTypeParameter(context.signature.typeParameters[index]);
inferredType = defaultType ? instantiateType(defaultType, getInferenceMapper(context)) : emptyObjectType;
const defaultType = getDefaultFromTypeParameter(context.signature.typeParameters[index]);
if (defaultType) {
const backreferenceMapper: TypeMapper = t => indexOf(context.signature.typeParameters, t) >= index ? emptyObjectType : t;
const mapper = combineTypeMappers(backreferenceMapper, getInferenceMapper(context));
inferredType = instantiateType(defaultType, mapper);
}
else {
inferredType = emptyObjectType;
}
inferenceSucceeded = true;
}
context.inferredTypes[index] = inferredType;
@ -15574,11 +15518,8 @@ namespace ts {
if (!hasNonCircularBaseConstraint(typeParameter)) {
error(node.constraint, Diagnostics.Type_parameter_0_has_a_circular_constraint, typeToString(typeParameter));
}
if (!hasNonCircularDefault(typeParameter)) {
error(node.default, Diagnostics.Type_parameter_0_has_a_circular_default, typeToString(typeParameter));
}
const constraintType = getConstraintOfTypeParameter(typeParameter);
const defaultType = getDefaultOfTypeParameter(typeParameter);
const defaultType = getDefaultFromTypeParameter(typeParameter);
if (constraintType && defaultType) {
checkTypeAssignableTo(defaultType, getTypeWithThisArgument(constraintType, defaultType), node.default, Diagnostics.Type_0_does_not_satisfy_the_constraint_1);
}

View file

@ -2043,11 +2043,7 @@
"category": "Error",
"code": 2705
},
"Type parameter '{0}' has a circular default.": {
"category": "Error",
"code": 2706
},
"Generic type '{0}' requires between {1} and {2} type arguments.": {
"Generic type '{0}' requires between {1} and {2} type arguments.": {
"category": "Error",
"code": 2707
},

View file

@ -2990,8 +2990,6 @@ namespace ts {
/* @internal */
resolvedBaseConstraint: Type;
/* @internal */
resolvedDefault: Type;
/* @internal */
resolvedIndexType: IndexType;
}

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -1,88 +1,42 @@
tests/cases/compiler/genericDefaultsErrors.ts(4,26): error TS2706: Type parameter 'T' has a circular default.
tests/cases/compiler/genericDefaultsErrors.ts(5,26): error TS2706: Type parameter 'T' has a circular default.
tests/cases/compiler/genericDefaultsErrors.ts(5,33): error TS2706: Type parameter 'U' has a circular default.
tests/cases/compiler/genericDefaultsErrors.ts(6,29): error TS2705: Required type parameters may not follow optional type parameters.
tests/cases/compiler/genericDefaultsErrors.ts(7,41): error TS2344: Type 'number' does not satisfy the constraint 'string'.
tests/cases/compiler/genericDefaultsErrors.ts(8,59): error TS2344: Type 'T' does not satisfy the constraint 'number'.
tests/cases/compiler/genericDefaultsErrors.ts(4,41): error TS2344: Type 'number' does not satisfy the constraint 'string'.
tests/cases/compiler/genericDefaultsErrors.ts(5,59): error TS2344: Type 'T' does not satisfy the constraint 'number'.
Type 'string' is not assignable to type 'number'.
tests/cases/compiler/genericDefaultsErrors.ts(9,44): error TS2344: Type 'T' does not satisfy the constraint 'number'.
tests/cases/compiler/genericDefaultsErrors.ts(10,39): error TS2344: Type 'number' does not satisfy the constraint 'T'.
tests/cases/compiler/genericDefaultsErrors.ts(11,26): error TS2706: Type parameter 'T' has a circular default.
tests/cases/compiler/genericDefaultsErrors.ts(11,33): error TS2706: Type parameter 'U' has a circular default.
tests/cases/compiler/genericDefaultsErrors.ts(12,26): error TS2706: Type parameter 'T' has a circular default.
tests/cases/compiler/genericDefaultsErrors.ts(12,33): error TS2706: Type parameter 'U' has a circular default.
tests/cases/compiler/genericDefaultsErrors.ts(13,26): error TS2706: Type parameter 'T' has a circular default.
tests/cases/compiler/genericDefaultsErrors.ts(13,33): error TS2706: Type parameter 'U' has a circular default.
tests/cases/compiler/genericDefaultsErrors.ts(14,26): error TS2706: Type parameter 'T' has a circular default.
tests/cases/compiler/genericDefaultsErrors.ts(14,33): error TS2706: Type parameter 'U' has a circular default.
tests/cases/compiler/genericDefaultsErrors.ts(18,1): error TS2346: Supplied parameters do not match any signature of call target.
tests/cases/compiler/genericDefaultsErrors.ts(21,1): error TS2346: Supplied parameters do not match any signature of call target.
tests/cases/compiler/genericDefaultsErrors.ts(25,13): error TS2345: Argument of type '"a"' is not assignable to parameter of type 'number'.
tests/cases/compiler/genericDefaultsErrors.ts(28,11): error TS2428: All declarations of 'i00' must have identical type parameters.
tests/cases/compiler/genericDefaultsErrors.ts(31,11): error TS2428: All declarations of 'i01' must have identical type parameters.
tests/cases/compiler/genericDefaultsErrors.ts(33,19): error TS2706: Type parameter 'T' has a circular default.
tests/cases/compiler/genericDefaultsErrors.ts(34,19): error TS2706: Type parameter 'T' has a circular default.
tests/cases/compiler/genericDefaultsErrors.ts(34,26): error TS2706: Type parameter 'U' has a circular default.
tests/cases/compiler/genericDefaultsErrors.ts(35,22): error TS2705: Required type parameters may not follow optional type parameters.
tests/cases/compiler/genericDefaultsErrors.ts(36,34): error TS2344: Type 'number' does not satisfy the constraint 'string'.
tests/cases/compiler/genericDefaultsErrors.ts(37,52): error TS2344: Type 'T' does not satisfy the constraint 'number'.
tests/cases/compiler/genericDefaultsErrors.ts(6,44): error TS2344: Type 'T' does not satisfy the constraint 'number'.
tests/cases/compiler/genericDefaultsErrors.ts(7,39): error TS2344: Type 'number' does not satisfy the constraint 'T'.
tests/cases/compiler/genericDefaultsErrors.ts(11,1): error TS2346: Supplied parameters do not match any signature of call target.
tests/cases/compiler/genericDefaultsErrors.ts(14,1): error TS2346: Supplied parameters do not match any signature of call target.
tests/cases/compiler/genericDefaultsErrors.ts(18,13): error TS2345: Argument of type '"a"' is not assignable to parameter of type 'number'.
tests/cases/compiler/genericDefaultsErrors.ts(21,11): error TS2428: All declarations of 'i00' must have identical type parameters.
tests/cases/compiler/genericDefaultsErrors.ts(24,11): error TS2428: All declarations of 'i01' must have identical type parameters.
tests/cases/compiler/genericDefaultsErrors.ts(26,27): error TS2705: Required type parameters may not follow optional type parameters.
tests/cases/compiler/genericDefaultsErrors.ts(27,34): error TS2344: Type 'number' does not satisfy the constraint 'string'.
tests/cases/compiler/genericDefaultsErrors.ts(28,52): error TS2344: Type 'T' does not satisfy the constraint 'number'.
Type 'string' is not assignable to type 'number'.
tests/cases/compiler/genericDefaultsErrors.ts(38,37): error TS2344: Type 'T' does not satisfy the constraint 'number'.
tests/cases/compiler/genericDefaultsErrors.ts(39,32): error TS2344: Type 'number' does not satisfy the constraint 'T'.
tests/cases/compiler/genericDefaultsErrors.ts(42,15): error TS2707: Generic type 'i09<T, U, V>' requires between 2 and 3 type arguments.
tests/cases/compiler/genericDefaultsErrors.ts(43,15): error TS2707: Generic type 'i09<T, U, V>' requires between 2 and 3 type arguments.
tests/cases/compiler/genericDefaultsErrors.ts(46,15): error TS2707: Generic type 'i09<T, U, V>' requires between 2 and 3 type arguments.
tests/cases/compiler/genericDefaultsErrors.ts(48,17): error TS2367: Type parameter 'T' cannot be referenced outside of a declaration that defines it.
tests/cases/compiler/genericDefaultsErrors.ts(29,37): error TS2344: Type 'T' does not satisfy the constraint 'number'.
tests/cases/compiler/genericDefaultsErrors.ts(30,32): error TS2344: Type 'number' does not satisfy the constraint 'T'.
tests/cases/compiler/genericDefaultsErrors.ts(33,15): error TS2707: Generic type 'i09<T, U, V>' requires between 2 and 3 type arguments.
tests/cases/compiler/genericDefaultsErrors.ts(34,15): error TS2707: Generic type 'i09<T, U, V>' requires between 2 and 3 type arguments.
tests/cases/compiler/genericDefaultsErrors.ts(37,15): error TS2707: Generic type 'i09<T, U, V>' requires between 2 and 3 type arguments.
tests/cases/compiler/genericDefaultsErrors.ts(39,17): error TS2367: Type parameter 'T' cannot be referenced outside of a declaration that defines it.
==== tests/cases/compiler/genericDefaultsErrors.ts (33 errors) ====
==== tests/cases/compiler/genericDefaultsErrors.ts (18 errors) ====
declare const x: any;
declare function f00<T = T>(): void;
~
!!! error TS2706: Type parameter 'T' has a circular default.
declare function f01<T = U, U = T>(): void;
~
!!! error TS2706: Type parameter 'T' has a circular default.
~
!!! error TS2706: Type parameter 'U' has a circular default.
declare function f02<T = U, U>();
~
!!! error TS2705: Required type parameters may not follow optional type parameters.
declare function f03<T extends string = number>(): void;
declare function f03<T extends string = number>(): void; // error
~~~~~~
!!! error TS2344: Type 'number' does not satisfy the constraint 'string'.
declare function f04<T extends string, U extends number = T>(): void;
declare function f04<T extends string, U extends number = T>(): void; // error
~
!!! error TS2344: Type 'T' does not satisfy the constraint 'number'.
!!! error TS2344: Type 'string' is not assignable to type 'number'.
declare function f05<T, U extends number = T>(): void;
declare function f05<T, U extends number = T>(): void; // error
~
!!! error TS2344: Type 'T' does not satisfy the constraint 'number'.
declare function f06<T, U extends T = number>(): void;
declare function f06<T, U extends T = number>(): void; // error
~~~~~~
!!! error TS2344: Type 'number' does not satisfy the constraint 'T'.
declare function f07<T = U, U = T | { a: number }>(): void;
~
!!! error TS2706: Type parameter 'T' has a circular default.
~~~~~~~~~~~~~~~~~
!!! error TS2706: Type parameter 'U' has a circular default.
declare function f08<T = U, U = T & { a: number }>(): void;
~
!!! error TS2706: Type parameter 'T' has a circular default.
~~~~~~~~~~~~~~~~~
!!! error TS2706: Type parameter 'U' has a circular default.
declare function f09<T = U, U = T | { a: number }>(): void;
~
!!! error TS2706: Type parameter 'T' has a circular default.
~~~~~~~~~~~~~~~~~
!!! error TS2706: Type parameter 'U' has a circular default.
declare function f10<T = U, U = T & { a: number }>(): void;
~
!!! error TS2706: Type parameter 'T' has a circular default.
~~~~~~~~~~~~~~~~~
!!! error TS2706: Type parameter 'U' has a circular default.
declare function f11<T, U, V = number>(): void;
f11(); // ok
@ -111,16 +65,8 @@ tests/cases/compiler/genericDefaultsErrors.ts(48,17): error TS2367: Type paramet
~~~
!!! error TS2428: All declarations of 'i01' must have identical type parameters.
interface i02<T = T> { } // error
~
!!! error TS2706: Type parameter 'T' has a circular default.
interface i03<T = U, U = T> { } // error
~
!!! error TS2706: Type parameter 'T' has a circular default.
~
!!! error TS2706: Type parameter 'U' has a circular default.
interface i04<T = U, U> { } // error
~
interface i04<T = number, U> { } // error
~
!!! error TS2705: Required type parameters may not follow optional type parameters.
interface i05<T extends string = number> { } // error
~~~~~~

View file

@ -2,17 +2,10 @@
declare const x: any;
declare function f00<T = T>(): void;
declare function f01<T = U, U = T>(): void;
declare function f02<T = U, U>();
declare function f03<T extends string = number>(): void;
declare function f04<T extends string, U extends number = T>(): void;
declare function f05<T, U extends number = T>(): void;
declare function f06<T, U extends T = number>(): void;
declare function f07<T = U, U = T | { a: number }>(): void;
declare function f08<T = U, U = T & { a: number }>(): void;
declare function f09<T = U, U = T | { a: number }>(): void;
declare function f10<T = U, U = T & { a: number }>(): void;
declare function f03<T extends string = number>(): void; // error
declare function f04<T extends string, U extends number = T>(): void; // error
declare function f05<T, U extends number = T>(): void; // error
declare function f06<T, U extends T = number>(): void; // error
declare function f11<T, U, V = number>(): void;
f11(); // ok
@ -31,9 +24,7 @@ interface i00<U = number> { } // error
interface i01<T = number> { } // ok
interface i01<T = string> { } // error
interface i02<T = T> { } // error
interface i03<T = U, U = T> { } // error
interface i04<T = U, U> { } // error
interface i04<T = number, U> { } // error
interface i05<T extends string = number> { } // error
interface i06<T extends string, U extends number = T> { } // error
interface i07<T, U extends number = T> { } // error
@ -61,25 +52,10 @@ f12("a"); // error
//// [genericDefaultsErrors.d.ts]
declare const x: any;
declare function f00<T = T>(): void;
declare function f01<T = U, U = T>(): void;
declare function f02<T = U, U>(): any;
declare function f03<T extends string = number>(): void;
declare function f04<T extends string, U extends number = T>(): void;
declare function f05<T, U extends number = T>(): void;
declare function f06<T, U extends T = number>(): void;
declare function f07<T = U, U = T | {
a: number;
}>(): void;
declare function f08<T = U, U = T & {
a: number;
}>(): void;
declare function f09<T = U, U = T | {
a: number;
}>(): void;
declare function f10<T = U, U = T & {
a: number;
}>(): void;
declare function f11<T, U, V = number>(): void;
declare function f12<T, U = T>(a?: U): void;
interface i00<T> {
@ -90,11 +66,7 @@ interface i01<T = number> {
}
interface i01<T = string> {
}
interface i02<T = T> {
}
interface i03<T = U, U = T> {
}
interface i04<T = U, U> {
interface i04<T = number, U> {
}
interface i05<T extends string = number> {
}

View file

@ -1,68 +1,398 @@
// @declaration: true
interface A { a: number; }
interface B { b: number; }
interface C { c: number; }
interface D { d: number; }
interface AB { a: number; b: number; }
interface BC { b: number; c: number; }
declare const a: A;
declare const b: B;
declare const c: C;
declare const d: D;
declare const ab: AB;
declare const bc: BC;
declare const x: any;
declare function f00<T = number>(a?: T): T;
const f00c00 = f00();
const f00c01 = f00(1);
const f00c02 = f00("a");
const f00c03 = f00<number>();
const f00c04 = f00<number>(1);
const f00c05 = f00<string>("a");
// function without type parameters
declare function f00(a?: A): A;
// no inference
f00();
f00(a);
declare function f01<T, U = T>(a?: T, b?: U): [T, U];
const f01c00 = f01();
const f01c01 = f01(1);
const f01c02 = f01(1, "a");
const f01c03 = f01<number>();
const f01c04 = f01<number>(1);
const f01c05 = f01<number>(1, 2);
const f01c06 = f01<number, string>();
const f01c07 = f01<number, string>(1);
const f01c08 = f01<number, string>(1, "a");
// function with a type parameter without a default
declare function f01<T>(a?: T): T;
// inference
f01();
f01(a);
// no inference, fully supplied
f01<A>();
f01<A>(a);
declare function f02<T extends number, U = T>(a?: T, b?: U): [T, U];
const f02c00 = f02();
const f02c01 = f02(1);
const f02c02 = f02(1, "a");
const f02c03 = f02<number>();
const f02c04 = f02<number>(1);
const f02c05 = f02<number>(1, 2);
const f02c06 = f02<number, string>();
const f02c07 = f02<number, string>(1);
const f02c08 = f02<number, string>(1, "a");
// function with a type paramter with a default
declare function f02<T = A>(a?: T): T;
// inference
f02();
f02(a);
f02(b);
// no inference, fully supplied
f02<A>();
f02<A>(a);
f02<B>();
f02<B>(b);
declare function f03<T extends number, U extends T = T>(a?: T, b?: U): [T, U];
const f03c00 = f03();
const f03c01 = f03(1);
const f03c02 = f03(1, 1);
const f03c03 = f03<number>();
const f03c04 = f03<number>(1);
const f03c05 = f03<number>(1, 2);
const f03c06 = f03<number, number>();
const f03c07 = f03<number, number>(1);
const f03c08 = f03<number, number>(1, 2);
// function with a type parameter with a default that refers to itself
declare function f03<T = T>(a?: T): T;
// inference
f03();
f03(a);
f03(b);
// no inference, fully supplied
f03<A>();
f03<A>(a);
f03<B>();
f03<B>(b);
declare function f04<T, U = T | { a: number }>(a?: T, b?: U): [T, U];
const f04c00 = f04();
const f04c01 = f04(1);
const f04c02 = f04(1, 1);
const f04c03 = f04<number>();
const f04c04 = f04<number>(1);
const f04c05 = f04<number>(1, 2);
const f04c06 = f04<number, number>();
const f04c07 = f04<number, number>(1);
const f04c08 = f04<number, number>(1, 2);
// function with a type paramter without a default and a type parameter with a default
declare function f04<T, U = B>(a?: T, b?: U): [T, U];
// inference
f04();
f04(a);
f04(a, b);
f04(a, c);
// no inference, partially supplied
f04<A>();
f04<A>(a);
f04<A>(a, b);
// no inference, fully supplied
f04<A, B>();
f04<A, B>(a);
f04<A, B>(a, b);
f04<A, C>();
f04<A, C>(a);
f04<A, C>(a, c);
declare function f05<T, U = T & { b: number }>(a?: T, b?: U): [T, U];
const f05c00 = f05();
const f05c01 = f05(1);
const f05c02 = f05(1, 1);
const f05c03 = f05<number>();
const f05c04 = f05<number>(1);
const f05c05 = f05<{ a: number }>({ a: 1 }, { a: 2, b: 3});
const f05c06 = f05<number, number>();
const f05c07 = f05<number, number>(1);
const f05c08 = f05<number, number>(1, 2);
// function with a type parameter without a default and a type parameter with a default that refers to an earlier type parameter
declare function f05<T, U = T>(a?: T, b?: U): [T, U];
// inference
f05();
f05(a);
f05(a, a);
f05(a, b);
// no inference, partially supplied
f05<A>();
f05<A>(a);
f05<A>(a, a);
// no inference, fully supplied
f05<A, B>();
f05<A, B>(a);
f05<A, B>(a, b);
// function with a type parameter with a default that refers to an earlier type parameter with a default
declare function f06<T = A, U = T>(a?: T, b?: U): [T, U];
// inference
f06();
f06(a);
f06(a, a);
f06(a, b);
f06(b, a);
f06(b, b);
// no inference, partially supplied
f06<A>();
f06<A>(a);
f06<A>(a, a);
f06<B>();
f06<B>(b);
f06<B>(b, b);
// no inference, fully supplied
f06<A, B>();
f06<A, B>(a);
f06<A, B>(a, b);
f06<B, C>();
f06<B, C>(b);
f06<B, C>(b, c);
// function with a type parameter without a default and a type parameter with a default that refers to an earlier type parameter with a default
declare function f07<T, U = B, V = U>(a?: T, b?: U, c?: V): [T, U, V];
// inference
f07();
f07(a, b);
f07(a, c);
f07(a, b, b);
f07(a, b, c);
f07(a, c, b);
f07(a, c, c);
// no inference, partially supplied
f07<A>();
f07<A>(a);
f07<A>(a, b);
f07<A>(a, b, b);
f07<A, B>();
f07<A, B>(a);
f07<A, B>(a, b);
f07<A, B>(a, b, b);
f07<A, C>();
f07<A, C>(a);
f07<A, C>(a, c);
f07<A, C>(a, c, c);
// no inference, fully supplied
f07<A, B, C>();
f07<A, B, C>(a);
f07<A, B, C>(a, b);
f07<A, B, C>(a, b, c);
f07<A, C, A>();
f07<A, C, A>(a);
f07<A, C, D>(a, c);
f07<A, C, D>(a, c, d);
// function with a type parameter with a default that refers to an earlier type parameter with a constraint
declare function f08<T extends A, U = T>(a?: T, b?: U): [T, U];
// inference
f08();
f08(a);
f08(a, a);
f08(a, b);
// no inference, partially supplied
f08<A>();
f08<A>(a);
f08<A>(a, a);
// no inference, fully supplied
f08<A, B>();
f08<A, B>(a);
f08<A, B>(a, b);
// function with a type parameter with a constraint and a default that refers to an earlier type parameter
declare function f09<T, U extends T = T>(a?: T, b?: U): [T, U];
// inference
f09();
f09(a);
f09(a, a);
f09(a, ab);
// no inference, partially supplied
f09<A>();
f09<A>(a);
f09<A>(a, a);
f09<A>(a, ab);
// no inference, fully supplied
f09<A, AB>();
f09<A, AB>(a);
f09<A, AB>(a, ab);
// function with a type parameter with a constraint and a default that refers to an earlier type parameter with a constraint
declare function f10<T extends A, U extends T = T>(a?: T, b?: U): [T, U];
// inference
f10();
f10(a);
f10(a, a);
f10(a, ab);
// no inference, partially supplied
f10<A>();
f10<A>(a);
f10<A>(a, a);
f10<A>(a, ab);
// no inference, fully supplied
f10<A, A>();
f10<A, A>(a);
f10<A, A>(a, a);
f10<A, A>(a, ab);
f10<A, AB>();
f10<A, AB>(a);
f10<A, AB>(a, ab);
// function with a type parameter with a default that refers to an earier type parameter in a union
declare function f11<T, U = T | B>(a?: T, b?: U): [T, U];
// inference
f11();
f11(a);
f11(a, a);
f11(a, b);
f11(a, c);
// no inference, partially supplied
f11<A>();
f11<A>(a);
f11<A>(a, a);
f11<A>(a, b);
// no inference, fully supplied
f11<A, C>();
f11<A, C>(a);
f11<A, C>(a, c);
// function with a type parameter with a default that refers to an earlier type parameter in an intersection
declare function f12<T, U = T & B>(a?: T, b?: U): [T, U];
// inference
f12();
f12(a);
f12(a, a);
f12(a, b);
f12(a, c);
// no inference, partially supplied
f12<A>();
f12<A>(a);
f12<A>(a, ab);
// no inference, fully supplied
f12<A, C>();
f12<A, C>(a);
f12<A, C>(a, c);
// function with a type parameter with a default that refers to a later type parameter with a default
declare function f13<T = U, U = B>(a?: T, b?: U): [T, U];
// inference
f13();
f13(a);
f13(a, b);
f13(a, c);
// no inference, partially supplied
f13<A>();
f13<A>(a);
f13<A>(a, b);
// no inference, fully supplied
f13<A, C>();
f13<A, C>(a);
f13<A, C>(a, c);
f13<A, C>(a, c);
// function with a type parameter without a default and a type parameter with a default that refers to a later type parameter with a default
declare function f14<T, U = V, V = C>(a?: T, b?: U, c?: V): [T, U, V];
// inference
f14();
f14(a);
f14(a, b);
f14(a, b, c);
f14(a, b, d);
// no inference, partially supplied
f14<A>();
f14<A>(a);
f14<A>(a, b);
f14<A>(a, b, c);
f14<A, B>();
f14<A, B>(a);
f14<A, B>(a, b);
f14<A, B>(a, b, c);
// no inference fully supplied
f14<A, B, D>();
f14<A, B, D>(a);
f14<A, B, D>(a, b);
f14<A, B, D>(a, b, d);
// function with two type parameters with defaults that mutually refer to each other
declare function f15<T = U, U = T>(a?: T, b?: U): [T, U];
// inference
f15();
f15(a);
f15(a, b);
// no inference, partially supplied
f15<A>();
f15<A>(a);
f15<A>(a, a);
// no inference, fully supplied
f15<A, B>();
f15<A, B>(a);
f15<A, B>(a, b);
// function with a type parameter without a default and two type parameters with defaults that mutually refer to each other
declare function f16<T, U = V, V = U>(a?: T, b?: U, c?: V): [T, U, V];
// no inference
f16();
f16(a);
f16(a, b);
f16(a, b, b);
// no inference, partially supplied
f16<A>();
f16<A>(a);
f16<A>(a, b);
f16<A>(a, b, b);
f16<A, B>();
f16<A, B>(a);
f16<A, B>(a, b);
f16<A, B>(a, b, b);
// no inference, fully supplied
f16<A, B, D>();
f16<A, B, D>(a);
f16<A, B, D>(a, b);
f16<A, B, D>(a, b, d);
// function with a type parameter with a default that refers to a later type parameter with a default that refers to an earlier type parameter in a union
declare function f17<T = U, U = T | B>(a?: T, b?: U): [T, U];
// inference
f17();
f17(a);
f17(a, a);
f17(a, b);
f17(a, c);
// no inference, partially supplied
f17<A>();
f17<A>(a);
f17<A>(a, a);
f17<A>(a, b);
// no inference, fully supplied
f17<A, C>();
f17<A, C>(a);
f17<A, C>(a, c);
// function with a type parameter without a default and a type parameter with a default that refers to a later type parameter with a default that refers to an earlier type parameter in a union
declare function f18<T, U = V, V = U | C>(a?: T, b?: U, c?: V): [T, U, V];
// inference
f18();
f18(a);
f18(a, b);
f18(a, b, b);
f18(a, b, c);
// no inference, partially supplied
f18<A>();
f18<A>(a);
f18<A>(a, b);
f18<A>(a, b, b);
f18<A>(a, b, c);
f18<A, B>();
f18<A, B>(a);
f18<A, B>(a, b);
f18<A, B>(a, b, b);
f18<A, B>(a, b, c);
// no inference, fully supplied
f18<A, B, D>();
f18<A, B, D>(a);
f18<A, B, D>(a, b);
f18<A, B, D>(a, b, d);
// function with a type parameter with a default that refers to a later type parameter with a default that refers to an earlier type parameter in an intersection
declare function f19<T = U, U = T & B>(a?: T, b?: U): [T, U];
// inference
f19();
f19(a);
f19(a, a);
f19(a, b);
f19(a, ab);
f19(a, c);
// no inference, partially supplied
f19<A>();
f19<A>(a);
f19<A>(a, ab);
// no inference, fully supplied
f19<A, C>();
f19<A, C>(a);
f19<A, C>(a, c);
// function with a type parameter without a default and a type parameter with a default that refers to a later type parameter with a default that refers to an earlier type parameter in an intersection
declare function f20<T, U = V, V = U & C>(a?: T, b?: U, c?: V): [T, U, V];
// inference
f20();
f20(a);
f20(a, b);
f20(a, b, c);
// no inference, partially supplied
f20<A>();
f20<A>(a);
f20<A>(a, b);
f20<A>(a, b, bc);
f20<A, B>();
f20<A, B>(a);
f20<A, B>(a, b);
f20<A, B>(a, b, bc);
// no inference, fully supplied
f20<A, B, D>();
f20<A, B, D>(a);
f20<A, B, D>(a, b);
f20<A, B, D>(a, b, d);
interface i00<T = number> { a: T; }
const i00c00 = (<i00>x).a;
@ -91,6 +421,15 @@ interface i04<T> {}
interface i04<T = number> {}
interface i04<T = number, U = string> {}
interface i05<T = T> { a: T; }
const i05c00 = (<i05>x).a;
const i05c01 = (<i05<number>>x).a;
interface i06<T = U, U = T> { a: [T, U]; }
const i06c00 = (<i06>x).a;
const i06c01 = (<i06<number>>x).a;
const i06c02 = (<i06<number, string>>x).a;
interface Base01<T> { a: T; }
interface Base01Constructor { new <T = number>(a?: T): Base01<T>; }

View file

@ -2,17 +2,10 @@
declare const x: any;
declare function f00<T = T>(): void;
declare function f01<T = U, U = T>(): void;
declare function f02<T = U, U>();
declare function f03<T extends string = number>(): void;
declare function f04<T extends string, U extends number = T>(): void;
declare function f05<T, U extends number = T>(): void;
declare function f06<T, U extends T = number>(): void;
declare function f07<T = U, U = T | { a: number }>(): void;
declare function f08<T = U, U = T & { a: number }>(): void;
declare function f09<T = U, U = T | { a: number }>(): void;
declare function f10<T = U, U = T & { a: number }>(): void;
declare function f03<T extends string = number>(): void; // error
declare function f04<T extends string, U extends number = T>(): void; // error
declare function f05<T, U extends number = T>(): void; // error
declare function f06<T, U extends T = number>(): void; // error
declare function f11<T, U, V = number>(): void;
f11(); // ok
@ -31,9 +24,7 @@ interface i00<U = number> { } // error
interface i01<T = number> { } // ok
interface i01<T = string> { } // error
interface i02<T = T> { } // error
interface i03<T = U, U = T> { } // error
interface i04<T = U, U> { } // error
interface i04<T = number, U> { } // error
interface i05<T extends string = number> { } // error
interface i06<T extends string, U extends number = T> { } // error
interface i07<T, U extends number = T> { } // error