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

🤖 Cherry-pick PR #33213 into release-3.6 #33245

Merged
Merged
Changes from all commits
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
Cherry-pick PR #33213 into release-3.6
Component commits:
cc1dc3b someTypeRelatedToType now passes isIntersectionConstituent

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

f10fe38 Fix [][] lint
sandersn authored and typescript-bot committed Sep 4, 2019

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
commit db2aea0c8ac28adde66ced09cc6adf7351880908
20 changes: 10 additions & 10 deletions src/compiler/checker.ts
Original file line number Diff line number Diff line change
@@ -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(<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)) {
@@ -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<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;
}
@@ -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;
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)} />;
}
}
}