Type checker: Don't attempt metatype-to-object conversions if ObjC interop is disabled.

The post-type-checking error that was here is arguably better QoI, but it is causing ambiguities that break the non-ObjC-compatible build in the stdlib. We shouldn't even attempt these conversions if there's no runtime support to back them up.

Swift SVN r27407
This commit is contained in:
Joe Groff
2015-04-17 05:30:16 +00:00
parent 836791691e
commit dfc57e6f01
4 changed files with 53 additions and 53 deletions

View File

@@ -1670,52 +1670,56 @@ ConstraintSystem::matchTypes(Type type1, Type type2, TypeMatchKind kind,
}
// Metatype to object conversion.
//
// Class and protocol metatypes are interoperable with certain Objective-C
// runtime classes, but only when ObjC interop is enabled.
// These conversions are between concrete types that don't need further
// resolution, so we can consider them immediately solved.
auto addSolvedRestrictedConstraint
= [&](ConversionRestrictionKind restriction) -> SolutionKind {
auto constraint = Constraint::createRestricted(*this,
ConstraintKind::Subtype,
restriction,
type1, type2,
getConstraintLocator(locator));
this->addConstraint(constraint);
return SolutionKind::Solved;
};
if (auto meta1 = type1->getAs<MetatypeType>()) {
// Class metatypes can be converted to AnyObject.
if (meta1->getInstanceType()->mayHaveSuperclass()
&& type2->isAnyObject()) {
return addSolvedRestrictedConstraint(
ConversionRestrictionKind::ClassMetatypeToAnyObject);
}
// Single @objc protocol value metatypes can be converted to the ObjC
// Protocol class type.
auto isProtocolClassType = [&](Type t) -> bool {
if (auto classDecl = t->getClassOrBoundGenericClass())
if (classDecl->getName() == getASTContext().Id_Protocol
&& classDecl->getModuleContext()->Name
== getASTContext().Id_ObjectiveC)
return true;
return false;
};
if (TC.getLangOpts().EnableObjCInterop) {
// These conversions are between concrete types that don't need further
// resolution, so we can consider them immediately solved.
auto addSolvedRestrictedConstraint
= [&](ConversionRestrictionKind restriction) -> SolutionKind {
auto constraint = Constraint::createRestricted(*this,
ConstraintKind::Subtype,
restriction,
type1, type2,
getConstraintLocator(locator));
this->addConstraint(constraint);
return SolutionKind::Solved;
};
if (auto protoTy = meta1->getInstanceType()->getAs<ProtocolType>()) {
if (protoTy->getDecl()->isObjC()
&& isProtocolClassType(type2)) {
if (auto meta1 = type1->getAs<MetatypeType>()) {
if (meta1->getInstanceType()->mayHaveSuperclass()
&& type2->isAnyObject()) {
return addSolvedRestrictedConstraint(
ConversionRestrictionKind::ProtocolMetatypeToProtocolClass);
ConversionRestrictionKind::ClassMetatypeToAnyObject);
}
// Single @objc protocol value metatypes can be converted to the ObjC
// Protocol class type.
auto isProtocolClassType = [&](Type t) -> bool {
if (auto classDecl = t->getClassOrBoundGenericClass())
if (classDecl->getName() == getASTContext().Id_Protocol
&& classDecl->getModuleContext()->Name
== getASTContext().Id_ObjectiveC)
return true;
return false;
};
if (auto protoTy = meta1->getInstanceType()->getAs<ProtocolType>()) {
if (protoTy->getDecl()->isObjC()
&& isProtocolClassType(type2)) {
return addSolvedRestrictedConstraint(
ConversionRestrictionKind::ProtocolMetatypeToProtocolClass);
}
}
}
}
if (auto meta1 = type1->getAs<ExistentialMetatypeType>()) {
// Class-constrained existential metatypes can be converted to AnyObject.
if (meta1->getInstanceType()->isClassExistentialType()
&& type2->isAnyObject()) {
return addSolvedRestrictedConstraint(
ConversionRestrictionKind::ExistentialMetatypeToAnyObject);
if (auto meta1 = type1->getAs<ExistentialMetatypeType>()) {
// Class-constrained existential metatypes can be converted to AnyObject.
if (meta1->getInstanceType()->isClassExistentialType()
&& type2->isAnyObject()) {
return addSolvedRestrictedConstraint(
ConversionRestrictionKind::ExistentialMetatypeToAnyObject);
}
}
}