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; 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::SolutionKind
ConstraintSystem::matchTypes(Type type1, Type type2, ConstraintKind kind, ConstraintSystem::matchTypes(Type type1, Type type2, ConstraintKind kind,
TypeMatchOptions flags, TypeMatchOptions flags,
@@ -2027,14 +1985,56 @@ ConstraintSystem::matchTypes(Type type1, Type type2, ConstraintKind kind,
} }
} }
// A value of type T! can be converted to type U if T is convertible // A value of type T can be converted to type U? if T is convertible to U.
// to U by force-unwrapping the source value. // A value of type T? can be converted to type U? if T is convertible to U.
// A value of type T, T?, or T! can be converted to type U? or U! if // The above conversions also apply to implicitly unwrapped optional types,
// T is convertible to U. // except that there is no implicit conversion from T? to T!.
if (concrete && kind >= ConstraintKind::Subtype) {
if (auto restriction = BoundGenericType *boundGenericType2;
selectOptionalConversionRestriction(type1, type2, kind))
conversionsOrFixes.push_back(restriction.getValue()); 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 // Allow '() -> T' to '() -> ()' and '() -> Never' to '() -> T' for closure
// literals. // literals.

View File

@@ -164,3 +164,15 @@ SR_3248().callback("test") // expected-error {{cannot convert value of type 'St
_? = nil // expected-error {{'nil' requires a contextual type}} _? = nil // expected-error {{'nil' requires a contextual type}}
_?? = nil // expected-error {{'nil' requires a contextual type}} _?? = nil // expected-error {{'nil' requires a contextual type}}
infix operator !====
func !====(_ lhs: AnyObject?, _ rhs: AnyObject?) -> Bool { return false }
func calleeRdar29977523(_ lhs: AnyObject?, _ rhs: AnyObject?) { }
func rdar29977523(lhs: AnyObject?!, rhs: AnyObject?) {
if lhs !==== rhs { }
calleeRdar29977523(lhs, rhs)
}