AbstractionPattern AbstractionPattern::getOptional(AbstractionPattern object) { switch (object.getKind()) { case Kind::Invalid: llvm_unreachable("querying invalid abstraction pattern!"); case Kind::Tuple: case Kind::PartialCurriedObjCMethodType: case Kind::CurriedObjCMethodType: case Kind::CFunctionAsMethodType: case Kind::PartialCurriedCFunctionAsMethodType: case Kind::CurriedCFunctionAsMethodType: case Kind::ObjCMethodType: llvm_unreachable("cannot add optionality to non-type abstraction"); case Kind::Opaque: return AbstractionPattern::getOpaque(); case Kind::ClangType: return AbstractionPattern(object.getGenericSignature(), OptionalType::get(object.getType()) ->getCanonicalType(), object.getClangType()); case Kind::Type: return AbstractionPattern(object.getGenericSignature(), OptionalType::get(object.getType()) ->getCanonicalType()); case Kind::Discard: return AbstractionPattern::getDiscard(object.getGenericSignature(), OptionalType::get(object.getType()) ->getCanonicalType()); } llvm_unreachable("bad kind"); }
Type TypeConverter::getLoweredCBridgedType(AbstractionPattern pattern, Type t, bool canBridgeBool, bool bridgedCollectionsAreOptional) { auto clangTy = pattern.isClangType() ? pattern.getClangType() : nullptr; // Bridge Bool back to ObjC bool, unless the original Clang type was _Bool // or the Darwin Boolean type. auto nativeBoolTy = getBoolType(); if (nativeBoolTy && t->isEqual(nativeBoolTy)) { if (clangTy) { if (clangTy->isBooleanType()) return t; if (clangTy->isSpecificBuiltinType(clang::BuiltinType::UChar)) return getDarwinBooleanType(); } if (clangTy || canBridgeBool) return getObjCBoolType(); return t; } // Class metatypes bridge to ObjC metatypes. if (auto metaTy = t->getAs<MetatypeType>()) { if (metaTy->getInstanceType()->getClassOrBoundGenericClass()) { return MetatypeType::get(metaTy->getInstanceType(), MetatypeRepresentation::ObjC); } } // ObjC-compatible existential metatypes. if (auto metaTy = t->getAs<ExistentialMetatypeType>()) { if (metaTy->getInstanceType()->isObjCExistentialType()) { return ExistentialMetatypeType::get(metaTy->getInstanceType(), MetatypeRepresentation::ObjC); } } // `Any` can bridge to `AnyObject` (`id` in ObjC). if (t->isAny()) { return Context.getProtocol(KnownProtocolKind::AnyObject)->getDeclaredType(); } if (auto funTy = t->getAs<FunctionType>()) { switch (funTy->getExtInfo().getSILRepresentation()) { // Functions that are already represented as blocks or C function pointers // don't need bridging. case SILFunctionType::Representation::Block: case SILFunctionType::Representation::CFunctionPointer: case SILFunctionType::Representation::Thin: case SILFunctionType::Representation::Method: case SILFunctionType::Representation::ObjCMethod: case SILFunctionType::Representation::WitnessMethod: case SILFunctionType::Representation::Closure: return t; case SILFunctionType::Representation::Thick: { // Thick functions (TODO: conditionally) get bridged to blocks. // This bridging is more powerful than usual block bridging, however, // so we use the ObjCMethod representation. Type newInput = getBridgedInputType(SILFunctionType::Representation::ObjCMethod, pattern.getFunctionInputType(), funTy->getInput()->getCanonicalType()); Type newResult = getBridgedResultType(SILFunctionType::Representation::ObjCMethod, pattern.getFunctionResultType(), funTy->getResult()->getCanonicalType(), /*non-optional*/false); return FunctionType::get(newInput, newResult, funTy->getExtInfo().withSILRepresentation( SILFunctionType::Representation::Block)); } } } auto foreignRepresentation = t->getForeignRepresentableIn(ForeignLanguage::ObjectiveC, M.TheSwiftModule); switch (foreignRepresentation.first) { case ForeignRepresentableKind::None: case ForeignRepresentableKind::Trivial: case ForeignRepresentableKind::Object: return t; case ForeignRepresentableKind::Bridged: case ForeignRepresentableKind::StaticBridged: { auto conformance = foreignRepresentation.second; assert(conformance && "Missing conformance?"); Type bridgedTy = ProtocolConformance::getTypeWitnessByName( t, ProtocolConformanceRef(conformance), M.getASTContext().Id_ObjectiveCType, nullptr); assert(bridgedTy && "Missing _ObjectiveCType witness?"); if (bridgedCollectionsAreOptional && clangTy) bridgedTy = OptionalType::get(bridgedTy); return bridgedTy; } case ForeignRepresentableKind::BridgedError: { auto nsErrorDecl = M.getASTContext().getNSErrorDecl(); assert(nsErrorDecl && "Cannot bridge when NSError isn't available"); return nsErrorDecl->getDeclaredInterfaceType(); } } return t; }