Source type parameter extending union works even when target is a type parameter

This commit is contained in:
Jason Freeman
2015-04-15 11:41:02 -07:00
parent 65790d1663
commit 1d8fb49f4c
19 changed files with 542 additions and 24 deletions

View File

@@ -4016,6 +4016,7 @@ module ts {
if (source === numberType && target.flags & TypeFlags.Enum) return Ternary.True;
}
}
let saveErrorInfo = errorInfo;
if (source.flags & TypeFlags.Union || target.flags & TypeFlags.Union) {
if (relation === identityRelation) {
if (source.flags & TypeFlags.Union && target.flags & TypeFlags.Union) {
@@ -4054,32 +4055,31 @@ module ts {
return result;
}
}
else {
let saveErrorInfo = errorInfo;
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 relationship holds for all type arguments
if (result = typesRelatedTo((<TypeReference>source).typeArguments, (<TypeReference>target).typeArguments, reportErrors)) {
return result;
}
}
// Even if relationship doesn't hold for type arguments, it may hold in a structural comparison
// Report structural errors only if we haven't reported any errors yet
let reportStructuralErrors = reportErrors && errorInfo === saveErrorInfo;
// identity relation does not use apparent type
let sourceOrApparentType = relation === identityRelation ? source : getApparentType(source);
if (sourceOrApparentType.flags & TypeFlags.ObjectType && target.flags & TypeFlags.ObjectType) {
if (result = objectTypeRelatedTo(sourceOrApparentType, <ObjectType>target, reportStructuralErrors)) {
errorInfo = saveErrorInfo;
return result;
}
}
else if (source.flags & TypeFlags.TypeParameter && sourceOrApparentType.flags & TypeFlags.Union) {
if (result = isRelatedTo(sourceOrApparentType, <ObjectType>target, reportStructuralErrors)) {
errorInfo = saveErrorInfo;
return result;
}
else 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 relationship holds for all type arguments
if (result = typesRelatedTo((<TypeReference>source).typeArguments, (<TypeReference>target).typeArguments, reportErrors)) {
return result;
}
}
// Even if relationship doesn't hold for type arguments, it may hold in a structural comparison
// Report structural errors only if we haven't reported any errors yet
let reportStructuralErrors = reportErrors && errorInfo === saveErrorInfo;
// identity relation does not use apparent type
let sourceOrApparentType = relation === identityRelation ? source : getApparentType(source);
if (sourceOrApparentType.flags & TypeFlags.ObjectType && target.flags & TypeFlags.ObjectType) {
if (result = objectTypeRelatedTo(sourceOrApparentType, <ObjectType>target, reportStructuralErrors)) {
errorInfo = saveErrorInfo;
return result;
}
}
else if (source.flags & TypeFlags.TypeParameter && sourceOrApparentType.flags & TypeFlags.Union) {
if (result = isRelatedTo(sourceOrApparentType, <ObjectType>target, reportStructuralErrors)) {
errorInfo = saveErrorInfo;
return result;
}
}
if (reportErrors) {
headMessage = headMessage || Diagnostics.Type_0_is_not_assignable_to_type_1;
let sourceType = typeToString(source);