Back to booleans.

I totally have an infinite amount of time to work on this.
This commit is contained in:
Daniel Rosenwasser
2016-01-14 11:33:05 -08:00
parent e8d4cf8231
commit 273cfc1cd7

View File

@@ -2,24 +2,6 @@
/* @internal */
namespace ts {
const enum ReportErrors {
/**
* Do not report errors at all.
*/
None,
/**
* Report errors in any fashion if any are encountered.
* This option implies that if an error has already been cached for a relationship
* between two types, it is okay to use the top-level error without elaboration.
*/
Basic,
/**
* Always force elaboration when comparing two types,
* even if the relation has been cached
*/
Elaborate,
}
let nextSymbolId = 1;
let nextNodeId = 1;
let nextMergeId = 1;
@@ -4937,7 +4919,7 @@ namespace ts {
function isSignatureAssignableTo(source: Signature,
target: Signature,
ignoreReturnTypes: boolean): boolean {
return compareSignaturesRelated(source, target, ignoreReturnTypes, ReportErrors.None, /*errorReporter*/ undefined, compareTypesAssignable) !== Ternary.False;
return compareSignaturesRelated(source, target, ignoreReturnTypes, /*reportErrors*/ false, /*errorReporter*/ undefined, compareTypesAssignable) !== Ternary.False;
}
/**
@@ -4946,9 +4928,9 @@ namespace ts {
function compareSignaturesRelated(source: Signature,
target: Signature,
ignoreReturnTypes: boolean,
reportErrors: ReportErrors,
reportErrors: boolean,
errorReporter: (d: DiagnosticMessage, arg0?: string, arg1?: string) => void,
compareTypes: (s: Type, t: Type, reportErrors?: ReportErrors) => Ternary): Ternary {
compareTypes: (s: Type, t: Type, reportErrors?: boolean) => Ternary): Ternary {
// TODO (drosen): De-duplicate code between related functions.
if (source === target) {
return Ternary.True;
@@ -4972,7 +4954,7 @@ namespace ts {
for (let i = 0; i < checkCount; i++) {
const s = i < sourceMax ? getTypeOfSymbol(sourceParams[i]) : getRestTypeOfSignature(source);
const t = i < targetMax ? getTypeOfSymbol(targetParams[i]) : getRestTypeOfSignature(target);
const related = compareTypes(t, s, /*reportErrors*/ ReportErrors.None) || compareTypes(s, t, reportErrors);
const related = compareTypes(t, s, /*reportErrors*/ false) || compareTypes(s, t, reportErrors);
if (!related) {
if (reportErrors) {
errorReporter(Diagnostics.Types_of_parameters_0_and_1_are_incompatible,
@@ -5078,19 +5060,11 @@ namespace ts {
Debug.assert(relation !== identityRelation || !errorNode, "no error reporting in identity checking");
const result = isRelatedTo(source, target, !!errorNode ? ReportErrors.Basic : ReportErrors.None, headMessage);
const result = isRelatedTo(source, target, /*reportErrors*/ !!errorNode, headMessage);
if (overflow) {
error(errorNode, Diagnostics.Excessive_stack_depth_comparing_types_0_and_1, typeToString(source), typeToString(target));
}
else if (errorInfo) {
// If we already computed this relation, but in a context where we didn't want to report errors (e.g. overload resolution),
// then we'll only have a top-level error (e.g. 'Class X does not implement interface Y') without any details. If this happened,
// request a recompuation to get a complete error message. This will be skipped if we've already done this computation in a context
// where errors were being reported.
if (errorInfo.next === undefined) {
errorInfo = undefined;
isRelatedTo(source, target, !!errorNode ? ReportErrors.Elaborate : ReportErrors.None, headMessage);
}
if (containingMessageChain) {
errorInfo = concatenateDiagnosticMessageChains(containingMessageChain, errorInfo);
}
@@ -5118,7 +5092,7 @@ namespace ts {
// Ternary.True if they are related with no assumptions,
// Ternary.Maybe if they are related with assumptions of other relationships, or
// Ternary.False if they are not related.
function isRelatedTo(source: Type, target: Type, reportErrors?: ReportErrors, headMessage?: DiagnosticMessage): Ternary {
function isRelatedTo(source: Type, target: Type, reportErrors?: boolean, headMessage?: DiagnosticMessage): Ternary {
let result: Ternary;
// both types are the same - covers 'they are the same primitive type or both are Any' or the same type parameter cases
if (source === target) return Ternary.True;
@@ -5206,7 +5180,7 @@ namespace ts {
// A & B = (A & B) | (C & D).
if (source.flags & TypeFlags.Intersection) {
// If target is a union type the following check will report errors so we suppress them here
if (result = someTypeRelatedToType(<IntersectionType>source, target, !(target.flags & TypeFlags.Union) ? reportErrors : ReportErrors.None)) {
if (result = someTypeRelatedToType(<IntersectionType>source, target, reportErrors && !(target.flags & TypeFlags.Union))) {
return result;
}
}
@@ -5223,7 +5197,7 @@ namespace ts {
constraint = emptyObjectType;
}
// Report constraint errors only if the constraint is not the empty object type
const reportConstraintErrors = constraint !== emptyObjectType ? reportErrors : ReportErrors.None;
const reportConstraintErrors = reportErrors && constraint !== emptyObjectType;
if (result = isRelatedTo(constraint, target, reportConstraintErrors)) {
errorInfo = saveErrorInfo;
return result;
@@ -5244,9 +5218,7 @@ namespace ts {
// relates to X. Thus, we include intersection types on the source side here.
if (apparentSource.flags & (TypeFlags.ObjectType | TypeFlags.Intersection) && target.flags & TypeFlags.ObjectType) {
// Report structural errors only if we haven't reported any errors yet
const reportStructuralErrors = reportErrors && errorInfo === saveErrorInfo && !(source.flags & TypeFlags.Primitive)
? ReportErrors.Elaborate
: ReportErrors.None;
const reportStructuralErrors = reportErrors && errorInfo === saveErrorInfo && !(source.flags & TypeFlags.Primitive);
if (result = objectTypeRelatedTo(apparentSource, source, target, reportStructuralErrors)) {
errorInfo = saveErrorInfo;
return result;
@@ -5265,11 +5237,11 @@ namespace ts {
if (source.flags & TypeFlags.ObjectType && target.flags & TypeFlags.ObjectType) {
if (source.flags & TypeFlags.Reference && target.flags & TypeFlags.Reference && (<TypeReference>source).target === (<TypeReference>target).target) {
// We have type references to same target type, see if all type arguments are identical
if (result = typeArgumentsRelatedTo(<TypeReference>source, <TypeReference>target, ReportErrors.None)) {
if (result = typeArgumentsRelatedTo(<TypeReference>source, <TypeReference>target, /*reportErrors*/ false)) {
return result;
}
}
return objectTypeRelatedTo(source, source, target, ReportErrors.None);
return objectTypeRelatedTo(source, source, target, /*reportErrors*/ false);
}
if (source.flags & TypeFlags.Union && target.flags & TypeFlags.Union ||
source.flags & TypeFlags.Intersection && target.flags & TypeFlags.Intersection) {
@@ -5304,7 +5276,7 @@ namespace ts {
return false;
}
function hasExcessProperties(source: FreshObjectLiteralType, target: Type, reportErrors: ReportErrors): boolean {
function hasExcessProperties(source: FreshObjectLiteralType, target: Type, reportErrors: boolean): boolean {
if (!(target.flags & TypeFlags.ObjectLiteralPatternWithComputedProperties) && someConstituentTypeHasKind(target, TypeFlags.ObjectType)) {
for (const prop of getPropertiesOfObjectType(source)) {
if (!isKnownProperty(target, prop.name)) {
@@ -5328,7 +5300,7 @@ namespace ts {
let result = Ternary.True;
const sourceTypes = source.types;
for (const sourceType of sourceTypes) {
const related = typeRelatedToSomeType(sourceType, target, ReportErrors.None);
const related = typeRelatedToSomeType(sourceType, target, /*reportErrors*/ false);
if (!related) {
return Ternary.False;
}
@@ -5337,10 +5309,10 @@ namespace ts {
return result;
}
function typeRelatedToSomeType(source: Type, target: UnionOrIntersectionType, reportErrors: ReportErrors): Ternary {
function typeRelatedToSomeType(source: Type, target: UnionOrIntersectionType, reportErrors: boolean): Ternary {
const targetTypes = target.types;
for (let i = 0, len = targetTypes.length; i < len; i++) {
const related = isRelatedTo(source, targetTypes[i], i === len - 1 ? reportErrors : ReportErrors.None);
const related = isRelatedTo(source, targetTypes[i], reportErrors && i === len - 1);
if (related) {
return related;
}
@@ -5348,7 +5320,7 @@ namespace ts {
return Ternary.False;
}
function typeRelatedToEachType(source: Type, target: UnionOrIntersectionType, reportErrors: ReportErrors): Ternary {
function typeRelatedToEachType(source: Type, target: UnionOrIntersectionType, reportErrors: boolean): Ternary {
let result = Ternary.True;
const targetTypes = target.types;
for (const targetType of targetTypes) {
@@ -5361,10 +5333,10 @@ namespace ts {
return result;
}
function someTypeRelatedToType(source: UnionOrIntersectionType, target: Type, reportErrors: ReportErrors): Ternary {
function someTypeRelatedToType(source: UnionOrIntersectionType, target: Type, reportErrors: boolean): Ternary {
const sourceTypes = source.types;
for (let i = 0, len = sourceTypes.length; i < len; i++) {
const related = isRelatedTo(sourceTypes[i], target, i === len - 1 ? reportErrors : ReportErrors.None);
const related = isRelatedTo(sourceTypes[i], target, reportErrors && i === len - 1);
if (related) {
return related;
}
@@ -5372,7 +5344,7 @@ namespace ts {
return Ternary.False;
}
function eachTypeRelatedToType(source: UnionOrIntersectionType, target: Type, reportErrors: ReportErrors): Ternary {
function eachTypeRelatedToType(source: UnionOrIntersectionType, target: Type, reportErrors: boolean): Ternary {
let result = Ternary.True;
const sourceTypes = source.types;
for (const sourceType of sourceTypes) {
@@ -5385,7 +5357,7 @@ namespace ts {
return result;
}
function typeArgumentsRelatedTo(source: TypeReference, target: TypeReference, reportErrors: ReportErrors): Ternary {
function typeArgumentsRelatedTo(source: TypeReference, target: TypeReference, reportErrors: boolean): Ternary {
const sources = source.typeArguments || emptyArray;
const targets = target.typeArguments || emptyArray;
if (sources.length !== targets.length && relation === identityRelation) {
@@ -5408,14 +5380,14 @@ namespace ts {
// Third, check if both types are part of deeply nested chains of generic type instantiations and if so assume the types are
// equal and infinitely expanding. Fourth, if we have reached a depth of 100 nested comparisons, assume we have runaway recursion
// and issue an error. Otherwise, actually compare the structure of the two types.
function objectTypeRelatedTo(source: Type, originalSource: Type, target: Type, reportErrors: ReportErrors): Ternary {
function objectTypeRelatedTo(source: Type, originalSource: Type, target: Type, reportErrors: boolean): Ternary {
if (overflow) {
return Ternary.False;
}
const id = relation !== identityRelation || source.id < target.id ? source.id + "," + target.id : target.id + "," + source.id;
const related = relation[id];
if (related !== undefined) {
if (reportErrors === ReportErrors.Elaborate && related === RelationComparisonResult.Failed) {
if (reportErrors && related === RelationComparisonResult.Failed) {
// We are elaborating errors and the cached result is an unreported failure. Record the result as a reported
// failure and continue computing the relation such that errors get reported.
relation[id] = RelationComparisonResult.FailedAndReported;
@@ -5485,7 +5457,7 @@ namespace ts {
return result;
}
function propertiesRelatedTo(source: Type, target: Type, reportErrors: ReportErrors): Ternary {
function propertiesRelatedTo(source: Type, target: Type, reportErrors: boolean): Ternary {
if (relation === identityRelation) {
return propertiesIdenticalTo(source, target);
}
@@ -5593,7 +5565,7 @@ namespace ts {
return result;
}
function signaturesRelatedTo(source: Type, target: Type, kind: SignatureKind, reportErrors: ReportErrors): Ternary {
function signaturesRelatedTo(source: Type, target: Type, kind: SignatureKind, reportErrors: boolean): Ternary {
if (relation === identityRelation) {
return signaturesIdenticalTo(source, target, kind);
}
@@ -5630,7 +5602,7 @@ namespace ts {
errorInfo = saveErrorInfo;
continue outer;
}
shouldElaborateErrors = ReportErrors.None;
shouldElaborateErrors = false;
}
}
// don't elaborate the primitive apparent types (like Number)
@@ -5649,7 +5621,7 @@ namespace ts {
/**
* See signatureAssignableTo, compareSignaturesIdentical
*/
function signatureRelatedTo(source: Signature, target: Signature, reportErrors: ReportErrors): Ternary {
function signatureRelatedTo(source: Signature, target: Signature, reportErrors: boolean): Ternary {
return compareSignaturesRelated(source, target, /*ignoreReturnTypes*/ false, reportErrors, reportError, isRelatedTo);
}
@@ -5670,7 +5642,7 @@ namespace ts {
return result;
}
function stringIndexTypesRelatedTo(source: Type, originalSource: Type, target: Type, reportErrors: ReportErrors): Ternary {
function stringIndexTypesRelatedTo(source: Type, originalSource: Type, target: Type, reportErrors: boolean): Ternary {
if (relation === identityRelation) {
return indexTypesIdenticalTo(IndexKind.String, source, target);
}
@@ -5700,7 +5672,7 @@ namespace ts {
return Ternary.True;
}
function numberIndexTypesRelatedTo(source: Type, originalSource: Type, target: Type, reportErrors: ReportErrors): Ternary {
function numberIndexTypesRelatedTo(source: Type, originalSource: Type, target: Type, reportErrors: boolean): Ternary {
if (relation === identityRelation) {
return indexTypesIdenticalTo(IndexKind.Number, source, target);
}
@@ -5722,7 +5694,7 @@ namespace ts {
let related: Ternary;
if (sourceStringType && sourceNumberType) {
// If we know for sure we're testing both string and numeric index types then only report errors from the second one
related = isRelatedTo(sourceStringType, targetType, ReportErrors.None) || isRelatedTo(sourceNumberType, targetType, reportErrors);
related = isRelatedTo(sourceStringType, targetType, /*reportErrors*/ false) || isRelatedTo(sourceNumberType, targetType, reportErrors);
}
else {
related = isRelatedTo(sourceStringType || sourceNumberType, targetType, reportErrors);
@@ -9003,7 +8975,7 @@ namespace ts {
getInferredTypes(context);
}
function checkTypeArguments(signature: Signature, typeArgumentNodes: TypeNode[], typeArgumentTypes: Type[], reportErrors: ReportErrors, headMessage?: DiagnosticMessage): boolean {
function checkTypeArguments(signature: Signature, typeArgumentNodes: TypeNode[], typeArgumentTypes: Type[], reportErrors: boolean, headMessage?: DiagnosticMessage): boolean {
const typeParameters = signature.typeParameters;
let typeArgumentsAreAssignable = true;
let mapper: TypeMapper;
@@ -9033,7 +9005,7 @@ namespace ts {
return typeArgumentsAreAssignable;
}
function checkApplicableSignature(node: CallLikeExpression, args: Expression[], signature: Signature, relation: Map<RelationComparisonResult>, excludeArgument: boolean[], reportErrors: ReportErrors) {
function checkApplicableSignature(node: CallLikeExpression, args: Expression[], signature: Signature, relation: Map<RelationComparisonResult>, excludeArgument: boolean[], reportErrors: boolean) {
const argCount = getEffectiveArgumentCount(node, args, signature);
for (let i = 0; i < argCount; i++) {
const arg = getEffectiveArgument(node, args, i);
@@ -9481,12 +9453,12 @@ namespace ts {
// in arguments too early. If possible, we'd like to only type them once we know the correct
// overload. However, this matters for the case where the call is correct. When the call is
// an error, we don't need to exclude any arguments, although it would cause no harm to do so.
checkApplicableSignature(node, args, candidateForArgumentError, assignableRelation, /*excludeArgument*/ undefined, ReportErrors.Basic);
checkApplicableSignature(node, args, candidateForArgumentError, assignableRelation, /*excludeArgument*/ undefined, /*reportErrors*/ true);
}
else if (candidateForTypeArgumentError) {
if (!isTaggedTemplate && !isDecorator && typeArguments) {
const typeArguments = (<CallExpression>node).typeArguments;
checkTypeArguments(candidateForTypeArgumentError, typeArguments, map(typeArguments, getTypeFromTypeNode), ReportErrors.Basic, headMessage);
checkTypeArguments(candidateForTypeArgumentError, typeArguments, map(typeArguments, getTypeFromTypeNode), /*reportErrors*/ true, headMessage);
}
else {
Debug.assert(resultOfFailedInference.failedTypeParameterIndex >= 0);
@@ -9554,7 +9526,7 @@ namespace ts {
let typeArgumentTypes: Type[];
if (typeArguments) {
typeArgumentTypes = map(typeArguments, getTypeFromTypeNode);
typeArgumentsAreValid = checkTypeArguments(candidate, typeArguments, typeArgumentTypes, ReportErrors.None);
typeArgumentsAreValid = checkTypeArguments(candidate, typeArguments, typeArgumentTypes, /*reportErrors*/ false);
}
else {
inferTypeArguments(node, candidate, args, excludeArgument, inferenceContext);
@@ -9566,7 +9538,7 @@ namespace ts {
}
candidate = getSignatureInstantiation(candidate, typeArgumentTypes);
}
if (!checkApplicableSignature(node, args, candidate, relation, excludeArgument, ReportErrors.None)) {
if (!checkApplicableSignature(node, args, candidate, relation, excludeArgument, /*reportErrors*/ false)) {
break;
}
const index = excludeArgument ? indexOf(excludeArgument, true) : -1;