Skip to content

Commit

Permalink
Tweak co/contra inference logic from #52123 (#52180)
Browse files Browse the repository at this point in the history
  • Loading branch information
jakebailey authored Jan 11, 2023
1 parent 14b0d6d commit 28e4c81
Show file tree
Hide file tree
Showing 9 changed files with 1,445 additions and 2 deletions.
4 changes: 2 additions & 2 deletions src/compiler/checker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24590,8 +24590,8 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
// parameter and has inferences that would conflict. Otherwise, we use the contra-variant inference.
const useCovariantType = inferredCovariantType && !(inferredCovariantType.flags & TypeFlags.Never) &&
some(inference.contraCandidates, t => isTypeSubtypeOf(inferredCovariantType, t)) &&
every(context.inferences, other => other === inference ||
getConstraintOfTypeParameter(other.typeParameter) !== inference.typeParameter ||
every(context.inferences, other =>
other !== inference && getConstraintOfTypeParameter(other.typeParameter) !== inference.typeParameter ||
every(other.candidates, t => isTypeSubtypeOf(t, inferredCovariantType)));
inferredType = useCovariantType ? inferredCovariantType : getContravariantInference(inference);
}
Expand Down
163 changes: 163 additions & 0 deletions tests/baselines/reference/coAndContraVariantInferences3.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,163 @@
//// [coAndContraVariantInferences3.ts]
interface DeprecationOptions {
message?: string;
error?: boolean;
name?: string;
}

type UnionToIntersection<U> = (U extends any ? (k: U) => void : never) extends ((k: infer I) => void) ? I : never;

type OverloadDefinitions = { readonly [P in number]: (...args: any[]) => any; };

type OverloadBinder<T extends OverloadDefinitions> = (args: OverloadParameters<T>) => OverloadKeys<T> | undefined;

type OverloadKeys<T extends OverloadDefinitions> = Extract<keyof T, number>;

type OverloadParameters<T extends OverloadDefinitions> = Parameters<{ [P in OverloadKeys<T>]: T[P]; }[OverloadKeys<T>]>;

type OverloadFunction<T extends OverloadDefinitions> = UnionToIntersection<T[keyof T]>;

type OverloadBinders<T extends OverloadDefinitions> = { [P in OverloadKeys<T>]: (args: OverloadParameters<T>) => boolean | undefined; };

type OverloadDeprecations<T extends OverloadDefinitions> = { [P in OverloadKeys<T>]?: DeprecationOptions; };

declare function createOverload<T extends OverloadDefinitions>(name: string, overloads: T, binder: OverloadBinders<T>, deprecations?: OverloadDeprecations<T>): UnionToIntersection<T[keyof T]>;

declare function createBinder<T extends OverloadDefinitions>(overloads: T, binder: OverloadBinders<T>): OverloadBinder<T>;

interface OverloadBuilder {
overload<T extends OverloadDefinitions>(overloads: T): BindableOverloadBuilder<T>;
}

interface BindableOverloadBuilder<T extends OverloadDefinitions> {
bind(binder: OverloadBinders<T>): BoundOverloadBuilder<T>;
}

interface FinishableOverloadBuilder<T extends OverloadDefinitions> {
finish(): OverloadFunction<T>;
}

interface BoundOverloadBuilder<T extends OverloadDefinitions> extends FinishableOverloadBuilder<T> {
deprecate(deprecations: OverloadDeprecations<T>): FinishableOverloadBuilder<T>;
}

declare function buildOverload(name: string): OverloadBuilder;

const enum SyntaxKind {
ImportDeclaration,
Modifier,
ImportClause,
AssertClause,
Decorator
}

interface Node {
kind: SyntaxKind;
}

interface Declaration extends Node { _declarationBrand: any }
interface Statement extends Node { _statementBrand: any };
interface Expression extends Node { _expressionBrand: any; }

interface ImportDeclaration extends Statement { kind: SyntaxKind.ImportDeclaration; }
interface Modifier extends Node { kind: SyntaxKind.Modifier; }
interface Decorator extends Node { kind: SyntaxKind.Decorator; }
interface ImportClause extends Declaration { kind: SyntaxKind.ImportClause; }
interface AssertClause extends Node { kind: SyntaxKind.AssertClause; }

declare function isExpression(node: Node): node is Expression;
declare function isAssertClause(node: Node): node is AssertClause;
declare function isImportClause(node: Node): node is ImportClause;
declare function isModifier(node: Node): node is Modifier;
declare function isDecorator(node: Node): node is Decorator;

