diff --git a/include/swift/AST/ASTContext.h b/include/swift/AST/ASTContext.h index e19a10ba786c4..2ae67ba07d6d2 100644 --- a/include/swift/AST/ASTContext.h +++ b/include/swift/AST/ASTContext.h @@ -447,17 +447,13 @@ class ASTContext final { /// Retrieve the type Swift.Never. CanType getNeverType() const; - /// Retrieve the declaration of ObjectiveC.ObjCBool. - StructDecl *getObjCBoolDecl() const; - - /// Retrieve the declaration of Foundation.NSCopying. - ProtocolDecl *getNSCopyingDecl() const; - /// Retrieve the declaration of Foundation.NSError. - ClassDecl *getNSErrorDecl() const; - /// Retrieve the declaration of Foundation.NSNumber. - ClassDecl *getNSNumberDecl() const; - /// Retrieve the declaration of Foundation.NSValue. - ClassDecl *getNSValueDecl() const; +#define KNOWN_OBJC_TYPE_DECL(MODULE, NAME, DECL_CLASS) \ + /** Retrieve the declaration of MODULE.NAME. */ \ + DECL_CLASS *get##NAME##Decl() const; \ +\ + /** Retrieve the type of MODULE.NAME. */ \ + Type get##NAME##Type() const; +#include "swift/AST/KnownObjCTypes.def" // Declare accessors for the known declarations. #define FUNC_DECL(Name, Id) \ diff --git a/include/swift/AST/KnownObjCTypes.def b/include/swift/AST/KnownObjCTypes.def new file mode 100644 index 0000000000000..b77eb4f893554 --- /dev/null +++ b/include/swift/AST/KnownObjCTypes.def @@ -0,0 +1,37 @@ +//===--- KnownObjCTypes.def - Common Objective-C types --------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2019 Apple Inc. and the Swift project authors +// Licensed under Apache License v2.0 with Runtime Library Exception +// +// See https://swift.org/LICENSE.txt for license information +// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors +// +//===----------------------------------------------------------------------===// +// +// This xmacro generates code for common imported Objective-C types the +// compiler has special knowledge of. +// +//===----------------------------------------------------------------------===// + +#ifndef KNOWN_OBJC_TYPE_DECL +/// KNOWN_OBJC_TYPE_DECL(MODULE, NAME, DECL_CLASS) +/// +/// The macro is expanded for each known imported Objective-C type. MODULE is +/// bound to the name of the module the type comes from. NAME is bound to the +/// unqualified name of the type. DECL_CLASS is bound to the Decl subclass it +/// is expected to be an instance of. +#define KNOWN_OBJC_TYPE_DECL(MODULE, NAME, DECL_CLASS) +#endif + +KNOWN_OBJC_TYPE_DECL(Foundation, NSCopying, ProtocolDecl) +KNOWN_OBJC_TYPE_DECL(Foundation, NSError, ClassDecl) +KNOWN_OBJC_TYPE_DECL(Foundation, NSNumber, ClassDecl) +KNOWN_OBJC_TYPE_DECL(Foundation, NSValue, ClassDecl) + +KNOWN_OBJC_TYPE_DECL(ObjectiveC, NSObject, ClassDecl) +KNOWN_OBJC_TYPE_DECL(ObjectiveC, Selector, StructDecl) +KNOWN_OBJC_TYPE_DECL(ObjectiveC, ObjCBool, StructDecl) + +#undef KNOWN_OBJC_TYPE_DECL diff --git a/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp index d4d79cac06579..a7a6e8f414b58 100644 --- a/lib/AST/ASTContext.cpp +++ b/lib/AST/ASTContext.cpp @@ -98,12 +98,6 @@ using AssociativityCacheType = llvm::DenseMap, Associativity>; -#define FOR_KNOWN_FOUNDATION_TYPES(MACRO) \ - MACRO(NSCopying, ProtocolDecl) \ - MACRO(NSError, ClassDecl) \ - MACRO(NSNumber, ClassDecl) \ - MACRO(NSValue, ClassDecl) - struct OverrideSignatureKey { GenericSignature baseMethodSig; GenericSignature derivedClassSig; @@ -190,6 +184,11 @@ struct ASTContext::Implementation { DECL_CLASS *NAME##Decl = nullptr; #include "swift/AST/KnownStdlibTypes.def" +#define KNOWN_OBJC_TYPE_DECL(MODULE, NAME, DECL_CLASS) \ + /** The declaration of MODULE.NAME. */ \ + DECL_CLASS *NAME##Decl = nullptr; +#include "swift/AST/KnownObjCTypes.def" + /// The declaration of '+' function for two RangeReplaceableCollection. FuncDecl *PlusFunctionOnRangeReplaceableCollection = nullptr; @@ -216,15 +215,6 @@ struct ASTContext::Implementation { /// The declaration of Swift.AutoreleasingUnsafeMutablePointer.memory. VarDecl *AutoreleasingUnsafeMutablePointerMemoryDecl = nullptr; - - /// The declaration of ObjectiveC.ObjCBool. - StructDecl *ObjCBoolDecl = nullptr; - -#define CACHE_FOUNDATION_DECL(NAME, DECLTYPE) \ - /** The declaration of Foundation.NAME. */ \ - DECLTYPE *NAME##Decl = nullptr; -FOR_KNOWN_FOUNDATION_TYPES(CACHE_FOUNDATION_DECL) -#undef CACHE_FOUNDATION_DECL // Declare cached declarations for each of the known declarations. #define FUNC_DECL(Name, Id) FuncDecl *Get##Name = nullptr; @@ -827,33 +817,12 @@ CanType ASTContext::getNeverType() const { return neverDecl->getDeclaredType()->getCanonicalType(); } -StructDecl *ASTContext::getObjCBoolDecl() const { - if (!getImpl().ObjCBoolDecl) { - SmallVector results; - auto *Context = const_cast(this); - if (ModuleDecl *M = Context->getModuleByName(Id_ObjectiveC.str())) { - M->lookupValue(getIdentifier("ObjCBool"), NLKind::UnqualifiedLookup, - results); - for (auto result : results) { - if (auto structDecl = dyn_cast(result)) { - if (structDecl->getGenericParams() == nullptr) { - getImpl().ObjCBoolDecl = structDecl; - break; - } - } - } - } - } - - return getImpl().ObjCBoolDecl; -} - -#define GET_FOUNDATION_DECL(NAME, DECLTYPE) \ +#define KNOWN_OBJC_TYPE_DECL(MODULE, NAME, DECLTYPE) \ DECLTYPE *ASTContext::get##NAME##Decl() const { \ if (!getImpl().NAME##Decl) { \ - if (ModuleDecl *M = getLoadedModule(Id_Foundation)) { \ - /* Note: lookupQualified() will search both the Foundation module \ - * and the Clang Foundation module it imports. */ \ + if (ModuleDecl *M = getLoadedModule(Id_##MODULE)) { \ + /* Note: lookupQualified() will search both the Swift overlay \ + * and the Clang module it imports. */ \ SmallVector decls; \ M->lookupQualified(M, getIdentifier(#NAME), NL_OnlyTypes, decls); \ if (decls.size() == 1 && isa(decls[0])) { \ @@ -866,11 +835,16 @@ DECLTYPE *ASTContext::get##NAME##Decl() const { \ } \ \ return getImpl().NAME##Decl; \ +} \ +\ +Type ASTContext::get##NAME##Type() const { \ + auto *decl = get##NAME##Decl(); \ + if (!decl) \ + return Type(); \ + return decl->getDeclaredInterfaceType(); \ } -FOR_KNOWN_FOUNDATION_TYPES(GET_FOUNDATION_DECL) -#undef GET_FOUNDATION_DECL -#undef FOR_KNOWN_FOUNDATION_TYPES +#include "swift/AST/KnownObjCTypes.def" ProtocolDecl *ASTContext::getProtocol(KnownProtocolKind kind) const { // Check whether we've already looked for and cached this protocol. @@ -4291,12 +4265,12 @@ Type ASTContext::getBridgedToObjC(const DeclContext *dc, Type type, // Check whether the type is an existential that contains // Error. If so, it's bridged to NSError. if (type->isExistentialWithError()) { - if (auto nsErrorDecl = getNSErrorDecl()) { + if (auto nsErrorTy = getNSErrorType()) { // The corresponding value type is Error. if (bridgedValueType) *bridgedValueType = getErrorDecl()->getDeclaredInterfaceType(); - return nsErrorDecl->getDeclaredInterfaceType(); + return nsErrorTy; } } @@ -4334,8 +4308,8 @@ Type ASTContext::getBridgedToObjC(const DeclContext *dc, Type type, *bridgedValueType = getErrorDecl()->getDeclaredInterfaceType(); // Bridge to NSError. - if (auto nsErrorDecl = getNSErrorDecl()) - return nsErrorDecl->getDeclaredInterfaceType(); + if (auto nsErrorTy = getNSErrorType()) + return nsErrorTy; } // No special bridging to Objective-C, but this can become an 'Any'. diff --git a/lib/ClangImporter/ImportType.cpp b/lib/ClangImporter/ImportType.cpp index 2930badfecb4e..0519170ab8ea2 100644 --- a/lib/ClangImporter/ImportType.cpp +++ b/lib/ClangImporter/ImportType.cpp @@ -2082,7 +2082,7 @@ ImportedType ClangImporter::Implementation::importMethodParamsAndReturnType( bool paramIsIUO; if (kind == SpecialMethodKind::NSDictionarySubscriptGetter && paramTy->isObjCIdType()) { - swiftParamTy = SwiftContext.getNSCopyingDecl()->getDeclaredType(); + swiftParamTy = SwiftContext.getNSCopyingType(); if (optionalityOfParam != OTK_None) swiftParamTy = OptionalType::get(swiftParamTy); diff --git a/lib/PrintAsObjC/DeclAndTypePrinter.cpp b/lib/PrintAsObjC/DeclAndTypePrinter.cpp index aef39d7944bb1..240e83d8a2ff8 100644 --- a/lib/PrintAsObjC/DeclAndTypePrinter.cpp +++ b/lib/PrintAsObjC/DeclAndTypePrinter.cpp @@ -1396,8 +1396,8 @@ class DeclAndTypePrinter::Implementation // upper-bounded keys. else if (swiftNominal == ctx.getDictionaryDecl() && isNSObjectOrAnyHashable(ctx, typeArgs[0])) { - if (auto proto = ctx.getNSCopyingDecl()) { - rewrittenArgsBuf[0] = proto->getDeclaredInterfaceType(); + if (auto protoTy = ctx.getNSCopyingType()) { + rewrittenArgsBuf[0] = protoTy; rewrittenArgsBuf[1] = typeArgs[1]; typeArgs = rewrittenArgsBuf; } diff --git a/lib/SIL/Bridging.cpp b/lib/SIL/Bridging.cpp index c00aff9cd1e23..ab2fc6bab7aef 100644 --- a/lib/SIL/Bridging.cpp +++ b/lib/SIL/Bridging.cpp @@ -232,9 +232,9 @@ Type TypeConverter::getLoweredCBridgedType(AbstractionPattern pattern, } case ForeignRepresentableKind::BridgedError: { - auto nsErrorDecl = M.getASTContext().getNSErrorDecl(); - assert(nsErrorDecl && "Cannot bridge when NSError isn't available"); - return nsErrorDecl->getDeclaredInterfaceType(); + auto nsErrorTy = M.getASTContext().getNSErrorType(); + assert(nsErrorTy && "Cannot bridge when NSError isn't available"); + return nsErrorTy; } } diff --git a/lib/SIL/SILType.cpp b/lib/SIL/SILType.cpp index bec7fa267819b..3b89dbc7852e9 100644 --- a/lib/SIL/SILType.cpp +++ b/lib/SIL/SILType.cpp @@ -304,12 +304,10 @@ static bool isBridgedErrorClass(ASTContext &ctx, Type t) { t = archetypeType->getSuperclass(); // NSError (TODO: and CFError) can be bridged. - auto nsErrorType = ctx.getNSErrorDecl(); - if (t && nsErrorType && - nsErrorType->getDeclaredType()->isExactSuperclassOf(t)) { + auto nsErrorType = ctx.getNSErrorType(); + if (t && nsErrorType && nsErrorType->isExactSuperclassOf(t)) return true; - } - + return false; } diff --git a/lib/SILGen/SILGen.cpp b/lib/SILGen/SILGen.cpp index fb8031d865bad..b1e5e9c22937f 100644 --- a/lib/SILGen/SILGen.cpp +++ b/lib/SILGen/SILGen.cpp @@ -336,8 +336,8 @@ ProtocolConformance *SILGenModule::getNSErrorConformanceToError() { return *NSErrorConformanceToError; auto &ctx = getASTContext(); - auto nsError = ctx.getNSErrorDecl(); - if (!nsError) { + auto nsErrorTy = ctx.getNSErrorType(); + if (!nsErrorTy) { NSErrorConformanceToError = nullptr; return nullptr; } @@ -349,8 +349,7 @@ ProtocolConformance *SILGenModule::getNSErrorConformanceToError() { } auto conformance = - SwiftModule->lookupConformance(nsError->getDeclaredInterfaceType(), - cast(error)); + SwiftModule->lookupConformance(nsErrorTy, cast(error)); if (conformance.isConcrete()) NSErrorConformanceToError = conformance.getConcrete(); diff --git a/lib/SILGen/SILGenConvert.cpp b/lib/SILGen/SILGenConvert.cpp index be0133d231e46..0602dd7117830 100644 --- a/lib/SILGen/SILGenConvert.cpp +++ b/lib/SILGen/SILGenConvert.cpp @@ -625,11 +625,9 @@ ManagedValue SILGenFunction::emitExistentialErasure( if (ctx.LangOpts.EnableObjCInterop && conformances.size() == 1 && conformances[0].getRequirement() == ctx.getErrorDecl() && ctx.getNSErrorDecl()) { - auto nsErrorDecl = ctx.getNSErrorDecl(); - // If the concrete type is NSError or a subclass thereof, just erase it // directly. - auto nsErrorType = nsErrorDecl->getDeclaredType()->getCanonicalType(); + auto nsErrorType = ctx.getNSErrorType()->getCanonicalType(); if (nsErrorType->isExactSuperclassOf(concreteFormalType)) { ManagedValue nsError = F(SGFContext()); if (nsErrorType != concreteFormalType) { diff --git a/lib/Sema/CSApply.cpp b/lib/Sema/CSApply.cpp index bfaa56dc86365..f74948077b6fc 100644 --- a/lib/Sema/CSApply.cpp +++ b/lib/Sema/CSApply.cpp @@ -1670,9 +1670,8 @@ namespace { Expr *bridgeErrorToObjectiveC(Expr *value) { auto &ctx = cs.getASTContext(); - auto nsErrorDecl = ctx.getNSErrorDecl(); - assert(nsErrorDecl && "Missing NSError?"); - Type nsErrorType = nsErrorDecl->getDeclaredInterfaceType(); + auto nsErrorType = ctx.getNSErrorType(); + assert(nsErrorType && "Missing NSError?"); auto result = new (ctx) BridgeToObjCExpr(value, nsErrorType); return cs.cacheType(result); diff --git a/lib/Sema/CSGen.cpp b/lib/Sema/CSGen.cpp index c00d25238a275..56cb0c0edaa6c 100644 --- a/lib/Sema/CSGen.cpp +++ b/lib/Sema/CSGen.cpp @@ -2981,7 +2981,7 @@ namespace { // Make sure we can reference ObjectiveC.Selector. // FIXME: Fix-It to add the import? - auto type = CS.getTypeChecker().getObjCSelectorType(CS.DC); + auto type = CS.getASTContext().getSelectorType(); if (!type) { ctx.Diags.diagnose(E->getLoc(), diag::expr_selector_module_missing); return nullptr; diff --git a/lib/Sema/CSSimplify.cpp b/lib/Sema/CSSimplify.cpp index 17cc7c34304d5..9eea6223f129e 100644 --- a/lib/Sema/CSSimplify.cpp +++ b/lib/Sema/CSSimplify.cpp @@ -6420,6 +6420,7 @@ ConstraintSystem::simplifyBridgingConstraint(Type type1, // If the bridged value type is generic, the generic arguments // must either match or be bridged. // FIXME: This should be an associated type of the protocol. + auto &ctx = getASTContext(); if (auto fromBGT = unwrappedToType->getAs()) { if (fromBGT->getDecl() == TC.Context.getArrayDecl()) { // [AnyObject] @@ -6429,14 +6430,14 @@ ConstraintSystem::simplifyBridgingConstraint(Type type1, LocatorPathElt::GenericArgument(0)))); } else if (fromBGT->getDecl() == TC.Context.getDictionaryDecl()) { // [NSObject : AnyObject] - auto NSObjectType = TC.getNSObjectType(DC); - if (!NSObjectType) { + auto nsObjectType = ctx.getNSObjectType(); + if (!nsObjectType) { // Not a bridging case. Should we detect this earlier? return SolutionKind::Error; } addConstraint(ConstraintKind::Bind, fromBGT->getGenericArgs()[0], - NSObjectType, + nsObjectType, getConstraintLocator( locator.withPathElement( LocatorPathElt::GenericArgument(0)))); @@ -6447,13 +6448,13 @@ ConstraintSystem::simplifyBridgingConstraint(Type type1, locator.withPathElement( LocatorPathElt::GenericArgument(1)))); } else if (fromBGT->getDecl() == TC.Context.getSetDecl()) { - auto NSObjectType = TC.getNSObjectType(DC); - if (!NSObjectType) { + auto nsObjectType = ctx.getNSObjectType(); + if (!nsObjectType) { // Not a bridging case. Should we detect this earlier? return SolutionKind::Error; } addConstraint(ConstraintKind::Bind, fromBGT->getGenericArgs()[0], - NSObjectType, + nsObjectType, getConstraintLocator( locator.withPathElement( LocatorPathElt::GenericArgument(0)))); diff --git a/lib/Sema/MiscDiagnostics.cpp b/lib/Sema/MiscDiagnostics.cpp index 691ea8540715c..b40e66cf1d33c 100644 --- a/lib/Sema/MiscDiagnostics.cpp +++ b/lib/Sema/MiscDiagnostics.cpp @@ -3474,7 +3474,7 @@ class ObjCSelectorWalker : public ASTWalker { static void diagDeprecatedObjCSelectors(TypeChecker &tc, const DeclContext *dc, const Expr *expr) { - auto selectorTy = tc.getObjCSelectorType(const_cast(dc)); + auto selectorTy = dc->getASTContext().getSelectorType(); if (!selectorTy) return; const_cast(expr)->walk(ObjCSelectorWalker(tc, dc, selectorTy)); @@ -4097,9 +4097,7 @@ static OmissionTypeName getTypeNameForOmission(Type type) { Type boolType; if (auto boolDecl = ctx.getBoolDecl()) boolType = boolDecl->getDeclaredInterfaceType(); - Type objcBoolType; - if (auto objcBoolDecl = ctx.getObjCBoolDecl()) - objcBoolType = objcBoolDecl->getDeclaredInterfaceType(); + auto objcBoolType = ctx.getObjCBoolType(); /// Determine the options associated with the given type. auto getOptions = [&](Type type) { diff --git a/lib/Sema/TypeCheckConstraints.cpp b/lib/Sema/TypeCheckConstraints.cpp index 3ee5ca9941795..fcfd1c66ac9be 100644 --- a/lib/Sema/TypeCheckConstraints.cpp +++ b/lib/Sema/TypeCheckConstraints.cpp @@ -1994,7 +1994,7 @@ Expr *PreCheckExpression::simplifyTypeConstructionWithLiteralArg(Expr *E) { return nullptr; // Don't bother to convert deprecated selector syntax. - if (auto selectorTy = TC.getObjCSelectorType(DC)) { + if (auto selectorTy = TC.Context.getSelectorType()) { if (type->isEqual(selectorTy)) return nullptr; } @@ -4407,7 +4407,7 @@ CheckedCastKind TypeChecker::typeCheckCheckedCast(Type fromType, // Objective-C metaclasses are subclasses of NSObject in the ObjC runtime, // so casts from NSObject to potentially-class metatypes may succeed. - if (auto nsObject = getNSObjectType(dc)) { + if (auto nsObject = Context.getNSObjectType()) { if (fromType->isEqual(nsObject)) { if (auto toMeta = toType->getAs()) { if (toMeta->getInstanceType()->mayHaveSuperclass() @@ -4427,10 +4427,9 @@ CheckedCastKind TypeChecker::typeCheckCheckedCast(Type fromType, if (!conformsToProtocol(toType, errorTypeProto, dc, ConformanceCheckFlags::InExpression) .isInvalid()) { - auto nsError = Context.getNSErrorDecl(); - if (nsError) { - Type NSErrorTy = nsError->getDeclaredInterfaceType(); - if (isSubtypeOf(fromType, NSErrorTy, dc) + auto nsErrorTy = Context.getNSErrorType(); + if (nsErrorTy) { + if (isSubtypeOf(fromType, nsErrorTy, dc) // Don't mask "always true" warnings if NSError is cast to // Error itself. && !isSubtypeOf(fromType, toType, dc)) diff --git a/lib/Sema/TypeCheckDeclObjC.cpp b/lib/Sema/TypeCheckDeclObjC.cpp index 0a5af66ebfe60..8d769cd58e648 100644 --- a/lib/Sema/TypeCheckDeclObjC.cpp +++ b/lib/Sema/TypeCheckDeclObjC.cpp @@ -680,11 +680,10 @@ bool swift::isRepresentableInObjC( } // The error type is always 'AutoreleasingUnsafeMutablePointer?'. - auto nsError = ctx.getNSErrorDecl(); + auto nsErrorTy = ctx.getNSErrorType(); Type errorParameterType; - if (nsError) { - errorParameterType = nsError->getDeclaredInterfaceType(); - errorParameterType = OptionalType::get(errorParameterType); + if (nsErrorTy) { + errorParameterType = OptionalType::get(nsErrorTy); errorParameterType = BoundGenericType::get( ctx.getAutoreleasingUnsafeMutablePointerDecl(), @@ -939,48 +938,6 @@ bool swift::canBeRepresentedInObjC(const ValueDecl *decl) { return false; } -static Type getObjectiveCNominalType(Type &cache, - Identifier ModuleName, - Identifier TypeName, - DeclContext *dc) { - if (cache) - return cache; - - // FIXME: Does not respect visibility of the module. - ASTContext &ctx = dc->getASTContext(); - ModuleDecl *module = ctx.getLoadedModule(ModuleName); - if (!module) - return nullptr; - - SmallVector decls; - NLOptions options = NL_QualifiedDefault | NL_OnlyTypes; - dc->lookupQualified(module, TypeName, options, decls); - for (auto decl : decls) { - if (auto nominal = dyn_cast(decl)) { - cache = nominal->getDeclaredType(); - return cache; - } - } - - return nullptr; -} - -#pragma mark Objective-C-specific types - -Type TypeChecker::getNSObjectType(DeclContext *dc) { - return getObjectiveCNominalType(NSObjectType, Context.Id_ObjectiveC, - Context.getSwiftId( - KnownFoundationEntity::NSObject), - dc); -} - -Type TypeChecker::getObjCSelectorType(DeclContext *dc) { - return getObjectiveCNominalType(ObjCSelectorType, - Context.Id_ObjectiveC, - Context.Id_Selector, - dc); -} - #pragma mark "@objc declaration handling" /// Whether this declaration is a member of a class extension marked @objc. diff --git a/lib/Sema/TypeChecker.h b/lib/Sema/TypeChecker.h index ad1ee51f5c658..a15a9740e41ac 100644 --- a/lib/Sema/TypeChecker.h +++ b/lib/Sema/TypeChecker.h @@ -556,12 +556,6 @@ class TypeChecker final { std::vector ClosuresWithUncomputedCaptures; private: - Type MaxIntegerType; - Type NSObjectType; - Type NSNumberType; - Type NSValueType; - Type ObjCSelectorType; - /// The set of expressions currently being analyzed for failures. llvm::DenseMap DiagnosedExprs; @@ -734,9 +728,7 @@ class TypeChecker final { Type getIntType(DeclContext *dc); Type getInt8Type(DeclContext *dc); Type getUInt8Type(DeclContext *dc); - Type getNSObjectType(DeclContext *dc); - Type getObjCSelectorType(DeclContext *dc); - + /// Try to resolve an IdentTypeRepr, returning either the referenced /// Type or an ErrorType in case of error. static Type resolveIdentifierType(TypeResolution resolution,