mirror of
https://github.com/apple/swift.git
synced 2025-12-21 12:14:44 +01:00
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:
@@ -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.
|
||||||
|
|||||||
@@ -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)
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user