Skip to content

Commit

Permalink
Cherry-pick PR #33213 into release-3.6 (#33245)
Browse files Browse the repository at this point in the history
Component commits:
cc1dc3b someTypeRelatedToType now passes isIntersectionConstituent

cf3eadc Merge branch 'master' into fix-missed-intersection-constituent-threading

f10fe38 Fix [][] lint
  • Loading branch information
typescript-bot authored and sandersn committed Sep 4, 2019
1 parent 49b910e commit 1ec17a8
Show file tree
Hide file tree
Showing 6 changed files with 176 additions and 10 deletions.
20 changes: 10 additions & 10 deletions src/compiler/checker.ts
Expand Up @@ -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 {
Expand Down Expand Up @@ -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(<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 @@ -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;
}
Expand Down Expand Up @@ -21542,13 +21542,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 @@ -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;
Expand All @@ -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;
}
}
}
Expand All @@ -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;
Expand Down Expand Up @@ -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;
Expand Down
@@ -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'.
}
}
}

@@ -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;
@@ -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))
}
}
}

@@ -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
}
}
}

@@ -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)} />;
}
}
}

0 comments on commit 1ec17a8

Please sign in to comment.