Skip to content
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

someTypeRelatedToType now passes isIntersectionConstituent #33213

Merged
merged 3 commits into from
Sep 4, 2019
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
20 changes: 10 additions & 10 deletions src/compiler/checker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12885,7 +12885,7 @@ namespace ts {
// and we need to handle "each" relations before "some" relations for the same kind of type.
if (source.flags & TypeFlags.Union) {
result = relation === comparableRelation ?
someTypeRelatedToType(source as UnionType, target, reportErrors && !(source.flags & TypeFlags.Primitive)) :
someTypeRelatedToType(source as UnionType, target, reportErrors && !(source.flags & TypeFlags.Primitive), isIntersectionConstituent) :
eachTypeRelatedToType(source as UnionType, target, reportErrors && !(source.flags & TypeFlags.Primitive));
}
else {
Expand Down Expand Up @@ -12923,7 +12923,7 @@ namespace ts {
//
// - For a primitive type or type parameter (such as 'number = A & B') there is no point in
// breaking the intersection apart.
result = someTypeRelatedToType(<IntersectionType>source, target, /*reportErrors*/ false);
result = someTypeRelatedToType(<IntersectionType>source, target, /*reportErrors*/ false, /*isIntersectionConstituent*/ true);
}
if (!result && (source.flags & TypeFlags.StructuredOrInstantiable || target.flags & TypeFlags.StructuredOrInstantiable)) {
if (result = recursiveTypeRelatedTo(source, target, reportErrors, isIntersectionConstituent)) {
Expand Down Expand Up @@ -13202,14 +13202,14 @@ namespace ts {
return result;
}

function someTypeRelatedToType(source: UnionOrIntersectionType, target: Type, reportErrors: boolean): Ternary {
function someTypeRelatedToType(source: UnionOrIntersectionType, target: Type, reportErrors: boolean, isIntersectionConstituent: boolean): Ternary {
const sourceTypes = source.types;
if (source.flags & TypeFlags.Union && containsType(sourceTypes, target)) {
return Ternary.True;
}
const len = sourceTypes.length;
for (let i = 0; i < len; i++) {
const related = isRelatedTo(sourceTypes[i], target, reportErrors && i === len - 1);
const related = isRelatedTo(sourceTypes[i], target, reportErrors && i === len - 1, /*headMessage*/ undefined, isIntersectionConstituent);
if (related) {
return related;
}
Expand Down Expand Up @@ -21578,13 +21578,13 @@ namespace ts {
checkMode: CheckMode,
reportErrors: boolean,
containingMessageChain: (() => DiagnosticMessageChain | undefined) | undefined,
) {
): ReadonlyArray<Diagnostic> | undefined {

const errorOutputContainer: { errors?: Diagnostic[], skipLogging?: boolean } = { errors: undefined, skipLogging: true };
if (isJsxOpeningLikeElement(node)) {
if (!checkApplicableSignatureForJsxOpeningLikeElement(node, signature, relation, checkMode, reportErrors, containingMessageChain, errorOutputContainer)) {
Debug.assert(!reportErrors || !!errorOutputContainer.errors, "jsx should have errors when reporting errors");
return errorOutputContainer.errors || [];
return errorOutputContainer.errors || emptyArray;
}
return undefined;
}
Expand All @@ -21599,7 +21599,7 @@ namespace ts {
const headMessage = Diagnostics.The_this_context_of_type_0_is_not_assignable_to_method_s_this_of_type_1;
if (!checkTypeRelatedTo(thisArgumentType, thisType, relation, errorNode, headMessage, containingMessageChain, errorOutputContainer)) {
Debug.assert(!reportErrors || !!errorOutputContainer.errors, "this parameter should have errors when reporting errors");
return errorOutputContainer.errors || [];
return errorOutputContainer.errors || emptyArray;
}
}
const headMessage = Diagnostics.Argument_of_type_0_is_not_assignable_to_parameter_of_type_1;
Expand All @@ -21617,7 +21617,7 @@ namespace ts {
if (!checkTypeRelatedToAndOptionallyElaborate(checkArgType, paramType, relation, reportErrors ? arg : undefined, arg, headMessage, containingMessageChain, errorOutputContainer)) {
Debug.assert(!reportErrors || !!errorOutputContainer.errors, "parameter should have errors when reporting errors");
maybeAddMissingAwaitInfo(arg, checkArgType, paramType);
return errorOutputContainer.errors || [];
return errorOutputContainer.errors || emptyArray;
}
}
}
Expand All @@ -21627,7 +21627,7 @@ namespace ts {
if (!checkTypeRelatedTo(spreadType, restType, relation, errorNode, headMessage, /*containingMessageChain*/ undefined, errorOutputContainer)) {
Debug.assert(!reportErrors || !!errorOutputContainer.errors, "rest parameter should have errors when reporting errors");
maybeAddMissingAwaitInfo(errorNode, spreadType, restType);
return errorOutputContainer.errors || [];
return errorOutputContainer.errors || emptyArray;
}
}
return undefined;
Expand Down Expand Up @@ -22018,7 +22018,7 @@ namespace ts {
}
}
else {
const allDiagnostics: DiagnosticRelatedInformation[][] = [];
const allDiagnostics: Array<ReadonlyArray<DiagnosticRelatedInformation>> = [];
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
const allDiagnostics: Array<ReadonlyArray<DiagnosticRelatedInformation>> = [];
const allDiagnostics: (readonly DiagnosticRelatedInformation[])[] = [];

to fix that lint failure.

Copy link
Member Author

@sandersn sandersn Sep 4, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Our parsing for readonly T[][] is so bad, and yet we have a lint rule requiring it.

let max = 0;
let min = Number.MAX_VALUE;
let minIndex = 0;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
tests/cases/compiler/quickIntersectionCheckCorrectlyCachesErrors.tsx(10,21): error TS2304: Cannot find name 'React'.


==== tests/cases/compiler/quickIntersectionCheckCorrectlyCachesErrors.tsx (1 errors) ====
interface F<P> {
(props: P & { children?: boolean }): void;
propTypes: { [K in keyof P]: null extends P ? K : K };
}
declare function g(C: F<unknown>): string;
export function wu<CP extends { o: object }>(CC: F<CP>) {
class WU {
m() {
g(CC)
return <CC {...(null as unknown as CP)} />;
~~
!!! error TS2304: Cannot find name 'React'.
}
}
}

Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
//// [quickIntersectionCheckCorrectlyCachesErrors.tsx]
interface F<P> {
(props: P & { children?: boolean }): void;
propTypes: { [K in keyof P]: null extends P ? K : K };
}
declare function g(C: F<unknown>): string;
export function wu<CP extends { o: object }>(CC: F<CP>) {
class WU {
m() {
g(CC)
return <CC {...(null as unknown as CP)} />;
}
}
}


//// [quickIntersectionCheckCorrectlyCachesErrors.js]
"use strict";
var __assign = (this && this.__assign) || function () {
__assign = Object.assign || function(t) {
for (var s, i = 1, n = arguments.length; i < n; i++) {
s = arguments[i];
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
t[p] = s[p];
}
return t;
};
return __assign.apply(this, arguments);
};
exports.__esModule = true;
function wu(CC) {
var WU = /** @class */ (function () {
function WU() {
}
WU.prototype.m = function () {
g(CC);
return React.createElement(CC, __assign({}, null));
};
return WU;
}());
}
exports.wu = wu;
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
=== tests/cases/compiler/quickIntersectionCheckCorrectlyCachesErrors.tsx ===
interface F<P> {
>F : Symbol(F, Decl(quickIntersectionCheckCorrectlyCachesErrors.tsx, 0, 0))
>P : Symbol(P, Decl(quickIntersectionCheckCorrectlyCachesErrors.tsx, 0, 12))

(props: P & { children?: boolean }): void;
>props : Symbol(props, Decl(quickIntersectionCheckCorrectlyCachesErrors.tsx, 1, 5))
>P : Symbol(P, Decl(quickIntersectionCheckCorrectlyCachesErrors.tsx, 0, 12))
>children : Symbol(children, Decl(quickIntersectionCheckCorrectlyCachesErrors.tsx, 1, 17))

propTypes: { [K in keyof P]: null extends P ? K : K };
>propTypes : Symbol(F.propTypes, Decl(quickIntersectionCheckCorrectlyCachesErrors.tsx, 1, 46))
>K : Symbol(K, Decl(quickIntersectionCheckCorrectlyCachesErrors.tsx, 2, 18))
>P : Symbol(P, Decl(quickIntersectionCheckCorrectlyCachesErrors.tsx, 0, 12))
>P : Symbol(P, Decl(quickIntersectionCheckCorrectlyCachesErrors.tsx, 0, 12))
>K : Symbol(K, Decl(quickIntersectionCheckCorrectlyCachesErrors.tsx, 2, 18))
>K : Symbol(K, Decl(quickIntersectionCheckCorrectlyCachesErrors.tsx, 2, 18))
}
declare function g(C: F<unknown>): string;
>g : Symbol(g, Decl(quickIntersectionCheckCorrectlyCachesErrors.tsx, 3, 1))
>C : Symbol(C, Decl(quickIntersectionCheckCorrectlyCachesErrors.tsx, 4, 19))
>F : Symbol(F, Decl(quickIntersectionCheckCorrectlyCachesErrors.tsx, 0, 0))

export function wu<CP extends { o: object }>(CC: F<CP>) {
>wu : Symbol(wu, Decl(quickIntersectionCheckCorrectlyCachesErrors.tsx, 4, 42))
>CP : Symbol(CP, Decl(quickIntersectionCheckCorrectlyCachesErrors.tsx, 5, 19))
>o : Symbol(o, Decl(quickIntersectionCheckCorrectlyCachesErrors.tsx, 5, 31))
>CC : Symbol(CC, Decl(quickIntersectionCheckCorrectlyCachesErrors.tsx, 5, 45))
>F : Symbol(F, Decl(quickIntersectionCheckCorrectlyCachesErrors.tsx, 0, 0))
>CP : Symbol(CP, Decl(quickIntersectionCheckCorrectlyCachesErrors.tsx, 5, 19))

class WU {
>WU : Symbol(WU, Decl(quickIntersectionCheckCorrectlyCachesErrors.tsx, 5, 57))

m() {
>m : Symbol(WU.m, Decl(quickIntersectionCheckCorrectlyCachesErrors.tsx, 6, 14))

g(CC)
>g : Symbol(g, Decl(quickIntersectionCheckCorrectlyCachesErrors.tsx, 3, 1))
>CC : Symbol(CC, Decl(quickIntersectionCheckCorrectlyCachesErrors.tsx, 5, 45))

return <CC {...(null as unknown as CP)} />;
>CC : Symbol(CC, Decl(quickIntersectionCheckCorrectlyCachesErrors.tsx, 5, 45))
>CP : Symbol(CP, Decl(quickIntersectionCheckCorrectlyCachesErrors.tsx, 5, 19))
}
}
}

Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
=== tests/cases/compiler/quickIntersectionCheckCorrectlyCachesErrors.tsx ===
interface F<P> {
(props: P & { children?: boolean }): void;
>props : P & { children?: boolean; }
>children : boolean

propTypes: { [K in keyof P]: null extends P ? K : K };
>propTypes : { [K in keyof P]: null extends P ? K : K; }
>null : null
}
declare function g(C: F<unknown>): string;
>g : (C: F<unknown>) => string
>C : F<unknown>

export function wu<CP extends { o: object }>(CC: F<CP>) {
>wu : <CP extends { o: object; }>(CC: F<CP>) => void
>o : object
>CC : F<CP>

class WU {
>WU : WU

m() {
>m : () => any

g(CC)
>g(CC) : string
>g : (C: F<unknown>) => string
>CC : F<CP>

return <CC {...(null as unknown as CP)} />;
><CC {...(null as unknown as CP)} /> : any
>CC : F<CP>
>(null as unknown as CP) : CP
>null as unknown as CP : CP
>null as unknown : unknown
>null : null
}
}
}

Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
// @jsx: react
// @filename: quickIntersectionCheckCorrectlyCachesErrors.tsx
interface F<P> {
(props: P & { children?: boolean }): void;
propTypes: { [K in keyof P]: null extends P ? K : K };
}
declare function g(C: F<unknown>): string;
export function wu<CP extends { o: object }>(CC: F<CP>) {
class WU {
m() {
g(CC)
return <CC {...(null as unknown as CP)} />;
}
}
}