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鈥檒l occasionally send you account related emails.

Already on GitHub? Sign in to your account

馃 Cherry-pick PR #33213 into release-3.6 #33245

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
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)} />;
}
}
}