From db2aea0c8ac28adde66ced09cc6adf7351880908 Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders Date: Wed, 4 Sep 2019 20:41:31 +0000 Subject: [PATCH] Cherry-pick PR #33213 into release-3.6 Component commits: cc1dc3b83b someTypeRelatedToType now passes isIntersectionConstituent cf3eadc85e Merge branch 'master' into fix-missed-intersection-constituent-threading f10fe3891f Fix [][] lint --- src/compiler/checker.ts | 20 ++++---- ...ctionCheckCorrectlyCachesErrors.errors.txt | 20 ++++++++ ...kIntersectionCheckCorrectlyCachesErrors.js | 42 ++++++++++++++++ ...rsectionCheckCorrectlyCachesErrors.symbols | 48 +++++++++++++++++++ ...tersectionCheckCorrectlyCachesErrors.types | 41 ++++++++++++++++ ...kIntersectionCheckCorrectlyCachesErrors.ts | 15 ++++++ 6 files changed, 176 insertions(+), 10 deletions(-) create mode 100644 tests/baselines/reference/quickIntersectionCheckCorrectlyCachesErrors.errors.txt create mode 100644 tests/baselines/reference/quickIntersectionCheckCorrectlyCachesErrors.js create mode 100644 tests/baselines/reference/quickIntersectionCheckCorrectlyCachesErrors.symbols create mode 100644 tests/baselines/reference/quickIntersectionCheckCorrectlyCachesErrors.types create mode 100644 tests/cases/compiler/quickIntersectionCheckCorrectlyCachesErrors.ts diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index f8fd620213241..b0cf7dad335e3 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -12846,7 +12846,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 { @@ -12884,7 +12884,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(source, target, /*reportErrors*/ false); + result = someTypeRelatedToType(source, target, /*reportErrors*/ false, /*isIntersectionConstituent*/ true); } if (!result && (source.flags & TypeFlags.StructuredOrInstantiable || target.flags & TypeFlags.StructuredOrInstantiable)) { if (result = recursiveTypeRelatedTo(source, target, reportErrors, isIntersectionConstituent)) { @@ -13163,14 +13163,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; } @@ -21542,13 +21542,13 @@ namespace ts { checkMode: CheckMode, reportErrors: boolean, containingMessageChain: (() => DiagnosticMessageChain | undefined) | undefined, - ) { + ): ReadonlyArray | 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; } @@ -21563,7 +21563,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; @@ -21581,7 +21581,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; } } } @@ -21591,7 +21591,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; @@ -21982,7 +21982,7 @@ namespace ts { } } else { - const allDiagnostics: DiagnosticRelatedInformation[][] = []; + const allDiagnostics: (readonly DiagnosticRelatedInformation[])[] = []; let max = 0; let min = Number.MAX_VALUE; let minIndex = 0; diff --git a/tests/baselines/reference/quickIntersectionCheckCorrectlyCachesErrors.errors.txt b/tests/baselines/reference/quickIntersectionCheckCorrectlyCachesErrors.errors.txt new file mode 100644 index 0000000000000..09dd54b1b9873 --- /dev/null +++ b/tests/baselines/reference/quickIntersectionCheckCorrectlyCachesErrors.errors.txt @@ -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

{ + (props: P & { children?: boolean }): void; + propTypes: { [K in keyof P]: null extends P ? K : K }; + } + declare function g(C: F): string; + export function wu(CC: F) { + class WU { + m() { + g(CC) + return ; + ~~ +!!! error TS2304: Cannot find name 'React'. + } + } + } + \ No newline at end of file diff --git a/tests/baselines/reference/quickIntersectionCheckCorrectlyCachesErrors.js b/tests/baselines/reference/quickIntersectionCheckCorrectlyCachesErrors.js new file mode 100644 index 0000000000000..b6e6cd8a1d0d3 --- /dev/null +++ b/tests/baselines/reference/quickIntersectionCheckCorrectlyCachesErrors.js @@ -0,0 +1,42 @@ +//// [quickIntersectionCheckCorrectlyCachesErrors.tsx] +interface F

{ + (props: P & { children?: boolean }): void; + propTypes: { [K in keyof P]: null extends P ? K : K }; +} +declare function g(C: F): string; +export function wu(CC: F) { + class WU { + m() { + g(CC) + return ; + } + } +} + + +//// [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; diff --git a/tests/baselines/reference/quickIntersectionCheckCorrectlyCachesErrors.symbols b/tests/baselines/reference/quickIntersectionCheckCorrectlyCachesErrors.symbols new file mode 100644 index 0000000000000..d712254288488 --- /dev/null +++ b/tests/baselines/reference/quickIntersectionCheckCorrectlyCachesErrors.symbols @@ -0,0 +1,48 @@ +=== tests/cases/compiler/quickIntersectionCheckCorrectlyCachesErrors.tsx === +interface F

{ +>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): 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(CC: F) { +>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 : Symbol(CC, Decl(quickIntersectionCheckCorrectlyCachesErrors.tsx, 5, 45)) +>CP : Symbol(CP, Decl(quickIntersectionCheckCorrectlyCachesErrors.tsx, 5, 19)) + } + } +} + diff --git a/tests/baselines/reference/quickIntersectionCheckCorrectlyCachesErrors.types b/tests/baselines/reference/quickIntersectionCheckCorrectlyCachesErrors.types new file mode 100644 index 0000000000000..04153e6e1df8e --- /dev/null +++ b/tests/baselines/reference/quickIntersectionCheckCorrectlyCachesErrors.types @@ -0,0 +1,41 @@ +=== tests/cases/compiler/quickIntersectionCheckCorrectlyCachesErrors.tsx === +interface F

{ + (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): string; +>g : (C: F) => string +>C : F + +export function wu(CC: F) { +>wu : (CC: F) => void +>o : object +>CC : F + + class WU { +>WU : WU + + m() { +>m : () => any + + g(CC) +>g(CC) : string +>g : (C: F) => string +>CC : F + + return ; +> : any +>CC : F +>(null as unknown as CP) : CP +>null as unknown as CP : CP +>null as unknown : unknown +>null : null + } + } +} + diff --git a/tests/cases/compiler/quickIntersectionCheckCorrectlyCachesErrors.ts b/tests/cases/compiler/quickIntersectionCheckCorrectlyCachesErrors.ts new file mode 100644 index 0000000000000..3dbc6ec9ec3f7 --- /dev/null +++ b/tests/cases/compiler/quickIntersectionCheckCorrectlyCachesErrors.ts @@ -0,0 +1,15 @@ +// @jsx: react +// @filename: quickIntersectionCheckCorrectlyCachesErrors.tsx +interface F

{ + (props: P & { children?: boolean }): void; + propTypes: { [K in keyof P]: null extends P ? K : K }; +} +declare function g(C: F): string; +export function wu(CC: F) { + class WU { + m() { + g(CC) + return ; + } + } +}