declare const updateImportDeclaration: {
(node: ImportDeclaration, modifiers: readonly Modifier[] | undefined, importClause: ImportClause | undefined, moduleSpecifier: Expression, assertClause: AssertClause | undefined): ImportDeclaration;
(node: ImportDeclaration, decorators: readonly Decorator[] | undefined, modifiers: readonly Modifier[] | undefined, importClause: ImportClause | undefined, moduleSpecifier: Expression, assertClause: AssertClause | undefined): ImportDeclaration;
}

declare function every<T, U extends T>(array: readonly T[], callback: (element: T, index: number) => element is U): array is readonly U[];
declare function every<T, U extends T>(array: readonly T[] | undefined, callback: (element: T, index: number) => element is U): array is readonly U[] | undefined;
declare function every<T>(array: readonly T[] | undefined, callback: (element: T, index: number) => boolean): boolean;

declare function isArray(value: any): value is readonly unknown[];

declare const DISALLOW_DECORATORS: DeprecationOptions;

buildOverload("updateImportDeclaration")
.overload({
0(node: ImportDeclaration, modifiers: readonly Modifier[] | undefined, importClause: ImportClause | undefined, moduleSpecifier: Expression, assertClause: AssertClause | undefined): ImportDeclaration {
return updateImportDeclaration(node, modifiers, importClause, moduleSpecifier, assertClause);
},

1(node: ImportDeclaration, _decorators: readonly Decorator[] | undefined, modifiers: readonly Modifier[] | undefined, importClause: ImportClause | undefined, moduleSpecifier: Expression, assertClause: AssertClause | undefined): ImportDeclaration {
return updateImportDeclaration(node, modifiers, importClause, moduleSpecifier, assertClause);
},
})
.bind({
0: ([, modifiers, importClause, moduleSpecifier, assertClause, other]) =>
(other === undefined) &&
(modifiers === undefined || every(modifiers, isModifier)) &&
(importClause === undefined || !isArray(importClause)) &&
(moduleSpecifier === undefined || isExpression(moduleSpecifier)) &&
(assertClause === undefined || isAssertClause(assertClause)),

1: ([, decorators, modifiers, importClause, moduleSpecifier, assertClause]) =>
(decorators === undefined || every(decorators, isDecorator)) &&
(modifiers === undefined || isArray(modifiers)) &&
(importClause === undefined || isImportClause(importClause)) &&
(moduleSpecifier !== undefined && isExpression(moduleSpecifier)) &&
(assertClause === undefined || isAssertClause(assertClause)),
})
.deprecate({
1: DISALLOW_DECORATORS
})
.finish();


declare const modifiers: readonly Modifier[] | readonly Decorator[];

function foo() {
every(modifiers, isModifier);
every(modifiers, isDecorator);
}


//// [coAndContraVariantInferences3.js]
"use strict";
;
buildOverload("updateImportDeclaration")
.overload({
0: function (node, modifiers, importClause, moduleSpecifier, assertClause) {
return updateImportDeclaration(node, modifiers, importClause, moduleSpecifier, assertClause);
},
1: function (node, _decorators, modifiers, importClause, moduleSpecifier, assertClause) {
return updateImportDeclaration(node, modifiers, importClause, moduleSpecifier, assertClause);
},
})
.bind({
0: function (_a) {
var modifiers = _a[1], importClause = _a[2], moduleSpecifier = _a[3], assertClause = _a[4], other = _a[5];
return (other === undefined) &&
(modifiers === undefined || every(modifiers, isModifier)) &&
(importClause === undefined || !isArray(importClause)) &&
(moduleSpecifier === undefined || isExpression(moduleSpecifier)) &&
(assertClause === undefined || isAssertClause(assertClause));
},
1: function (_a) {
var decorators = _a[1], modifiers = _a[2], importClause = _a[3], moduleSpecifier = _a[4], assertClause = _a[5];
return (decorators === undefined || every(decorators, isDecorator)) &&
(modifiers === undefined || isArray(modifiers)) &&
(importClause === undefined || isImportClause(importClause)) &&
(moduleSpecifier !== undefined && isExpression(moduleSpecifier)) &&
(assertClause === undefined || isAssertClause(assertClause));
},
})
.deprecate({
1: DISALLOW_DECORATORS
})
.finish();
function foo() {
every(modifiers, isModifier);
every(modifiers, isDecorator);
}
Loading

0 comments on commit 28e4c81

Please sign in to comment.