diff --git a/lib/Sema/CSApply.cpp b/lib/Sema/CSApply.cpp index 06d89e54482..0b26b6445b6 100644 --- a/lib/Sema/CSApply.cpp +++ b/lib/Sema/CSApply.cpp @@ -1942,8 +1942,8 @@ namespace { if (auto baseMetaTy = baseTy->getAs()) { auto &tc = cs.getTypeChecker(); auto classTy = tc.getBridgedToObjC(cs.DC, - baseMetaTy->getInstanceType()) - .first; + baseMetaTy->getInstanceType()); + // FIXME: We're dropping side effects in the base here! base = TypeExpr::createImplicitHack(base->getLoc(), classTy, tc.Context); diff --git a/lib/Sema/CSSimplify.cpp b/lib/Sema/CSSimplify.cpp index faa202c41a5..ea72421dc3d 100644 --- a/lib/Sema/CSSimplify.cpp +++ b/lib/Sema/CSSimplify.cpp @@ -1752,7 +1752,7 @@ ConstraintSystem::matchTypes(Type type1, Type type2, TypeMatchKind kind, != TC.Context.getImplicitlyUnwrappedOptionalDecl() && type2->isBridgeableObjectType() && !(flags & TMF_ApplyingOperatorParameter) && - TC.getBridgedToObjC(DC, type1).first) { + TC.getBridgedToObjC(DC, type1)) { conversionsOrFixes.push_back(ConversionRestrictionKind::BridgeToObjC); } @@ -1764,7 +1764,7 @@ ConstraintSystem::matchTypes(Type type1, Type type2, TypeMatchKind kind, type2->getAnyNominal() != TC.Context.getImplicitlyUnwrappedOptionalDecl() && !(flags & TMF_ApplyingOperatorParameter) && - TC.getBridgedToObjC(DC, type2).first) { + TC.getBridgedToObjC(DC, type2)) { conversionsOrFixes.push_back(ConversionRestrictionKind::BridgeFromObjC); } @@ -2753,7 +2753,7 @@ ConstraintSystem::simplifyMemberConstraint(const Constraint &constraint) { Type bridgedClass; Type bridgedType; if (instanceTy->getAnyNominal() == TC.Context.getStringDecl()) { - if (Type classType = TC.getBridgedToObjC(DC, instanceTy).first) { + if (Type classType = TC.getBridgedToObjC(DC, instanceTy)) { bridgedClass = classType; bridgedType = isMetatype ? MetatypeType::get(classType) : classType; } @@ -2986,7 +2986,7 @@ ConstraintSystem::simplifyBridgedToObjectiveCConstraint( if (!baseTy) return SolutionKind::Unsolved; - if (TC.getBridgedToObjC(DC, baseTy).first) { + if (TC.getBridgedToObjC(DC, baseTy)) { increaseScore(SK_UserConversion); return SolutionKind::Solved; } @@ -3520,7 +3520,7 @@ ConstraintSystem::simplifyRestrictedConstraint(ConversionRestrictionKind restric increaseScore(SK_CollectionUpcastConversion); } else { // Check whether this is a bridging upcast. - Type bridgedType1 = TC.getBridgedToObjC(DC, baseType1).first; + Type bridgedType1 = TC.getBridgedToObjC(DC, baseType1); if (!bridgedType1) { // FIXME: Record error. return SolutionKind::Error; @@ -3583,10 +3583,10 @@ ConstraintSystem::simplifyRestrictedConstraint(ConversionRestrictionKind restric increaseScore(SK_CollectionUpcastConversion); } else { // This might be a bridged upcast. - Type bridgedKey1 = TC.getBridgedToObjC(DC, key1).first; + Type bridgedKey1 = TC.getBridgedToObjC(DC, key1); Type bridgedValue1; if (bridgedKey1) { - bridgedValue1 = TC.getBridgedToObjC(DC, value1).first; + bridgedValue1 = TC.getBridgedToObjC(DC, value1); } // Both the key and value types need to be bridged. @@ -3652,7 +3652,7 @@ ConstraintSystem::simplifyRestrictedConstraint(ConversionRestrictionKind restric // T bridges to C and C < U ===> T T getClassOrBoundGenericClass()) return Type(); + // If the value type canot be bridged, we're done. if (!valueType->isPotentiallyBridgedValueType()) return Type(); - return getBridgedToObjC(dc, valueType).first; + return getBridgedToObjC(dc, valueType); } void TypeChecker::forceExternalDeclMembers(NominalTypeDecl *nominalDecl) { @@ -2202,35 +2203,25 @@ bool TypeChecker::isTriviallyRepresentableInObjC(const DeclContext *DC, return false; } -std::pair TypeChecker::getBridgedToObjC(const DeclContext *dc, - Type type) { - // Class types and ObjC existential types are always bridged verbatim. - if (type->getClassOrBoundGenericClass() || type->isObjCExistentialType()) - return { type, true }; - - // Class archetypes are always bridged verbatim. - if (auto archetype = type->getAs()) { - if (archetype->requiresClass()) { - return { type, true }; - } - } +Type TypeChecker::getBridgedToObjC(const DeclContext *dc, Type type) { + if (type->isBridgeableObjectType()) + return type; // Retrieve the _BridgedToObjectiveC protocol. auto bridgedProto = Context.getProtocol(KnownProtocolKind::_BridgedToObjectiveC); if (!bridgedProto) - return { nullptr, false }; + return nullptr; // Check whether the type conforms to _BridgedToObjectiveC. ProtocolConformance *conformance = nullptr; if (!conformsToProtocol(type, bridgedProto, const_cast(dc), &conformance)) - return { nullptr, false }; + return nullptr; - return { getWitnessType(type, bridgedProto, conformance, - Context.getIdentifier("ObjectiveCType"), - diag::broken_bridged_to_objc_protocol), - false }; + return getWitnessType(type, bridgedProto, conformance, + Context.getIdentifier("ObjectiveCType"), + diag::broken_bridged_to_objc_protocol); } bool TypeChecker::isRepresentableInObjC(const DeclContext *DC, Type T) { @@ -2279,7 +2270,7 @@ bool TypeChecker::isRepresentableInObjC(const DeclContext *DC, Type T) { if (auto boundGeneric = T->getAs()) { if (boundGeneric->getDecl() == arrayDecl) { auto elementType = boundGeneric->getGenericArgs()[0]; - return !getBridgedToObjC(DC, elementType).first.isNull(); + return !getBridgedToObjC(DC, elementType).isNull(); } } } @@ -2290,12 +2281,12 @@ bool TypeChecker::isRepresentableInObjC(const DeclContext *DC, Type T) { if (boundGeneric->getDecl() == dictDecl) { // The key type must be bridged to Objective-C. auto keyType = boundGeneric->getGenericArgs()[0]; - if (getBridgedToObjC(DC, keyType).first.isNull()) + if (getBridgedToObjC(DC, keyType).isNull()) return false; // The value type must be bridged to Objective-C. auto valueType = boundGeneric->getGenericArgs()[1]; - if (getBridgedToObjC(DC, valueType).first.isNull()) + if (getBridgedToObjC(DC, valueType).isNull()) return false; return true; diff --git a/lib/Sema/TypeChecker.h b/lib/Sema/TypeChecker.h index 67652478c39..5e8800f0338 100644 --- a/lib/Sema/TypeChecker.h +++ b/lib/Sema/TypeChecker.h @@ -713,18 +713,16 @@ public: std::function convertToType); /// Retrieves the Objective-C type to which the given value type is - /// bridged along with a bit indicating whether it was bridged - /// verbatim. + /// bridged. /// /// \param dc The declaration context from which we will look for /// bridging. /// /// \param type The value type being queried, e.g., String. /// - /// \returns a pair containing the bridged type (or a null type if the type - /// cannot be bridged) and a bit indicating whether the type was bridged - /// verbatim. - std::pair getBridgedToObjC(const DeclContext *dc, Type type); + /// \returns the class type to which the given type is bridged, or null if it + /// is not bridged. + Type getBridgedToObjC(const DeclContext *dc, Type type); /// Find the Objective-C class that bridges between a value of the given /// dynamic type and the given value type.