Revert "Fix one source of exponential behavior in the type checker."

This reverts commit 1efafbcd9b because
results in a regression in source compatibility with Swift 3.

It also adds a test demonstrating what was broken by the change.

I will take another look at fixing the exponential behavior that this
was attempting to fix.

Fixes rdar://problem/29977523.
This commit is contained in:
Mark Lacey
2017-01-15 22:02:55 -07:00
parent 7dd2489151
commit fc73e79b74
2 changed files with 62 additions and 50 deletions

View File

@@ -1193,48 +1193,6 @@ static bool isStringCompatiblePointerBaseType(TypeChecker &TC,
return false;
}
static Optional<ConversionRestrictionKind>
selectOptionalConversionRestriction(Type type1, Type type2,
ConstraintKind kind) {
OptionalTypeKind optionalKind1 = OTK_None;
if (auto boundGeneric1 = type1->getAs<BoundGenericType>())
optionalKind1 = boundGeneric1->getDecl()->classifyAsOptionalType();
OptionalTypeKind optionalKind2 = OTK_None;
if (auto boundGeneric2 = type2->getAs<BoundGenericType>())
optionalKind2 = boundGeneric2->getDecl()->classifyAsOptionalType();
if (optionalKind2 == OTK_None) {
if (optionalKind1 == OTK_ImplicitlyUnwrappedOptional &&
kind >= ConstraintKind::Conversion)
return ConversionRestrictionKind::ForceUnchecked;
return llvm::None;
}
if (optionalKind1 == optionalKind2)
return ConversionRestrictionKind::OptionalToOptional;
if (optionalKind1 == OTK_None)
return ConversionRestrictionKind::ValueToOptional;
if (optionalKind1 == OTK_Optional) {
if (kind >= ConstraintKind::Conversion)
return ConversionRestrictionKind::OptionalToImplicitlyUnwrappedOptional;
assert(optionalKind2 == OTK_ImplicitlyUnwrappedOptional &&
"Result has unexpected optional kind!");
return llvm::None;
}
assert(optionalKind1 == OTK_ImplicitlyUnwrappedOptional &&
"Source has unexpected optional kind!");
return ConversionRestrictionKind::ImplicitlyUnwrappedOptionalToOptional;
}
ConstraintSystem::SolutionKind
ConstraintSystem::matchTypes(Type type1, Type type2, ConstraintKind kind,
TypeMatchOptions flags,
@@ -2027,15 +1985,57 @@ ConstraintSystem::matchTypes(Type type1, Type type2, ConstraintKind kind,
}
}
// A value of type T! can be converted to type U if T is convertible
// to U by force-unwrapping the source value.
// A value of type T, T?, or T! can be converted to type U? or U! if
// T is convertible to U.
if (concrete && kind >= ConstraintKind::Subtype)
if (auto restriction =
selectOptionalConversionRestriction(type1, type2, kind))
conversionsOrFixes.push_back(restriction.getValue());
// A value of type T can be converted to type U? if T is convertible to U.
// A value of type T? can be converted to type U? if T is convertible to U.
// The above conversions also apply to implicitly unwrapped optional types,
// except that there is no implicit conversion from T? to T!.
{
BoundGenericType *boundGenericType2;
if (concrete && kind >= ConstraintKind::Subtype &&
(boundGenericType2 = type2->getAs<BoundGenericType>())) {
auto decl2 = boundGenericType2->getDecl();
if (auto optionalKind2 = decl2->classifyAsOptionalType()) {
assert(boundGenericType2->getGenericArgs().size() == 1);
BoundGenericType *boundGenericType1 = type1->getAs<BoundGenericType>();
if (boundGenericType1) {
auto decl1 = boundGenericType1->getDecl();
if (decl1 == decl2) {
assert(boundGenericType1->getGenericArgs().size() == 1);
conversionsOrFixes.push_back(
ConversionRestrictionKind::OptionalToOptional);
} else if (optionalKind2 == OTK_Optional &&
decl1 == TC.Context.getImplicitlyUnwrappedOptionalDecl()) {
assert(boundGenericType1->getGenericArgs().size() == 1);
conversionsOrFixes.push_back(
ConversionRestrictionKind::ImplicitlyUnwrappedOptionalToOptional);
} else if (optionalKind2 == OTK_ImplicitlyUnwrappedOptional &&
kind >= ConstraintKind::Conversion &&
decl1 == TC.Context.getOptionalDecl()) {
assert(boundGenericType1->getGenericArgs().size() == 1);
conversionsOrFixes.push_back(
ConversionRestrictionKind::OptionalToImplicitlyUnwrappedOptional);
}
}
conversionsOrFixes.push_back(
ConversionRestrictionKind::ValueToOptional);
}
}
}
// A value of type T! can be (unsafely) forced to U if T
// is convertible to U.
{
Type objectType1;
if (concrete && kind >= ConstraintKind::Conversion &&
(objectType1 = lookThroughImplicitlyUnwrappedOptionalType(type1))) {
conversionsOrFixes.push_back(
ConversionRestrictionKind::ForceUnchecked);
}
}
// Allow '() -> T' to '() -> ()' and '() -> Never' to '() -> T' for closure
// literals.
if (auto elt = locator.last()) {