"Fossies" - the Fresh Open Source Software Archive  

Source code changes of the file "src/compiler/checker.ts" between
TypeScript-3.6.2.tar.gz and TypeScript-3.6.3.tar.gz

About: Microsoft\PKG_DESCR_TTrsquo;s TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

checker.ts  (TypeScript-3.6.2):checker.ts  (TypeScript-3.6.3)
skipping to change at line 9980 skipping to change at line 9980
type.flags & TypeFlags.UniqueESSymbol ? esSymbolType : type.flags & TypeFlags.UniqueESSymbol ? esSymbolType :
undefined; undefined;
if (!primitive || !containsType(u.types, primitive)) { if (!primitive || !containsType(u.types, primitive)) {
return false; return false;
} }
} }
} }
return true; return true;
} }
function extractIrreducible(types: Type[], flag: TypeFlags) {
if (every(types, t => !!(t.flags & TypeFlags.Union) && some((t as Un
ionType).types, tt => !!(tt.flags & flag)))) {
for (let i = 0; i < types.length; i++) {
types[i] = filterType(types[i], t => !(t.flags & flag));
}
return true;
}
return false;
}
// If the given list of types contains more than one union of primitive types, replace the // If the given list of types contains more than one union of primitive types, replace the
// first with a union containing an intersection of those primitive type s, then remove the // first with a union containing an intersection of those primitive type s, then remove the
// other unions and return true. Otherwise, do nothing and return false. // other unions and return true. Otherwise, do nothing and return false.
function intersectUnionsOfPrimitiveTypes(types: Type[]) { function intersectUnionsOfPrimitiveTypes(types: Type[]) {
let unionTypes: UnionType[] | undefined; let unionTypes: UnionType[] | undefined;
const index = findIndex(types, t => !!(getObjectFlags(t) & ObjectFla gs.PrimitiveUnion)); const index = findIndex(types, t => !!(getObjectFlags(t) & ObjectFla gs.PrimitiveUnion));
if (index < 0) { if (index < 0) {
return false; return false;
} }
let i = index + 1; let i = index + 1;
skipping to change at line 10098 skipping to change at line 10108
const id = getTypeListId(typeSet); const id = getTypeListId(typeSet);
let result = intersectionTypes.get(id); let result = intersectionTypes.get(id);
if (!result) { if (!result) {
if (includes & TypeFlags.Union) { if (includes & TypeFlags.Union) {
if (intersectUnionsOfPrimitiveTypes(typeSet)) { if (intersectUnionsOfPrimitiveTypes(typeSet)) {
// When the intersection creates a reduced set (which mi ght mean that *all* union types have // When the intersection creates a reduced set (which mi ght mean that *all* union types have
// disappeared), we restart the operation to get a new s et of combined flags. Once we have // disappeared), we restart the operation to get a new s et of combined flags. Once we have
// reduced we'll never reduce again, so this occurs at m ost once. // reduced we'll never reduce again, so this occurs at m ost once.
result = getIntersectionType(typeSet, aliasSymbol, alias TypeArguments); result = getIntersectionType(typeSet, aliasSymbol, alias TypeArguments);
} }
else if (extractIrreducible(typeSet, TypeFlags.Undefined)) {
result = getUnionType([getIntersectionType(typeSet), und
efinedType], UnionReduction.Literal, aliasSymbol, aliasTypeArguments);
}
else if (extractIrreducible(typeSet, TypeFlags.Null)) {
result = getUnionType([getIntersectionType(typeSet), nul
lType], UnionReduction.Literal, aliasSymbol, aliasTypeArguments);
}
else { else {
// We are attempting to construct a type of the form X & (A | B) & Y. Transform this into a type of // We are attempting to construct a type of the form X & (A | B) & Y. Transform this into a type of
// the form X & A & Y | X & B & Y and recursively reduce until no union type constituents remain. // the form X & A & Y | X & B & Y and recursively reduce until no union type constituents remain.
// If the estimated size of the resulting union type exc eeds 100000 constituents, report an error. // If the estimated size of the resulting union type exc eeds 100000 constituents, report an error.
const size = reduceLeft(typeSet, (n, t) => n * (t.flags & TypeFlags.Union ? (<UnionType>t).types.length : 1), 1); const size = reduceLeft(typeSet, (n, t) => n * (t.flags & TypeFlags.Union ? (<UnionType>t).types.length : 1), 1);
if (size >= 100000) { if (size >= 100000) {
error(currentNode, Diagnostics.Expression_produces_a _union_type_that_is_too_complex_to_represent); error(currentNode, Diagnostics.Expression_produces_a _union_type_that_is_too_complex_to_represent);
return errorType; return errorType;
} }
const unionIndex = findIndex(typeSet, t => (t.flags & Ty peFlags.Union) !== 0); const unionIndex = findIndex(typeSet, t => (t.flags & Ty peFlags.Union) !== 0);
skipping to change at line 12846 skipping to change at line 12862
let result = Ternary.False; let result = Ternary.False;
const saveErrorInfo = errorInfo; const saveErrorInfo = errorInfo;
let isIntersectionConstituent = !!isApparentIntersectionConstitu ent; let isIntersectionConstituent = !!isApparentIntersectionConstitu ent;
// Note that these checks are specifically ordered to produce co rrect results. In particular, // Note that these checks are specifically ordered to produce co rrect results. In particular,
// we need to deconstruct unions before intersections (because u nions are always at the top), // we need to deconstruct unions before intersections (because u nions are always at the top),
// and we need to handle "each" relations before "some" relation s for the same kind of type. // and we need to handle "each" relations before "some" relation s for the same kind of type.
if (source.flags & TypeFlags.Union) { if (source.flags & TypeFlags.Union) {
result = relation === comparableRelation ? result = relation === comparableRelation ?
someTypeRelatedToType(source as UnionType, target, repor tErrors && !(source.flags & TypeFlags.Primitive)) : someTypeRelatedToType(source as UnionType, target, repor tErrors && !(source.flags & TypeFlags.Primitive), isIntersectionConstituent) :
eachTypeRelatedToType(source as UnionType, target, repor tErrors && !(source.flags & TypeFlags.Primitive)); eachTypeRelatedToType(source as UnionType, target, repor tErrors && !(source.flags & TypeFlags.Primitive));
} }
else { else {
if (target.flags & TypeFlags.Union) { if (target.flags & TypeFlags.Union) {
result = typeRelatedToSomeType(getRegularTypeOfObjectLit eral(source), <UnionType>target, reportErrors && !(source.flags & TypeFlags.Prim itive) && !(target.flags & TypeFlags.Primitive)); result = typeRelatedToSomeType(getRegularTypeOfObjectLit eral(source), <UnionType>target, reportErrors && !(source.flags & TypeFlags.Prim itive) && !(target.flags & TypeFlags.Primitive));
if (result && (isPerformingExcessPropertyChecks || isPer formingCommonPropertyChecks)) { if (result && (isPerformingExcessPropertyChecks || isPer formingCommonPropertyChecks)) {
// Validate against excess props using the original `source` // Validate against excess props using the original `source`
const discriminantType = findMatchingDiscriminantTyp e(source, target as UnionType) || filterPrimitivesIfContainsNonPrimitive(target as UnionType); const discriminantType = findMatchingDiscriminantTyp e(source, target as UnionType) || filterPrimitivesIfContainsNonPrimitive(target as UnionType);
if (!propertiesRelatedTo(source, discriminantType, r eportErrors, /*excludedProperties*/ undefined, isIntersectionConstituent)) { if (!propertiesRelatedTo(source, discriminantType, r eportErrors, /*excludedProperties*/ undefined, isIntersectionConstituent)) {
return Ternary.False; return Ternary.False;
skipping to change at line 12884 skipping to change at line 12900
// useful and leads to some confusing error messages. In stead it is better to let the below checks // useful and leads to some confusing error messages. In stead it is better to let the below checks
// take care of this, or to not elaborate at all. For in stance, // take care of this, or to not elaborate at all. For in stance,
// //
// - For an object type (such as 'C = A & B'), users are usually more interested in structural errors. // - For an object type (such as 'C = A & B'), users are usually more interested in structural errors.
// //
// - For a union type (such as '(A | B) = (C & D)'), it's better to hold onto the whole intersection // - For a union type (such as '(A | B) = (C & D)'), it's better to hold onto the whole intersection
// than to report that 'D' is not assignable to 'A' or 'B'. // than to report that 'D' is not assignable to 'A' or 'B'.
// //
// - For a primitive type or type parameter (such as 'number = A & B') there is no point in // - For a primitive type or type parameter (such as 'number = A & B') there is no point in
// breaking the intersection apart. // 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.StructuredOrInstant iable || target.flags & TypeFlags.StructuredOrInstantiable)) { if (!result && (source.flags & TypeFlags.StructuredOrInstant iable || target.flags & TypeFlags.StructuredOrInstantiable)) {
if (result = recursiveTypeRelatedTo(source, target, repo rtErrors, isIntersectionConstituent)) { if (result = recursiveTypeRelatedTo(source, target, repo rtErrors, isIntersectionConstituent)) {
errorInfo = saveErrorInfo; errorInfo = saveErrorInfo;
} }
} }
} }
if (!result && source.flags & TypeFlags.Intersection) { if (!result && source.flags & TypeFlags.Intersection) {
// The combined constraint of an intersection type is the in tersection of the constraints of // The combined constraint of an intersection type is the in tersection of the constraints of
// the constituents. When an intersection type contains inst antiable types with union type // the constituents. When an intersection type contains inst antiable types with union type
skipping to change at line 13163 skipping to change at line 13179
for (const targetType of targetTypes) { for (const targetType of targetTypes) {
const related = isRelatedTo(source, targetType, reportErrors , /*headMessage*/ undefined, /*isIntersectionConstituent*/ true); const related = isRelatedTo(source, targetType, reportErrors , /*headMessage*/ undefined, /*isIntersectionConstituent*/ true);
if (!related) { if (!related) {
return Ternary.False; return Ternary.False;
} }
result &= related; result &= related;
} }
return result; return result;
} }
function someTypeRelatedToType(source: UnionOrIntersectionType, targ et: Type, reportErrors: boolean): Ternary { function someTypeRelatedToType(source: UnionOrIntersectionType, targ et: Type, reportErrors: boolean, isIntersectionConstituent: boolean): Ternary {
const sourceTypes = source.types; const sourceTypes = source.types;
if (source.flags & TypeFlags.Union && containsType(sourceTypes, target)) { if (source.flags & TypeFlags.Union && containsType(sourceTypes, target)) {
return Ternary.True; return Ternary.True;
} }
const len = sourceTypes.length; const len = sourceTypes.length;
for (let i = 0; i < len; i++) { for (let i = 0; i < len; i++) {
const related = isRelatedTo(sourceTypes[i], target, reportEr rors && i === len - 1); const related = isRelatedTo(sourceTypes[i], target, reportEr rors && i === len - 1, /*headMessage*/ undefined, isIntersectionConstituent);
if (related) { if (related) {
return related; return related;
} }
} }
return Ternary.False; return Ternary.False;
} }
function eachTypeRelatedToType(source: UnionOrIntersectionType, targ et: Type, reportErrors: boolean): Ternary { function eachTypeRelatedToType(source: UnionOrIntersectionType, targ et: Type, reportErrors: boolean): Ternary {
let result = Ternary.True; let result = Ternary.True;
const sourceTypes = source.types; const sourceTypes = source.types;
skipping to change at line 14500 skipping to change at line 14516
function isClassDerivedFromDeclaringClasses(checkClass: Type, prop: Symb ol) { function isClassDerivedFromDeclaringClasses(checkClass: Type, prop: Symb ol) {
return forEachProperty(prop, p => getDeclarationModifierFlagsFromSym bol(p) & ModifierFlags.Protected ? return forEachProperty(prop, p => getDeclarationModifierFlagsFromSym bol(p) & ModifierFlags.Protected ?
!hasBaseType(checkClass, getDeclaringClass(p)) : false) ? undefi ned : checkClass; !hasBaseType(checkClass, getDeclaringClass(p)) : false) ? undefi ned : checkClass;
} }
// Return true if the given type is deeply nested. We consider this to b e the case when structural type comparisons // Return true if the given type is deeply nested. We consider this to b e the case when structural type comparisons
// for 5 or more occurrences or instantiations of the type have been rec orded on the given stack. It is possible, // for 5 or more occurrences or instantiations of the type have been rec orded on the given stack. It is possible,
// though highly unlikely, for this test to be true in a situation where a chain of instantiations is not infinitely // though highly unlikely, for this test to be true in a situation where a chain of instantiations is not infinitely
// expanding. Effectively, we will generate a false positive when two ty pes are structurally equal to at least 5 // expanding. Effectively, we will generate a false positive when two ty pes are structurally equal to at least 5
// levels, but unequal at some level beyond that. // levels, but unequal at some level beyond that.
// In addition, this will also detect when an indexed access has been ch
ained off of 5 or more times (which is essentially
// the dual of the structural comparison), and likewise mark the type as
deeply nested, potentially adding false positives
// for finite but deeply expanding indexed accesses (eg, for `Q[P1][P2][
P3][P4][P5]`).
function isDeeplyNestedType(type: Type, stack: Type[], depth: number): b oolean { function isDeeplyNestedType(type: Type, stack: Type[], depth: number): b oolean {
// We track all object types that have an associated symbol (represe nting the origin of the type) // We track all object types that have an associated symbol (represe nting the origin of the type)
if (depth >= 5 && type.flags & TypeFlags.Object) { if (depth >= 5 && type.flags & TypeFlags.Object) {
const symbol = type.symbol; const symbol = type.symbol;
if (symbol) { if (symbol) {
let count = 0; let count = 0;
for (let i = 0; i < depth; i++) { for (let i = 0; i < depth; i++) {
const t = stack[i]; const t = stack[i];
if (t.flags & TypeFlags.Object && t.symbol === symbol) { if (t.flags & TypeFlags.Object && t.symbol === symbol) {
count++; count++;
if (count >= 5) return true; if (count >= 5) return true;
} }
} }
} }
} }
if (depth >= 5 && type.flags & TypeFlags.IndexedAccess) {
const root = getRootObjectTypeFromIndexedAccessChain(type);
let count = 0;
for (let i = 0; i < depth; i++) {
const t = stack[i];
if (getRootObjectTypeFromIndexedAccessChain(t) === root) {
count++;
if (count >= 5) return true;
}
}
}
return false; return false;
} }
/**
* Gets the leftmost object type in a chain of indexed accesses, eg, in
A[P][Q], returns A
*/
function getRootObjectTypeFromIndexedAccessChain(type: Type) {
let t = type;
while (t.flags & TypeFlags.IndexedAccess) {
t = (t as IndexedAccessType).objectType;
}
return t;
}
function isPropertyIdenticalTo(sourceProp: Symbol, targetProp: Symbol): boolean { function isPropertyIdenticalTo(sourceProp: Symbol, targetProp: Symbol): boolean {
return compareProperties(sourceProp, targetProp, compareTypesIdentic al) !== Ternary.False; return compareProperties(sourceProp, targetProp, compareTypesIdentic al) !== Ternary.False;
} }
function compareProperties(sourceProp: Symbol, targetProp: Symbol, compa reTypes: (source: Type, target: Type) => Ternary): Ternary { function compareProperties(sourceProp: Symbol, targetProp: Symbol, compa reTypes: (source: Type, target: Type) => Ternary): Ternary {
// Two members are considered identical when // Two members are considered identical when
// - they are public properties with identical names, optionality, a nd types, // - they are public properties with identical names, optionality, a nd types,
// - they are private or protected properties originating in the sam e declaration and having identical types // - they are private or protected properties originating in the sam e declaration and having identical types
if (sourceProp === targetProp) { if (sourceProp === targetProp) {
return Ternary.True; return Ternary.True;
skipping to change at line 15518 skipping to change at line 15559
} }
if (source === target && source.flags & TypeFlags.UnionOrInterse ction) { if (source === target && source.flags & TypeFlags.UnionOrInterse ction) {
// When source and target are the same union or intersection type, just relate each constituent // When source and target are the same union or intersection type, just relate each constituent
// type to itself. // type to itself.
for (const t of (<UnionOrIntersectionType>source).types) { for (const t of (<UnionOrIntersectionType>source).types) {
inferFromTypes(t, t); inferFromTypes(t, t);
} }
return; return;
} }
if (target.flags & TypeFlags.Union) { if (target.flags & TypeFlags.Union) {
if (source.flags & TypeFlags.Union) { // First, infer between identically matching source and targ
// First, infer between identically matching source and et constituents and remove the
target constituents and remove the // matching types.
// matching types. const [tempSources, tempTargets] = inferFromMatchingTypes(so
const [tempSources, tempTargets] = inferFromMatchingType urce.flags & TypeFlags.Union ? (<UnionType>source).types : [source], (<UnionType
s((<UnionType>source).types, (<UnionType>target).types, isTypeOrBaseIdenticalTo) >target).types, isTypeOrBaseIdenticalTo);
; // Next, infer between closely matching source and target co
// Next, infer between closely matching source and targe nstituents and remove
t constituents and remove // the matching types. Types closely match when they are ins
// the matching types. Types closely match when they are tantiations of the same
instantiations of the same // object type or instantiations of the same type alias.
// object type or instantiations of the same type alias. const [sources, targets] = inferFromMatchingTypes(tempSource
const [sources, targets] = inferFromMatchingTypes(tempSo s, tempTargets, isTypeCloselyMatchedBy);
urces, tempTargets, isTypeCloselyMatchedBy); if (targets.length === 0) {
if (sources.length === 0 || targets.length === 0) { return;
return;
}
source = getUnionType(sources);
target = getUnionType(targets);
} }
else { target = getUnionType(targets);
if (inferFromMatchingType(source, (<UnionType>target).ty if (sources.length === 0) {
pes, isTypeOrBaseIdenticalTo)) return; // All source constituents have been matched and there i
if (inferFromMatchingType(source, (<UnionType>target).ty s nothing further to infer from.
pes, isTypeCloselyMatchedBy)) return; // However, simply making no inferences is undesirable b
ecause it could ultimately mean
// inferring a type parameter constraint. Instead, make
a lower priority inference from
// the full source to whatever remains in the target. Fo
r example, when inferring from
// string to 'string | T', make a lower priority inferen
ce of string for T.
const savePriority = priority;
priority |= InferencePriority.NakedTypeVariable;
inferFromTypes(source, target);
priority = savePriority;
return;
} }
source = getUnionType(sources);
} }
else if (target.flags & TypeFlags.Intersection && some((<Interse else if (target.flags & TypeFlags.Intersection && some((<Interse
ctionType>target).types, t => !!getInferenceInfoForType(t))) { ctionType>target).types,
t => !!getInferenceInfoForType(t) || (isGenericMappedType(t)
&& !!getInferenceInfoForType(getHomomorphicTypeVariable(t) || neverType)))) {
// We reduce intersection types only when they contain naked type parameters. For example, when // We reduce intersection types only when they contain naked type parameters. For example, when
// inferring from 'string[] & { extra: any }' to 'string[] & T' we want to remove string[] and // inferring from 'string[] & { extra: any }' to 'string[] & T' we want to remove string[] and
// infer { extra: any } for T. But when inferring to 'string [] & Iterable<T>' we want to keep the // infer { extra: any } for T. But when inferring to 'string [] & Iterable<T>' we want to keep the
// string[] on the source side and infer string for T. // string[] on the source side and infer string for T.
if (source.flags & TypeFlags.Intersection) { // Likewise, we consider a homomorphic mapped type constrain
ted to the target type parameter as similar to a "naked type variable"
// in such scenarios.
if (!(source.flags & TypeFlags.Union)) {
// Infer between identically matching source and target constituents and remove the matching types. // Infer between identically matching source and target constituents and remove the matching types.
const [sources, targets] = inferFromMatchingTypes((<Inte rsectionType>source).types, (<IntersectionType>target).types, isTypeIdenticalTo) ; const [sources, targets] = inferFromMatchingTypes(source .flags & TypeFlags.Intersection ? (<IntersectionType>source).types : [source], ( <IntersectionType>target).types, isTypeIdenticalTo);
if (sources.length === 0 || targets.length === 0) { if (sources.length === 0 || targets.length === 0) {
return; return;
} }
source = getIntersectionType(sources); source = getIntersectionType(sources);
target = getIntersectionType(targets); target = getIntersectionType(targets);
} }
else if (!(source.flags & TypeFlags.Union)) {
if (inferFromMatchingType(source, (<IntersectionType>tar
get).types, isTypeIdenticalTo)) return;
}
} }
else if (target.flags & (TypeFlags.IndexedAccess | TypeFlags.Sub stitution)) { else if (target.flags & (TypeFlags.IndexedAccess | TypeFlags.Sub stitution)) {
target = getActualTypeVariable(target); target = getActualTypeVariable(target);
} }
if (target.flags & TypeFlags.TypeVariable) { if (target.flags & TypeFlags.TypeVariable) {
// If target is a type parameter, make an inference, unless the source type contains // If target is a type parameter, make an inference, unless the source type contains
// the anyFunctionType (the wildcard type that's used to avo id contextually typing functions). // the anyFunctionType (the wildcard type that's used to avo id contextually typing functions).
// Because the anyFunctionType is internal, it should not be exposed to the user by adding // Because the anyFunctionType is internal, it should not be exposed to the user by adding
// it as an inference candidate. Hopefully, a better candida te will come along that does // it as an inference candidate. Hopefully, a better candida te will come along that does
// not contain anyFunctionType when we come back to this arg ument for its second round // not contain anyFunctionType when we come back to this arg ument for its second round
skipping to change at line 15703 skipping to change at line 15750
return; return;
} }
(visited || (visited = createMap<number>())).set(key, InferenceP riority.Circularity); (visited || (visited = createMap<number>())).set(key, InferenceP riority.Circularity);
const saveInferencePriority = inferencePriority; const saveInferencePriority = inferencePriority;
inferencePriority = InferencePriority.MaxValue; inferencePriority = InferencePriority.MaxValue;
action(source, target); action(source, target);
visited.set(key, inferencePriority); visited.set(key, inferencePriority);
inferencePriority = Math.min(inferencePriority, saveInferencePri ority); inferencePriority = Math.min(inferencePriority, saveInferencePri ority);
} }
function inferFromMatchingType(source: Type, targets: Type[], matche
s: (s: Type, t: Type) => boolean) {
let matched = false;
for (const t of targets) {
if (matches(source, t)) {
inferFromTypes(source, t);
matched = true;
}
}
return matched;
}
function inferFromMatchingTypes(sources: Type[], targets: Type[], ma tches: (s: Type, t: Type) => boolean): [Type[], Type[]] { function inferFromMatchingTypes(sources: Type[], targets: Type[], ma tches: (s: Type, t: Type) => boolean): [Type[], Type[]] {
let matchedSources: Type[] | undefined; let matchedSources: Type[] | undefined;
let matchedTargets: Type[] | undefined; let matchedTargets: Type[] | undefined;
for (const t of targets) { for (const t of targets) {
for (const s of sources) { for (const s of sources) {
if (matches(s, t)) { if (matches(s, t)) {
inferFromTypes(s, t); inferFromTypes(s, t);
matchedSources = appendIfUnique(matchedSources, s); matchedSources = appendIfUnique(matchedSources, s);
matchedTargets = appendIfUnique(matchedTargets, t); matchedTargets = appendIfUnique(matchedTargets, t);
} }
skipping to change at line 21541 skipping to change at line 21577
} }
function getSignatureApplicabilityError( function getSignatureApplicabilityError(
node: CallLikeExpression, node: CallLikeExpression,
args: ReadonlyArray<Expression>, args: ReadonlyArray<Expression>,
signature: Signature, signature: Signature,
relation: Map<RelationComparisonResult>, relation: Map<RelationComparisonResult>,
checkMode: CheckMode, checkMode: CheckMode,
reportErrors: boolean, reportErrors: boolean,
containingMessageChain: (() => DiagnosticMessageChain | undefined) | undefined, containingMessageChain: (() => DiagnosticMessageChain | undefined) | undefined,
) { ): ReadonlyArray<Diagnostic> | undefined {
const errorOutputContainer: { errors?: Diagnostic[], skipLogging?: b oolean } = { errors: undefined, skipLogging: true }; const errorOutputContainer: { errors?: Diagnostic[], skipLogging?: b oolean } = { errors: undefined, skipLogging: true };
if (isJsxOpeningLikeElement(node)) { if (isJsxOpeningLikeElement(node)) {
if (!checkApplicableSignatureForJsxOpeningLikeElement(node, sign ature, relation, checkMode, reportErrors, containingMessageChain, errorOutputCon tainer)) { if (!checkApplicableSignatureForJsxOpeningLikeElement(node, sign ature, relation, checkMode, reportErrors, containingMessageChain, errorOutputCon tainer)) {
Debug.assert(!reportErrors || !!errorOutputContainer.errors, "jsx should have errors when reporting errors"); Debug.assert(!reportErrors || !!errorOutputContainer.errors, "jsx should have errors when reporting errors");
return errorOutputContainer.errors || []; return errorOutputContainer.errors || emptyArray;
} }
return undefined; return undefined;
} }
const thisType = getThisTypeOfSignature(signature); const thisType = getThisTypeOfSignature(signature);
if (thisType && thisType !== voidType && node.kind !== SyntaxKind.Ne wExpression) { if (thisType && thisType !== voidType && node.kind !== SyntaxKind.Ne wExpression) {
// If the called expression is not of the form `x.f` or `x["f"]` , then sourceType = voidType // If the called expression is not of the form `x.f` or `x["f"]` , then sourceType = voidType
// If the signature's 'this' type is voidType, then the check is skipped -- anything is compatible. // If the signature's 'this' type is voidType, then the check is skipped -- anything is compatible.
// If the expression is a new expression, then the check is skip ped. // If the expression is a new expression, then the check is skip ped.
const thisArgumentNode = getThisArgumentOfCall(node); const thisArgumentNode = getThisArgumentOfCall(node);
const thisArgumentType = thisArgumentNode ? checkExpression(this ArgumentNode) : voidType; const thisArgumentType = thisArgumentNode ? checkExpression(this ArgumentNode) : voidType;
const errorNode = reportErrors ? (thisArgumentNode || node) : un defined; const errorNode = reportErrors ? (thisArgumentNode || node) : un defined;
const headMessage = Diagnostics.The_this_context_of_type_0_is_no t_assignable_to_method_s_this_of_type_1; const headMessage = Diagnostics.The_this_context_of_type_0_is_no t_assignable_to_method_s_this_of_type_1;
if (!checkTypeRelatedTo(thisArgumentType, thisType, relation, er rorNode, headMessage, containingMessageChain, errorOutputContainer)) { if (!checkTypeRelatedTo(thisArgumentType, thisType, relation, er rorNode, headMessage, containingMessageChain, errorOutputContainer)) {
Debug.assert(!reportErrors || !!errorOutputContainer.errors, "this parameter should have errors when reporting errors"); 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; const headMessage = Diagnostics.Argument_of_type_0_is_not_assignable _to_parameter_of_type_1;
const restType = getNonArrayRestType(signature); const restType = getNonArrayRestType(signature);
const argCount = restType ? Math.min(getParameterCount(signature) - 1, args.length) : args.length; const argCount = restType ? Math.min(getParameterCount(signature) - 1, args.length) : args.length;
for (let i = 0; i < argCount; i++) { for (let i = 0; i < argCount; i++) {
const arg = args[i]; const arg = args[i];
if (arg.kind !== SyntaxKind.OmittedExpression) { if (arg.kind !== SyntaxKind.OmittedExpression) {
const paramType = getTypeAtPosition(signature, i); const paramType = getTypeAtPosition(signature, i);
const argType = checkExpressionWithContextualType(arg, param Type, /*inferenceContext*/ undefined, checkMode); const argType = checkExpressionWithContextualType(arg, param Type, /*inferenceContext*/ undefined, checkMode);
// If one or more arguments are still excluded (as indicated by CheckMode.SkipContextSensitive), // If one or more arguments are still excluded (as indicated by CheckMode.SkipContextSensitive),
// we obtain the regular type of any object literal argument s because we may not have inferred complete // we obtain the regular type of any object literal argument s because we may not have inferred complete
// parameter types yet and therefore excess property checks may yield false positives (see #17041). // parameter types yet and therefore excess property checks may yield false positives (see #17041).
const checkArgType = checkMode & CheckMode.SkipContextSensit ive ? getRegularTypeOfObjectLiteral(argType) : argType; const checkArgType = checkMode & CheckMode.SkipContextSensit ive ? getRegularTypeOfObjectLiteral(argType) : argType;
if (!checkTypeRelatedToAndOptionallyElaborate(checkArgType, paramType, relation, reportErrors ? arg : undefined, arg, headMessage, containin gMessageChain, errorOutputContainer)) { if (!checkTypeRelatedToAndOptionallyElaborate(checkArgType, paramType, relation, reportErrors ? arg : undefined, arg, headMessage, containin gMessageChain, errorOutputContainer)) {
Debug.assert(!reportErrors || !!errorOutputContainer.err ors, "parameter should have errors when reporting errors"); Debug.assert(!reportErrors || !!errorOutputContainer.err ors, "parameter should have errors when reporting errors");
maybeAddMissingAwaitInfo(arg, checkArgType, paramType); maybeAddMissingAwaitInfo(arg, checkArgType, paramType);
return errorOutputContainer.errors || []; return errorOutputContainer.errors || emptyArray;
} }
} }
} }
if (restType) { if (restType) {
const spreadType = getSpreadArgumentType(args, argCount, args.le ngth, restType, /*context*/ undefined); const spreadType = getSpreadArgumentType(args, argCount, args.le ngth, restType, /*context*/ undefined);
const errorNode = reportErrors ? argCount < args.length ? args[a rgCount] : node : undefined; const errorNode = reportErrors ? argCount < args.length ? args[a rgCount] : node : undefined;
if (!checkTypeRelatedTo(spreadType, restType, relation, errorNod e, headMessage, /*containingMessageChain*/ undefined, errorOutputContainer)) { if (!checkTypeRelatedTo(spreadType, restType, relation, errorNod e, headMessage, /*containingMessageChain*/ undefined, errorOutputContainer)) {
Debug.assert(!reportErrors || !!errorOutputContainer.errors, "rest parameter should have errors when reporting errors"); Debug.assert(!reportErrors || !!errorOutputContainer.errors, "rest parameter should have errors when reporting errors");
maybeAddMissingAwaitInfo(errorNode, spreadType, restType); maybeAddMissingAwaitInfo(errorNode, spreadType, restType);
return errorOutputContainer.errors || []; return errorOutputContainer.errors || emptyArray;
} }
} }
return undefined; return undefined;
function maybeAddMissingAwaitInfo(errorNode: Node | undefined, sourc e: Type, target: Type) { function maybeAddMissingAwaitInfo(errorNode: Node | undefined, sourc e: Type, target: Type) {
if (errorNode && reportErrors && errorOutputContainer.errors && errorOutputContainer.errors.length) { if (errorNode && reportErrors && errorOutputContainer.errors && errorOutputContainer.errors.length) {
// Bail if target is Promise-like---something else is wrong // Bail if target is Promise-like---something else is wrong
if (getAwaitedTypeOfPromise(target)) { if (getAwaitedTypeOfPromise(target)) {
return; return;
} }
skipping to change at line 21981 skipping to change at line 22017
addRelatedInfo(d, createDiagnosticForNode(la st.declaration, Diagnostics.The_last_overload_is_declared_here)); addRelatedInfo(d, createDiagnosticForNode(la st.declaration, Diagnostics.The_last_overload_is_declared_here));
} }
diagnostics.add(d); diagnostics.add(d);
} }
} }
else { else {
Debug.fail("No error for last overload signature"); Debug.fail("No error for last overload signature");
} }
} }
else { else {
const allDiagnostics: DiagnosticRelatedInformation[][] = []; const allDiagnostics: (readonly DiagnosticRelatedInforma tion[])[] = [];
let max = 0; let max = 0;
let min = Number.MAX_VALUE; let min = Number.MAX_VALUE;
let minIndex = 0; let minIndex = 0;
let i = 0; let i = 0;
for (const c of candidatesForArgumentError) { for (const c of candidatesForArgumentError) {
const chain = () => chainDiagnosticMessages(/*detail s*/ undefined, Diagnostics.Overload_0_of_1_2_gave_the_following_error, i + 1, ca ndidates.length, signatureToString(c)); const chain = () => chainDiagnosticMessages(/*detail s*/ undefined, Diagnostics.Overload_0_of_1_2_gave_the_following_error, i + 1, ca ndidates.length, signatureToString(c));
const diags = getSignatureApplicabilityError(node, a rgs, c, assignableRelation, CheckMode.Normal, /*reportErrors*/ true, chain); const diags = getSignatureApplicabilityError(node, a rgs, c, assignableRelation, CheckMode.Normal, /*reportErrors*/ true, chain);
if (diags) { if (diags) {
if (diags.length <= min) { if (diags.length <= min) {
min = diags.length; min = diags.length;
 End of changes. 23 change blocks. 
54 lines changed or deleted 100 lines changed or added

Home  |  About  |  Features  |  All  |  Newest  |  Dox  |  Diffs  |  RSS Feeds  |  Screenshots  |  Comments  |  Imprint  |  Privacy  |  HTTP(S)