Skip to content

[AST] Consolidate Obj-C types on ASTContext #28128

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Nov 7, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 7 additions & 11 deletions include/swift/AST/ASTContext.h
Original file line number Diff line number Diff line change
Expand Up @@ -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) \
Expand Down
37 changes: 37 additions & 0 deletions include/swift/AST/KnownObjCTypes.def
Original file line number Diff line number Diff line change
@@ -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
68 changes: 21 additions & 47 deletions lib/AST/ASTContext.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -98,12 +98,6 @@ using AssociativityCacheType =
llvm::DenseMap<std::pair<PrecedenceGroupDecl *, PrecedenceGroupDecl *>,
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;
Expand Down Expand Up @@ -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;

Expand All @@ -216,15 +215,6 @@ struct ASTContext::Implementation {

/// The declaration of Swift.AutoreleasingUnsafeMutablePointer<T>.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;
Expand Down Expand Up @@ -827,33 +817,12 @@ CanType ASTContext::getNeverType() const {
return neverDecl->getDeclaredType()->getCanonicalType();
}

StructDecl *ASTContext::getObjCBoolDecl() const {
if (!getImpl().ObjCBoolDecl) {
SmallVector<ValueDecl *, 1> results;
auto *Context = const_cast<ASTContext *>(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<StructDecl>(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<ValueDecl *, 1> decls; \
M->lookupQualified(M, getIdentifier(#NAME), NL_OnlyTypes, decls); \
if (decls.size() == 1 && isa<DECLTYPE>(decls[0])) { \
Expand All @@ -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.
Expand Down Expand Up @@ -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;
}
}

Expand Down Expand Up @@ -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'.
Expand Down
2 changes: 1 addition & 1 deletion lib/ClangImporter/ImportType.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);

Expand Down
4 changes: 2 additions & 2 deletions lib/PrintAsObjC/DeclAndTypePrinter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
Expand Down
6 changes: 3 additions & 3 deletions lib/SIL/Bridging.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
}

Expand Down
8 changes: 3 additions & 5 deletions lib/SIL/SILType.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}

Expand Down
7 changes: 3 additions & 4 deletions lib/SILGen/SILGen.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
Expand All @@ -349,8 +349,7 @@ ProtocolConformance *SILGenModule::getNSErrorConformanceToError() {
}

auto conformance =
SwiftModule->lookupConformance(nsError->getDeclaredInterfaceType(),
cast<ProtocolDecl>(error));
SwiftModule->lookupConformance(nsErrorTy, cast<ProtocolDecl>(error));

if (conformance.isConcrete())
NSErrorConformanceToError = conformance.getConcrete();
Expand Down
4 changes: 1 addition & 3 deletions lib/SILGen/SILGenConvert.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down
5 changes: 2 additions & 3 deletions lib/Sema/CSApply.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
2 changes: 1 addition & 1 deletion lib/Sema/CSGen.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
13 changes: 7 additions & 6 deletions lib/Sema/CSSimplify.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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<BoundGenericType>()) {
if (fromBGT->getDecl() == TC.Context.getArrayDecl()) {
// [AnyObject]
Expand All @@ -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))));
Expand All @@ -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))));
Expand Down
6 changes: 2 additions & 4 deletions lib/Sema/MiscDiagnostics.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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<DeclContext *>(dc));
auto selectorTy = dc->getASTContext().getSelectorType();
if (!selectorTy) return;

const_cast<Expr *>(expr)->walk(ObjCSelectorWalker(tc, dc, selectorTy));
Expand Down Expand Up @@ -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) {
Expand Down
11 changes: 5 additions & 6 deletions lib/Sema/TypeCheckConstraints.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
Expand Down Expand Up @@ -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<MetatypeType>()) {
if (toMeta->getInstanceType()->mayHaveSuperclass()
Expand All @@ -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))
Expand Down
Loading