Merge pull request #18060 from jrose-apple/and-you-get-a-class_getImageName
[runtime] Backwards-deployment support for class_getImageName
https://bugs.swift.org/browse/SR-1917
rdar://problem/41535552
diff --git a/docs/GenericsManifesto.md b/docs/GenericsManifesto.md
index 2413bee..b54fa9b 100644
--- a/docs/GenericsManifesto.md
+++ b/docs/GenericsManifesto.md
@@ -757,9 +757,9 @@
One explicit way to allow such operations in a type-safe manner is to introduce an "open existential" operation of some sort, which extracts and gives a name to the dynamic type stored inside an existential. For example:
```Swift
-if let storedInE1 = e1 openas T { // T is a the type of storedInE1, a copy of the value stored in e1
- if let storedInE2 = e2 as? T { // is e2 also a T?
- if storedInE1 == storedInE2 { ... } // okay: storedInT1 and storedInE2 are both of type T, which we know is Equatable
+if let storedInE1 = e1 openas T { // T is the type of storedInE1, a copy of the value stored in e1
+ if let storedInE2 = e2 as? T { // Does e2 have type T? If so, copy its value to storedInE2
+ if storedInE1 == storedInE2 { ... } // Okay: storedInT1 and storedInE2 are both of type T, which we know is Equatable
}
}
```
diff --git a/include/swift/AST/AnyRequest.h b/include/swift/AST/AnyRequest.h
index f742f95..6cb7d0f 100644
--- a/include/swift/AST/AnyRequest.h
+++ b/include/swift/AST/AnyRequest.h
@@ -136,9 +136,20 @@
public:
AnyRequest(const AnyRequest &other) = default;
- AnyRequest(AnyRequest &&other) = default;
AnyRequest &operator=(const AnyRequest &other) = default;
- AnyRequest &operator=(AnyRequest &&other) = default;
+
+ AnyRequest(AnyRequest &&other)
+ : storageKind(other.storageKind), stored(std::move(other.stored)) {
+ other.storageKind = StorageKind::Empty;
+ }
+
+ AnyRequest &operator=(AnyRequest &&other) {
+ storageKind = other.storageKind;
+ stored = std::move(other.stored);
+ other.storageKind = StorageKind::Empty;
+ other.stored = nullptr;
+ return *this;
+ }
AnyRequest(AnyRequest &other)
: storageKind(other.storageKind), stored(other.stored) { }
diff --git a/include/swift/AST/Decl.h b/include/swift/AST/Decl.h
index 057521b..ec62472 100644
--- a/include/swift/AST/Decl.h
+++ b/include/swift/AST/Decl.h
@@ -2242,8 +2242,20 @@
/// Whether there are any "overridden" declarations. The actual overridden
/// declarations are kept in a side table in the ASTContext.
unsigned hasOverridden : 1;
+
+ /// Whether the "isDynamic" bit has been computed yet.
+ unsigned isDynamicComputed : 1;
+
+ /// Whether this declaration is 'dynamic', meaning that all uses of
+ /// the declaration will go through an extra level of indirection that
+ /// allows the entity to be replaced at runtime.
+ unsigned isDynamic : 1;
} LazySemanticInfo;
+ friend class OverriddenDeclsRequest;
+ friend class IsObjCRequest;
+ friend class IsDynamicRequest;
+
protected:
ValueDecl(DeclKind K,
llvm::PointerUnion<DeclContext *, ASTContext *> context,
@@ -2256,6 +2268,8 @@
LazySemanticInfo.isObjC = false;
LazySemanticInfo.hasOverriddenComputed = false;
LazySemanticInfo.hasOverridden = false;
+ LazySemanticInfo.isDynamicComputed = false;
+ LazySemanticInfo.isDynamic = false;
}
// MemberLookupTable borrows a bit from this type
@@ -2468,18 +2482,15 @@
ValueDecl *getOverriddenDecl() const;
/// Retrieve the declarations that this declaration overrides, if any.
- ArrayRef<ValueDecl *> getOverriddenDecls() const;
+ llvm::TinyPtrVector<ValueDecl *> getOverriddenDecls() const;
/// Set the declaration that this declaration overrides.
void setOverriddenDecl(ValueDecl *overridden) {
- (void)setOverriddenDecls(overridden);
+ setOverriddenDecls(overridden);
}
/// Set the declarations that this declaration overrides.
- ///
- /// \returns the ASTContext-allocated version of the array of overridden
- /// declarations.
- ArrayRef<ValueDecl *> setOverriddenDecls(ArrayRef<ValueDecl *> overridden);
+ void setOverriddenDecls(ArrayRef<ValueDecl *> overridden);
/// Whether the overridden declarations have already been computed.
bool overriddenDeclsComputed() const;
@@ -2507,8 +2518,14 @@
}
/// Is this declaration marked with 'dynamic'?
- bool isDynamic() const {
- return getAttrs().hasAttribute<DynamicAttr>();
+ bool isDynamic() const;
+
+ /// Set whether this type is 'dynamic' or not.
+ void setIsDynamic(bool value);
+
+ /// Whether the 'dynamic' bit has been computed already.
+ bool isDynamicComputed() const {
+ return LazySemanticInfo.isDynamicComputed;
}
/// Returns true if this decl can be found by id-style dynamic lookup.
@@ -2884,11 +2901,7 @@
/// Retrieve the set of associated types overridden by this associated
/// type.
- CastArrayRefView<ValueDecl *, AssociatedTypeDecl>
- getOverriddenDecls() const {
- return CastArrayRefView<ValueDecl *, AssociatedTypeDecl>(
- AbstractTypeParamDecl::getOverriddenDecls());
- }
+ llvm::TinyPtrVector<AssociatedTypeDecl *> getOverriddenDecls() const;
SourceLoc getStartLoc() const { return KeywordLoc; }
SourceRange getSourceRange() const;
diff --git a/include/swift/AST/LazyResolver.h b/include/swift/AST/LazyResolver.h
index 3620dc0..3f45cd5 100644
--- a/include/swift/AST/LazyResolver.h
+++ b/include/swift/AST/LazyResolver.h
@@ -60,12 +60,6 @@
/// consistency and provides the value a type.
virtual void resolveDeclSignature(ValueDecl *VD) = 0;
- /// Resolve the "overridden" declaration of the given declaration.
- virtual void resolveOverriddenDecl(ValueDecl *VD) = 0;
-
- /// Resolve the "is Objective-C" bit for the given declaration.
- virtual void resolveIsObjC(ValueDecl *VD) = 0;
-
/// Resolve the trailing where clause of the given protocol in-place.
virtual void resolveTrailingWhereClause(ProtocolDecl *proto) = 0;
diff --git a/include/swift/AST/NameLookup.h b/include/swift/AST/NameLookup.h
index c551604..be4ea1a 100644
--- a/include/swift/AST/NameLookup.h
+++ b/include/swift/AST/NameLookup.h
@@ -287,12 +287,10 @@
///
/// \param decls The set of declarations being considered.
/// \param curModule The current module.
-/// \param typeResolver Used to resolve overload types.
///
/// \returns true if any shadowed declarations were removed.
bool removeShadowedDecls(SmallVectorImpl<ValueDecl*> &decls,
- const ModuleDecl *curModule,
- LazyResolver *typeResolver);
+ const ModuleDecl *curModule);
/// Finds decls visible in the given context and feeds them to the given
/// VisibleDeclConsumer. If the current DeclContext is nested in a function,
diff --git a/include/swift/AST/TypeCheckRequests.h b/include/swift/AST/TypeCheckRequests.h
index 437414a..51f5eb3 100644
--- a/include/swift/AST/TypeCheckRequests.h
+++ b/include/swift/AST/TypeCheckRequests.h
@@ -21,6 +21,7 @@
#include "swift/AST/SimpleRequest.h"
#include "swift/Basic/Statistic.h"
#include "llvm/ADT/Hashing.h"
+#include "llvm/ADT/TinyPtrVector.h"
namespace swift {
@@ -121,6 +122,89 @@
void cacheResult(Type value) const;
};
+/// Request to determine the set of declarations that were are overridden
+/// by the given declaration.
+class OverriddenDeclsRequest
+ : public SimpleRequest<OverriddenDeclsRequest,
+ CacheKind::SeparatelyCached,
+ llvm::TinyPtrVector<ValueDecl *>,
+ ValueDecl *> {
+public:
+ using SimpleRequest::SimpleRequest;
+
+private:
+ friend class SimpleRequest;
+
+ // Evaluation.
+ llvm::TinyPtrVector<ValueDecl *> evaluate(Evaluator &evaluator,
+ ValueDecl *decl) const;
+
+public:
+ // Cycle handling
+ llvm::TinyPtrVector<ValueDecl *> breakCycle() const { return { }; }
+ void diagnoseCycle(DiagnosticEngine &diags) const;
+ void noteCycleStep(DiagnosticEngine &diags) const;
+
+ // Separate caching.
+ bool isCached() const { return true; }
+ Optional<llvm::TinyPtrVector<ValueDecl *>> getCachedResult() const;
+ void cacheResult(llvm::TinyPtrVector<ValueDecl *> value) const;
+};
+
+/// Determine whether the given declaration is exposed to Objective-C.
+class IsObjCRequest :
+ public SimpleRequest<IsObjCRequest,
+ CacheKind::SeparatelyCached,
+ bool,
+ ValueDecl *> {
+public:
+ using SimpleRequest::SimpleRequest;
+
+private:
+ friend class SimpleRequest;
+
+ // Evaluation.
+ bool evaluate(Evaluator &evaluator, ValueDecl *decl) const;
+
+public:
+ // Cycle handling
+ bool breakCycle() const;
+ void diagnoseCycle(DiagnosticEngine &diags) const;
+ void noteCycleStep(DiagnosticEngine &diags) const;
+
+ // Separate caching.
+ bool isCached() const { return true; }
+ Optional<bool> getCachedResult() const;
+ void cacheResult(bool value) const;
+};
+
+/// Determine whether the given declaration is 'dynamic''.
+class IsDynamicRequest :
+ public SimpleRequest<IsDynamicRequest,
+ CacheKind::SeparatelyCached,
+ bool,
+ ValueDecl *> {
+public:
+ using SimpleRequest::SimpleRequest;
+
+private:
+ friend class SimpleRequest;
+
+ // Evaluation.
+ bool evaluate(Evaluator &evaluator, ValueDecl *decl) const;
+
+public:
+ // Cycle handling
+ bool breakCycle() const;
+ void diagnoseCycle(DiagnosticEngine &diags) const;
+ void noteCycleStep(DiagnosticEngine &diags) const;
+
+ // Separate caching.
+ bool isCached() const { return true; }
+ Optional<bool> getCachedResult() const;
+ void cacheResult(bool value) const;
+};
+
/// The zone number for the type checker.
#define SWIFT_TYPE_CHECKER_REQUESTS_TYPEID_ZONE 10
diff --git a/include/swift/AST/TypeCheckerTypeIDZone.def b/include/swift/AST/TypeCheckerTypeIDZone.def
index 44732e6..d754436 100644
--- a/include/swift/AST/TypeCheckerTypeIDZone.def
+++ b/include/swift/AST/TypeCheckerTypeIDZone.def
@@ -17,3 +17,6 @@
SWIFT_TYPEID(InheritedTypeRequest)
SWIFT_TYPEID(SuperclassTypeRequest)
SWIFT_TYPEID(EnumRawTypeRequest)
+SWIFT_TYPEID(OverriddenDeclsRequest)
+SWIFT_TYPEID(IsObjCRequest)
+SWIFT_TYPEID(IsDynamicRequest)
diff --git a/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp
index 4bad14c..c63bb39 100644
--- a/lib/AST/ASTContext.cpp
+++ b/lib/AST/ASTContext.cpp
@@ -35,6 +35,7 @@
#include "swift/AST/RawComment.h"
#include "swift/AST/SubstitutionMap.h"
#include "swift/AST/SILLayout.h"
+#include "swift/AST/TypeCheckRequests.h"
#include "swift/AST/TypeCheckerDebugConsumer.h"
#include "swift/Basic/Compiler.h"
#include "swift/Basic/SourceManager.h"
@@ -1594,53 +1595,47 @@
return env;
}
-ArrayRef<ValueDecl *> ValueDecl::getOverriddenDecls() const {
- // Check whether the overrides have already been computed.
- if (LazySemanticInfo.hasOverriddenComputed) {
- // If there are no overridden declarations (the common case), return.
- if (!LazySemanticInfo.hasOverridden) return { };
+Optional<llvm::TinyPtrVector<ValueDecl *>>
+OverriddenDeclsRequest::getCachedResult() const {
+ auto decl = std::get<0>(getStorage());
+ if (!decl->LazySemanticInfo.hasOverriddenComputed)
+ return None;
- // Look up the overridden declarations in the ASTContext.
- auto known = getASTContext().getImpl().Overrides.find(this);
- assert(known != getASTContext().getImpl().Overrides.end());
- return known->second;
- }
+ // If there are no overridden declarations (the common case), return.
+ llvm::TinyPtrVector<ValueDecl *> overridden;
+ if (!decl->LazySemanticInfo.hasOverridden) return overridden;
- ASTContext &ctx = getASTContext();
- if (auto resolver = ctx.getLazyResolver()) {
- resolver->resolveOverriddenDecl(const_cast<ValueDecl *>(this));
- assert(LazySemanticInfo.hasOverriddenComputed);
- return getOverriddenDecls();
- }
-
- // FIXME: Shouldn't need this fallback.
- return { };
+ // Retrieve the set of overrides from the ASTContext.
+ ASTContext &ctx = decl->getASTContext();
+ auto known = ctx.getImpl().Overrides.find(decl);
+ assert(known != ctx.getImpl().Overrides.end());
+ overridden.insert(overridden.end(),
+ known->second.begin(), known->second.end());
+ return overridden;
}
-ArrayRef<ValueDecl *> ValueDecl::setOverriddenDecls(
- ArrayRef<ValueDecl *> overridden) {
- LazySemanticInfo.hasOverriddenComputed = true;
+void OverriddenDeclsRequest::cacheResult(
+ llvm::TinyPtrVector<ValueDecl *> value) const {
+ auto decl = std::get<0>(getStorage());
+ decl->LazySemanticInfo.hasOverriddenComputed = true;
+ decl->LazySemanticInfo.hasOverridden = !value.empty();
- // If the set of overridden declarations is empty, note that.
- if (overridden.empty()) {
- LazySemanticInfo.hasOverridden = false;
- return { };
- }
+ if (value.empty())
+ return;
// Sanity-check the declarations we were given.
- for (auto decl : overridden) {
- assert(decl->getKind() == this->getKind() &&
+ for (auto overriddenDecl : value) {
+ assert(overriddenDecl->getKind() == decl->getKind() &&
"Overridden decl kind mismatch");
- if (auto func = dyn_cast<AbstractFunctionDecl>(decl))
+ if (auto func = dyn_cast<AbstractFunctionDecl>(overriddenDecl))
func->setIsOverridden();
}
// Record the overrides in the context.
- auto &ctx = getASTContext();
- LazySemanticInfo.hasOverridden = true;
- auto overriddenCopy = ctx.AllocateCopy(overridden);
- (void)ctx.getImpl().Overrides.insert({this, overriddenCopy});
- return overriddenCopy;
+ auto &ctx = decl->getASTContext();
+ auto overriddenCopy =
+ ctx.AllocateCopy(value.operator ArrayRef<ValueDecl *>());
+ (void)ctx.getImpl().Overrides.insert({decl, overriddenCopy});
}
bool ASTContext::canImportModule(std::pair<Identifier, SourceLoc> ModulePath) {
@@ -2372,8 +2367,6 @@
Optional<ForeignErrorConvention>
AbstractFunctionDecl::getForeignErrorConvention() const {
- if (!isObjC() && !getAttrs().hasAttribute<CDeclAttr>())
- return None;
if (!hasThrows())
return None;
auto &conventionsMap = getASTContext().getImpl().ForeignErrorConventions;
diff --git a/lib/AST/ASTVerifier.cpp b/lib/AST/ASTVerifier.cpp
index 0c200d8..30879fc 100644
--- a/lib/AST/ASTVerifier.cpp
+++ b/lib/AST/ASTVerifier.cpp
@@ -181,6 +181,16 @@
}
};
+namespace {
+ /// Retrieve the "overridden" declaration of this declaration, but only if
+ // it's already been computed.
+ template<typename T>
+ T *getOverriddenDeclIfAvailable(T *decl) {
+ if (!decl->overriddenDeclsComputed()) return nullptr;
+
+ return cast_or_null<T>(decl->getOverriddenDecl());
+ }
+}
class Verifier : public ASTWalker {
PointerUnion<ModuleDecl *, SourceFile *> M;
ASTContext &Ctx;
@@ -841,7 +851,7 @@
}
}
- if (auto Overridden = D->getOverriddenDecl()) {
+ if (auto Overridden = getOverriddenDeclIfAvailable(D)) {
if (D->getDeclContext() == Overridden->getDeclContext()) {
PrettyStackTraceDecl debugStack("verifying overridden", D);
Out << "cannot override a decl in the same DeclContext";
@@ -2232,42 +2242,6 @@
}
}
- // Make sure we consistently set accessor overrides.
- if (auto *baseASD = ASD->getOverriddenDecl()) {
- if (ASD->getGetter() && baseASD->getGetter())
- assert(ASD->getGetter()->getOverriddenDecl() ==
- baseASD->getGetter() &&
- "Storage overrides but getter does not");
- if (ASD->getSetter() && baseASD->getSetter() &&
- baseASD->isSetterAccessibleFrom(ASD->getDeclContext()))
- assert(ASD->getSetter()->getOverriddenDecl() ==
- baseASD->getSetter() &&
- "Storage overrides but setter does not");
- if (ASD->getMaterializeForSetFunc() &&
- baseASD->getMaterializeForSetFunc() &&
- baseASD->isSetterAccessibleFrom(ASD->getDeclContext())) {
- if (baseASD->getMaterializeForSetFunc()->hasForcedStaticDispatch()) {
- assert(ASD->getMaterializeForSetFunc()->getOverriddenDecl() == nullptr
- && "Forced static dispatch materializeForSet should not be "
- "overridden");
- } else {
- assert(ASD->getMaterializeForSetFunc()->getOverriddenDecl() ==
- baseASD->getMaterializeForSetFunc() &&
- "Storage override but materializeForSet does not");
- }
- }
- } else {
- if (ASD->getGetter())
- assert(!ASD->getGetter()->getOverriddenDecl() &&
- "Storage does not override but getter does");
- if (ASD->getSetter())
- assert(!ASD->getSetter()->getOverriddenDecl() &&
- "Storage does not override but setter does");
- if (ASD->getMaterializeForSetFunc())
- assert(!ASD->getMaterializeForSetFunc()->getOverriddenDecl() &&
- "Storage does not override but materializeForSet does");
- }
-
verifyCheckedBase(ASD);
}
diff --git a/lib/AST/Decl.cpp b/lib/AST/Decl.cpp
index 1833cdb..3f86048 100644
--- a/lib/AST/Decl.cpp
+++ b/lib/AST/Decl.cpp
@@ -2022,13 +2022,20 @@
return CanType();
}
-bool ValueDecl::isObjC() const {
- if (LazySemanticInfo.isObjCComputed)
- return LazySemanticInfo.isObjC;
+llvm::TinyPtrVector<ValueDecl *> ValueDecl::getOverriddenDecls() const {
+ ASTContext &ctx = getASTContext();
+ return ctx.evaluator(OverriddenDeclsRequest{const_cast<ValueDecl *>(this)});
+}
- // Fallback: look for an @objc attribute.
- // FIXME: This should become an error, eventually.
- return getAttrs().hasAttribute<ObjCAttr>();
+void ValueDecl::setOverriddenDecls(ArrayRef<ValueDecl *> overridden) {
+ llvm::TinyPtrVector<ValueDecl *> overriddenVec(overridden);
+ OverriddenDeclsRequest request{const_cast<ValueDecl *>(this)};
+ request.cacheResult(overriddenVec);
+}
+
+bool ValueDecl::isObjC() const {
+ ASTContext &ctx = getASTContext();
+ return ctx.evaluator(IsObjCRequest{const_cast<ValueDecl *>(this)});
}
void ValueDecl::setIsObjC(bool value) {
@@ -2043,6 +2050,24 @@
LazySemanticInfo.isObjC = value;
}
+bool ValueDecl::isDynamic() const {
+ ASTContext &ctx = getASTContext();
+ return ctx.evaluator(IsDynamicRequest{const_cast<ValueDecl *>(this)});
+}
+
+void ValueDecl::setIsDynamic(bool value) {
+ assert(!LazySemanticInfo.isDynamicComputed ||
+ LazySemanticInfo.isDynamic == value);
+
+ if (LazySemanticInfo.isDynamicComputed) {
+ assert(LazySemanticInfo.isDynamic == value);
+ return;
+ }
+
+ LazySemanticInfo.isDynamicComputed = true;
+ LazySemanticInfo.isDynamic = value;
+}
+
bool ValueDecl::canBeAccessedByDynamicLookup() const {
if (!hasName())
return false;
@@ -2866,6 +2891,24 @@
return SourceRange(KeywordLoc, endLoc);
}
+llvm::TinyPtrVector<AssociatedTypeDecl *>
+AssociatedTypeDecl::getOverriddenDecls() const {
+ // FIXME: Performance hack because we end up looking at the overridden
+ // declarations of an associated type a *lot*.
+ OverriddenDeclsRequest request{const_cast<AssociatedTypeDecl *>(this)};
+ llvm::TinyPtrVector<ValueDecl *> overridden;
+ if (auto cached = request.getCachedResult())
+ overridden = std::move(*cached);
+ else
+ overridden = AbstractTypeParamDecl::getOverriddenDecls();
+
+ llvm::TinyPtrVector<AssociatedTypeDecl *> assocTypes;
+ for (auto decl : overridden) {
+ assocTypes.push_back(cast<AssociatedTypeDecl>(decl));
+ }
+ return assocTypes;
+}
+
AssociatedTypeDecl *AssociatedTypeDecl::getAssociatedTypeAnchor() const {
auto overridden = getOverriddenDecls();
@@ -3042,7 +3085,9 @@
if (CD->isGenericContext())
genericAncestry = true;
- if (CD->isObjC())
+ // FIXME: Checking isObjC() introduces cyclic dependencies here, but this
+ // doesn't account for ill-formed @objc.
+ if (CD->getAttrs().hasAttribute<ObjCAttr>())
isObjC = true;
if (!CD->hasSuperclass())
@@ -4869,6 +4914,10 @@
ObjCSelector
AbstractFunctionDecl::getObjCSelector(DeclName preferredName) const {
+ // FIXME: Forces computation of the Objective-C selector.
+ if (getASTContext().getLazyResolver())
+ (void)isObjC();
+
// If there is an @objc attribute with a name, use that name.
auto *objc = getAttrs().getAttribute<ObjCAttr>();
if (auto name = getNameFromObjcAttribute(objc, preferredName)) {
@@ -5020,7 +5069,7 @@
// Final members are always be called directly.
// Dynamic methods are always accessed by objc_msgSend().
- if (decl->isFinal() || decl->isDynamic())
+ if (decl->isFinal() || decl->isDynamic() || decl->hasClangNode())
return false;
if (auto *accessor = dyn_cast<AccessorDecl>(decl)) {
@@ -5046,7 +5095,7 @@
}
auto base = decl->getOverriddenDecl();
- if (!base || base->hasClangNode())
+ if (!base || base->hasClangNode() || base->isDynamic())
return true;
// If the method overrides something, we only need a new entry if the
diff --git a/lib/AST/LookupVisibleDecls.cpp b/lib/AST/LookupVisibleDecls.cpp
index d77c23d..d69a4c6 100644
--- a/lib/AST/LookupVisibleDecls.cpp
+++ b/lib/AST/LookupVisibleDecls.cpp
@@ -215,7 +215,7 @@
}
// Handle shadowing.
- removeShadowedDecls(FoundDecls, CurrDC->getParentModule(), TypeResolver);
+ removeShadowedDecls(FoundDecls, CurrDC->getParentModule());
}
/// \brief Enumerate immediate members of the type \c LookupType and its
diff --git a/lib/AST/NameLookup.cpp b/lib/AST/NameLookup.cpp
index 3093bd7..9a32213 100644
--- a/lib/AST/NameLookup.cpp
+++ b/lib/AST/NameLookup.cpp
@@ -157,8 +157,9 @@
}
bool swift::removeShadowedDecls(SmallVectorImpl<ValueDecl*> &decls,
- const ModuleDecl *curModule,
- LazyResolver *typeResolver) {
+ const ModuleDecl *curModule) {
+ auto typeResolver = curModule->getASTContext().getLazyResolver();
+
// Category declarations by their signatures.
llvm::SmallDenseMap<std::pair<CanType, DeclBaseName>,
llvm::TinyPtrVector<ValueDecl *>>
@@ -478,6 +479,7 @@
{
ModuleDecl &M = *DC->getParentModule();
ASTContext &Ctx = M.getASTContext();
+ if (!TypeResolver) TypeResolver = Ctx.getLazyResolver();
const SourceManager &SM = Ctx.SourceMgr;
DebuggerClient *DebugClient = M.getDebugClient();
@@ -1491,8 +1493,6 @@
createObjCMethodLookup();
}
- assert(method->isObjC() && "Not an Objective-C method");
-
// Record the method.
bool isInstanceMethod = method->isObjCInstanceMethod();
auto selector = method->getObjCSelector();
@@ -1614,6 +1614,9 @@
using namespace namelookup;
assert(decls.empty() && "additive lookup not supported");
+ if (!typeResolver)
+ typeResolver = getASTContext().getLazyResolver();
+
auto checkLookupCascading = [this, options]() -> Optional<bool> {
switch (static_cast<unsigned>(options & NL_KnownDependencyMask)) {
case 0:
@@ -1885,9 +1888,6 @@
continue;
// If the declaration is not @objc, it cannot be called dynamically.
- if (typeResolver)
- typeResolver->resolveIsObjC(decl);
-
if (!decl->isObjC())
continue;
@@ -1920,7 +1920,7 @@
// If we're supposed to remove shadowed/hidden declarations, do so now.
ModuleDecl *M = getParentModule();
if (options & NL_RemoveNonVisible)
- removeShadowedDecls(decls, M, typeResolver);
+ removeShadowedDecls(decls, M);
if (auto *debugClient = M->getDebugClient())
filterForDiscriminator(decls, debugClient);
diff --git a/lib/AST/ProtocolConformance.cpp b/lib/AST/ProtocolConformance.cpp
index 0d7e18c..3eee9ef 100644
--- a/lib/AST/ProtocolConformance.cpp
+++ b/lib/AST/ProtocolConformance.cpp
@@ -673,6 +673,7 @@
// Otherwise, resolve the type witness.
PrettyStackTraceRequirement trace("resolving", this, assocType);
+ if (!resolver) resolver = assocType->getASTContext().getLazyResolver();
assert(resolver && "Unable to resolve type witness");
// Block recursive resolution of this type witness.
@@ -800,6 +801,7 @@
auto known = Mapping.find(requirement);
if (known == Mapping.end()) {
+ if (!resolver) resolver = requirement->getASTContext().getLazyResolver();
assert(resolver && "Unable to resolve witness without resolver");
resolver->resolveWitness(this, requirement);
known = Mapping.find(requirement);
diff --git a/lib/AST/Type.cpp b/lib/AST/Type.cpp
index 74e3e5f..c29348a 100644
--- a/lib/AST/Type.cpp
+++ b/lib/AST/Type.cpp
@@ -1154,6 +1154,18 @@
case TypeKind::GenericTypeParam: {
GenericTypeParamType *gp = cast<GenericTypeParamType>(this);
auto gpDecl = gp->getDecl();
+
+ // If we haven't set a depth for this generic parameter, try to do so.
+ // FIXME: This is a dreadful hack.
+ if (gpDecl->getDepth() == GenericTypeParamDecl::InvalidDepth) {
+ auto resolver = gpDecl->getASTContext().getLazyResolver();
+ assert(resolver && "Need to resolve generic parameter depth");
+ if (auto decl =
+ gpDecl->getDeclContext()->getInnermostDeclarationDeclContext())
+ if (auto valueDecl = dyn_cast<ValueDecl>(decl))
+ resolver->resolveDeclSignature(valueDecl);
+ }
+
assert(gpDecl->getDepth() != GenericTypeParamDecl::InvalidDepth &&
"parameter hasn't been validated");
Result = GenericTypeParamType::get(gpDecl->getDepth(), gpDecl->getIndex(),
@@ -1866,10 +1878,6 @@
// @objc classes.
if (auto classDecl = type->getClassOrBoundGenericClass()) {
- auto &ctx = classDecl->getASTContext();
- if (auto resolver = ctx.getLazyResolver())
- resolver->resolveIsObjC(classDecl);
-
if (classDecl->isObjC())
return ForeignRepresentableKind::Object;
}
diff --git a/lib/AST/TypeCheckRequests.cpp b/lib/AST/TypeCheckRequests.cpp
index 3937522..48894a0 100644
--- a/lib/AST/TypeCheckRequests.cpp
+++ b/lib/AST/TypeCheckRequests.cpp
@@ -146,3 +146,84 @@
auto enumDecl = std::get<0>(getStorage());
enumDecl->LazySemanticInfo.RawType.setPointerAndInt(value, true);
}
+
+//----------------------------------------------------------------------------//
+// Overridden decls computation.
+//----------------------------------------------------------------------------//
+void OverriddenDeclsRequest::diagnoseCycle(DiagnosticEngine &diags) const {
+ auto decl = std::get<0>(getStorage());
+ diags.diagnose(decl, diag::circular_reference);
+}
+
+void OverriddenDeclsRequest::noteCycleStep(DiagnosticEngine &diags) const {
+ auto decl = std::get<0>(getStorage());
+ diags.diagnose(decl, diag::circular_reference_through);
+}
+
+//----------------------------------------------------------------------------//
+// isObjC computation.
+//----------------------------------------------------------------------------//
+
+bool IsObjCRequest::breakCycle() const {
+ auto decl = std::get<0>(getStorage());
+ return decl->getAttrs().hasAttribute<ObjCAttr>();
+}
+
+void IsObjCRequest::diagnoseCycle(DiagnosticEngine &diags) const {
+ // FIXME: Improve this diagnostic.
+ auto decl = std::get<0>(getStorage());
+ diags.diagnose(decl, diag::circular_reference);
+}
+
+void IsObjCRequest::noteCycleStep(DiagnosticEngine &diags) const {
+ auto decl = std::get<0>(getStorage());
+ // FIXME: Customize this further.
+ diags.diagnose(decl, diag::circular_reference_through);
+}
+
+Optional<bool> IsObjCRequest::getCachedResult() const {
+ auto decl = std::get<0>(getStorage());
+ if (decl->LazySemanticInfo.isObjCComputed)
+ return decl->LazySemanticInfo.isObjC;
+
+ return None;
+}
+
+void IsObjCRequest::cacheResult(bool value) const {
+ auto decl = std::get<0>(getStorage());
+ decl->setIsObjC(value);
+}
+
+//----------------------------------------------------------------------------//
+// isDynamic computation.
+//----------------------------------------------------------------------------//
+
+bool IsDynamicRequest::breakCycle() const {
+ auto decl = std::get<0>(getStorage());
+ return decl->getAttrs().hasAttribute<DynamicAttr>();
+}
+
+void IsDynamicRequest::diagnoseCycle(DiagnosticEngine &diags) const {
+ // FIXME: Improve this diagnostic.
+ auto decl = std::get<0>(getStorage());
+ diags.diagnose(decl, diag::circular_reference);
+}
+
+void IsDynamicRequest::noteCycleStep(DiagnosticEngine &diags) const {
+ auto decl = std::get<0>(getStorage());
+ // FIXME: Customize this further.
+ diags.diagnose(decl, diag::circular_reference_through);
+}
+
+Optional<bool> IsDynamicRequest::getCachedResult() const {
+ auto decl = std::get<0>(getStorage());
+ if (decl->LazySemanticInfo.isDynamicComputed)
+ return decl->LazySemanticInfo.isDynamic;
+
+ return None;
+}
+
+void IsDynamicRequest::cacheResult(bool value) const {
+ auto decl = std::get<0>(getStorage());
+ decl->setIsDynamic(value);
+}
diff --git a/lib/ClangImporter/ClangImporter.cpp b/lib/ClangImporter/ClangImporter.cpp
index 7930e93..11b3717 100644
--- a/lib/ClangImporter/ClangImporter.cpp
+++ b/lib/ClangImporter/ClangImporter.cpp
@@ -3542,10 +3542,6 @@
return EffectiveClangContext();
}
- // Resolve the type.
- if (auto typeResolver = getTypeResolver())
- typeResolver->resolveIsObjC(const_cast<NominalTypeDecl *>(nominal));
-
// If it's an @objc entity, go look for it.
if (nominal->isObjC()) {
// Map the name. If we can't represent the Swift name in Clang.
diff --git a/lib/ClangImporter/ImportDecl.cpp b/lib/ClangImporter/ImportDecl.cpp
index 8668b58..ffd40ec 100644
--- a/lib/ClangImporter/ImportDecl.cpp
+++ b/lib/ClangImporter/ImportDecl.cpp
@@ -531,6 +531,7 @@
/*GenericParams=*/nullptr, params,
TypeLoc::withoutLoc(rawTy), enumDecl);
getterDecl->setImplicit();
+ getterDecl->setIsObjC(false);
auto type = ParameterList::getFullInterfaceType(rawTy, params, C);
@@ -615,6 +616,7 @@
/*GenericParams=*/nullptr, params,
TypeLoc::withoutLoc(computedType), structDecl);
getterDecl->setImplicit();
+ getterDecl->setIsObjC(false);
auto type = ParameterList::getFullInterfaceType(computedType, params, C);
@@ -684,6 +686,7 @@
/*GenericParams=*/nullptr, params,
TypeLoc::withoutLoc(getterType), importedDecl, clangNode);
getterDecl->setAccess(AccessLevel::Public);
+ getterDecl->setIsObjC(false);
auto type = ParameterList::getFullInterfaceType(getterType, params, C);
getterDecl->setInterfaceType(type);
@@ -725,6 +728,7 @@
/*ThrowsLoc=*/SourceLoc(),
/*GenericParams=*/nullptr, params,
TypeLoc::withoutLoc(voidTy), importedDecl, clangNode);
+ setterDecl->setIsObjC(false);
auto type = ParameterList::getFullInterfaceType(voidTy, params, C);
setterDecl->setInterfaceType(type);
@@ -1883,6 +1887,7 @@
TypeLoc::withoutLoc(stringTy), swiftDecl);
getterDecl->setInterfaceType(toStringTy);
getterDecl->setValidationToChecked();
+ getterDecl->setIsObjC(false);
swiftDecl->addMember(errorDomainPropertyDecl);
swiftDecl->addMember(getterDecl);
@@ -3445,6 +3450,7 @@
Impl.importSourceLoc(decl->getLocStart()),
name, dc->mapTypeIntoContext(type), dc);
result->setInterfaceType(type);
+ result->setIsObjC(false);
Impl.recordImplicitUnwrapForDecl(result,
importedType.isImplicitlyUnwrapped());
@@ -3579,6 +3585,7 @@
result->setInterfaceType(type);
result->setValidationToChecked();
+ result->setIsObjC(false);
Impl.recordImplicitUnwrapForDecl(result,
importedType.isImplicitlyUnwrapped());
@@ -3672,6 +3679,7 @@
/*IsCaptureList*/false,
Impl.importSourceLoc(decl->getLocation()),
name, dc->mapTypeIntoContext(type), dc);
+ result->setIsObjC(false);
result->setInterfaceType(type);
Impl.recordImplicitUnwrapForDecl(result,
importedType.isImplicitlyUnwrapped());
@@ -3757,6 +3765,7 @@
/*IsCaptureList*/false,
Impl.importSourceLoc(decl->getLocation()),
name, dc->mapTypeIntoContext(type), dc);
+ result->setIsObjC(false);
result->setInterfaceType(type);
Impl.recordImplicitUnwrapForDecl(result,
importedType.isImplicitlyUnwrapped());
@@ -5675,6 +5684,8 @@
result->setInterfaceType(allocType);
Impl.recordImplicitUnwrapForDecl(result,
importedType.isImplicitlyUnwrapped());
+ result->setOverriddenDecls({ });
+ result->setIsObjC(false);
finishFuncDecl(decl, result);
if (correctSwiftName)
@@ -5921,6 +5932,7 @@
VarDecl::Specifier::Var, /*IsCaptureList*/false, SourceLoc(),
propertyName, dc->mapTypeIntoContext(swiftPropertyType), dc);
property->setInterfaceType(swiftPropertyType);
+ property->setIsObjC(false);
Impl.recordImplicitUnwrapForDecl(property,
importedType.isImplicitlyUnwrapped());
@@ -6389,13 +6401,10 @@
// Make sure that we always set the overriden declarations.
SWIFT_DEFER {
if (!decl->overriddenDeclsComputed())
- (void)decl->setOverriddenDecls({ });
+ decl->setOverriddenDecls({ });
};
// Figure out the class in which this method occurs.
- if (!decl->getDeclContext()->isTypeContext())
- return;
-
auto classDecl = decl->getDeclContext()->getAsClassOrClassExtensionContext();
if (!classDecl)
return;
@@ -8323,6 +8332,7 @@
}
var->setInterfaceType(type);
+ var->setIsObjC(false);
// Form the argument patterns.
SmallVector<ParameterList*, 3> getterArgs;
@@ -8357,6 +8367,7 @@
func->setAccess(getOverridableAccessLevel(dc));
func->setValidationToChecked();
func->setImplicit();
+ func->setIsObjC(false);
// If we're not done type checking, build the getter body.
if (!hasFinishedTypeChecking()) {
@@ -8433,6 +8444,7 @@
VarDecl::Specifier::Var,
/*IsCaptureList*/false,
SourceLoc(), name, type, dc);
+ var->setIsObjC(false);
var->setInterfaceType(type);
markUnavailable(var, UnavailableMessage);
diff --git a/lib/SILGen/SILGenBridging.cpp b/lib/SILGen/SILGenBridging.cpp
index 9f1c46a..c2be909 100644
--- a/lib/SILGen/SILGenBridging.cpp
+++ b/lib/SILGen/SILGenBridging.cpp
@@ -1431,7 +1431,7 @@
// Builtin.swift3ImplicitObjCEntrypoint() to enable runtime logging of
// the uses of such entrypoints.
if (attr->isSwift3Inferred() &&
- !decl->getAttrs().hasAttribute<DynamicAttr>() &&
+ !decl->isDynamic() &&
!getASTContext().LangOpts.isSwiftVersion3()) {
// Get the starting source location of the declaration so we can say
diff --git a/lib/SILGen/SILGenFunction.cpp b/lib/SILGen/SILGenFunction.cpp
index 183e34d..4bb9c6d 100644
--- a/lib/SILGen/SILGenFunction.cpp
+++ b/lib/SILGen/SILGenFunction.cpp
@@ -449,9 +449,24 @@
/*resolver*/nullptr,
results);
assert(!results.empty() && "couldn't find UIApplicationMain in UIKit");
- assert(results.size() == 1 && "more than one UIApplicationMain?");
- auto mainRef = SILDeclRef(results.front()).asForeign();
+ // We want the original UIApplicationMain() declaration from Objective-C,
+ // not any overlay overloads.
+ ValueDecl *UIApplicationMainDecl = nullptr;
+ for (auto *result : results) {
+ if (result->hasClangNode()) {
+ assert(!UIApplicationMainDecl
+ && "more than one UIApplicationMain defined in ObjC?!");
+ UIApplicationMainDecl = result;
+#ifndef NDEBUG
+ break;
+#endif
+ }
+ }
+
+ assert(UIApplicationMainDecl && "no UIApplicationMain defined in ObjC?!");
+
+ auto mainRef = SILDeclRef(UIApplicationMainDecl).asForeign();
auto UIApplicationMainFn = SGM.M.getOrCreateFunction(mainClass, mainRef,
NotForDefinition);
auto fnTy = UIApplicationMainFn->getLoweredFunctionType();
diff --git a/lib/Sema/CSApply.cpp b/lib/Sema/CSApply.cpp
index c74645d..969e349 100644
--- a/lib/Sema/CSApply.cpp
+++ b/lib/Sema/CSApply.cpp
@@ -18,6 +18,7 @@
#include "ConstraintSystem.h"
#include "MiscDiagnostics.h"
+#include "TypeCheckProtocol.h"
#include "swift/AST/ASTVisitor.h"
#include "swift/AST/ASTWalker.h"
#include "swift/AST/ExistentialLayout.h"
@@ -558,6 +559,7 @@
FunctionRefKind functionRefKind,
AccessSemantics semantics) {
auto *decl = choice.getDecl();
+
// Determine the declaration selected for this overloaded reference.
auto &ctx = cs.getASTContext();
@@ -900,6 +902,7 @@
FunctionRefKind functionRefKind,
AccessSemantics semantics, bool isDynamic) {
ValueDecl *member = choice.getDecl();
+
auto &tc = cs.getTypeChecker();
auto &context = tc.Context;
@@ -4610,8 +4613,7 @@
// Mark any _ObjectiveCBridgeable conformances as 'used'.
if (result) {
- auto &tc = cs.getTypeChecker();
- tc.useObjectiveCBridgeableConformances(cs.DC, cs.getType(result));
+ useObjectiveCBridgeableConformances(cs.DC, cs.getType(result));
}
assert(expr == ExprStack.back());
diff --git a/lib/Sema/CSRanking.cpp b/lib/Sema/CSRanking.cpp
index 954f05f..46eb6c9 100644
--- a/lib/Sema/CSRanking.cpp
+++ b/lib/Sema/CSRanking.cpp
@@ -67,11 +67,7 @@
case SK_CollectionUpcastConversion:
log << "collection upcast conversion";
break;
-
- case SK_BindOptionalToArchetype:
- log << "bind optional to archetype";
- break;
-
+
case SK_ValueToOptional:
log << "value to optional";
break;
@@ -638,28 +634,6 @@
Type paramType1 = getAdjustedParamType(param1);
Type paramType2 = getAdjustedParamType(param2);
- // If we have:
- // param1Type = $T0?
- // param2Type = $T1
- // the subtype constraint check will always return true
- // since we'll attempt to bind $T1 as $T0?.
- //
- // What we're comparing here is foo<T>(_: T?) vs. foo<T>(_: T) and
- // we don't want to consider the optional-taking function to be the
- // the more specialized one since throughout the type system we
- // consider T to be a subtype of T?.
- SmallVector<Type, 2> optionals1;
- paramType1->lookThroughAllOptionalTypes(optionals1);
- auto numOptionals1 = optionals1.size();
-
- SmallVector<Type, 2> optionals2;
- Type objType2 = paramType2->lookThroughAllOptionalTypes(optionals2);
- auto numOptionals2 = optionals2.size();
-
- if (numOptionals1 > numOptionals2 &&
- (objType2->is<TypeVariableType>() || objType2->isAny()))
- return false;
-
// Check whether the first parameter is a subtype of the second.
cs.addConstraint(ConstraintKind::Subtype,
paramType1, paramType2, locator);
@@ -708,7 +682,10 @@
if (!knownNonSubtype) {
// Solve the system.
- if (cs.solveSingle(FreeTypeVariableBinding::Allow))
+ auto solution = cs.solveSingle(FreeTypeVariableBinding::Allow);
+
+ // Ban value-to-optional conversions.
+ if (solution && solution->getFixedScore().Data[SK_ValueToOptional] == 0)
return true;
}
@@ -775,6 +752,9 @@
auto foundRefinement1 = false;
auto foundRefinement2 = false;
+ bool isStdlibOptionalMPlusOperator1 = false;
+ bool isStdlibOptionalMPlusOperator2 = false;
+
auto getWeight = [&](ConstraintLocator *locator) -> unsigned {
if (auto *anchor = locator->getAnchor()) {
auto weight = weights.find(anchor);
@@ -980,6 +960,40 @@
foundRefinement2 = decl2InSubprotocol;
}
}
+
+ // FIXME: Lousy hack for ?? to prefer the catamorphism (flattening)
+ // over the mplus (non-flattening) overload if all else is equal.
+ if (decl1->getBaseName() == "??") {
+ assert(decl2->getBaseName() == "??");
+
+ auto check = [](const ValueDecl *VD) -> bool {
+ if (!VD->getModuleContext()->isStdlibModule())
+ return false;
+ auto fnTy = VD->getInterfaceType()->castTo<AnyFunctionType>();
+ if (!fnTy->getResult()->getOptionalObjectType())
+ return false;
+
+ // Check that the standard library hasn't added another overload of
+ // the ?? operator.
+ auto params = fnTy->getParams();
+ assert(params.size() == 2);
+
+ auto param1 = params[0].getType();
+ auto param2 = params[1].getType()->castTo<AnyFunctionType>();
+
+ assert(param1->getOptionalObjectType());
+ assert(param2->isAutoClosure());
+ assert(param2->getResult()->getOptionalObjectType());
+
+ (void) param1;
+ (void) param2;
+
+ return true;
+ };
+
+ isStdlibOptionalMPlusOperator1 = check(decl1);
+ isStdlibOptionalMPlusOperator2 = check(decl2);
+ }
}
// Compare the type variable bindings.
@@ -1095,6 +1109,14 @@
}
}
+ // FIXME: All other things being equal, prefer the catamorphism (flattening)
+ // overload of ?? over the mplus (non-flattening) overload.
+ if (score1 == score2) {
+ // This is correct: we want to /disprefer/ the mplus.
+ score2 += isStdlibOptionalMPlusOperator1;
+ score1 += isStdlibOptionalMPlusOperator2;
+ }
+
// FIXME: There are type variables and overloads not common to both solutions
// that haven't been considered. They make the systems different, but don't
// affect ranking. We need to handle this.
diff --git a/lib/Sema/CSSimplify.cpp b/lib/Sema/CSSimplify.cpp
index 33173e0..1c872de 100644
--- a/lib/Sema/CSSimplify.cpp
+++ b/lib/Sema/CSSimplify.cpp
@@ -683,9 +683,6 @@
}
}
- if (!argType->isAny())
- cs.increaseScore(ScoreKind::SK_EmptyExistentialConversion);
-
return cs.getTypeMatchSuccess();
}
@@ -1660,16 +1657,6 @@
auto *typeVar = typeVar1 ? typeVar1 : typeVar2;
auto type = typeVar1 ? type2 : type1;
- if (type->getOptionalObjectType()) {
- if (auto *typeVarLocator = typeVar->getImpl().getLocator()) {
- auto path = typeVarLocator->getPath();
- if (!path.empty() &&
- path.back().getKind() == ConstraintLocator::Archetype) {
- increaseScore(SK_BindOptionalToArchetype);
- }
- }
- }
-
return matchTypesBindTypeVar(typeVar, type, kind, flags, locator,
formUnsolvedResult);
}
diff --git a/lib/Sema/CodeSynthesis.cpp b/lib/Sema/CodeSynthesis.cpp
index abbd032..6d2a99a 100644
--- a/lib/Sema/CodeSynthesis.cpp
+++ b/lib/Sema/CodeSynthesis.cpp
@@ -218,10 +218,6 @@
if (storage->isStatic())
getter->setStatic();
- if (auto *overridden = storage->getOverriddenDecl())
- if (auto *overriddenAccessor = overridden->getGetter())
- getter->setOverriddenDecl(overriddenAccessor);
-
// Always add the getter to the context immediately after the storage.
addMemberToContextIfNeeded(getter, storage->getDeclContext(), storage);
@@ -274,14 +270,6 @@
if (isStatic)
setter->setStatic();
- if (auto *overridden = storage->getOverriddenDecl()) {
- auto *overriddenAccessor = overridden->getSetter();
- if (overriddenAccessor &&
- overridden->isSetterAccessibleFrom(storage->getDeclContext())) {
- setter->setOverriddenDecl(overriddenAccessor);
- }
- }
-
// Always add the setter to the context immediately after the getter.
if (!getter) getter = storage->getGetter();
assert(getter && "always synthesize setter prototype after getter");
@@ -428,14 +416,6 @@
if (storage->isFinal())
makeFinal(ctx, materializeForSet);
- if (auto *overridden = storage->getOverriddenDecl()) {
- auto *overriddenAccessor = overridden->getMaterializeForSetFunc();
- if (overriddenAccessor && !overriddenAccessor->hasForcedStaticDispatch() &&
- overridden->isSetterAccessibleFrom(storage->getDeclContext())) {
- materializeForSet->setOverriddenDecl(overriddenAccessor);
- }
- }
-
// If the storage is dynamic or ObjC-native, we can't add a dynamically-
// dispatched method entry for materializeForSet, so force it to be
// statically dispatched. ("final" would be inappropriate because the
@@ -2414,25 +2394,16 @@
ctor->getAttrs().add(new (ctx) OverrideAttr(/*IsImplicit=*/true));
ctor->setOverriddenDecl(superclassCtor);
- if (superclassCtor->isObjC()) {
- // Inherit the @objc name from the superclass initializer, if it
- // has one.
- if (auto objcAttr = superclassCtor->getAttrs().getAttribute<ObjCAttr>()) {
- if (objcAttr->hasName()) {
- auto *clonedAttr = objcAttr->clone(ctx);
- clonedAttr->setImplicit(true);
- ctor->getAttrs().add(clonedAttr);
- }
- }
-
- auto errorConvention = superclassCtor->getForeignErrorConvention();
- markAsObjC(tc, ctor, ObjCReason(ObjCReason::ImplicitlyObjC),
- errorConvention);
- }
if (superclassCtor->isRequired())
ctor->getAttrs().add(new (ctx) RequiredAttr(/*IsImplicit=*/true));
- if (superclassCtor->isDynamic())
- ctor->getAttrs().add(new (ctx) DynamicAttr(/*IsImplicit*/true));
+
+ // If the superclass constructor is @objc but the subclass constructor is
+ // not representable in Objective-C, add @nonobjc implicitly.
+ Optional<ForeignErrorConvention> errorConvention;
+ if (superclassCtor->isObjC() &&
+ !isRepresentableInObjC(ctor, ObjCReason::MemberOfObjCSubclass,
+ errorConvention))
+ ctor->getAttrs().add(new (ctx) NonObjCAttr(/*isImplicit=*/true));
}
ConstructorDecl *
diff --git a/lib/Sema/CodeSynthesis.h b/lib/Sema/CodeSynthesis.h
index ec9dba5..5d38391 100644
--- a/lib/Sema/CodeSynthesis.h
+++ b/lib/Sema/CodeSynthesis.h
@@ -95,10 +95,9 @@
// These are implemented in TypeCheckDecl.cpp.
void makeFinal(ASTContext &ctx, ValueDecl *D);
-void makeDynamic(ASTContext &ctx, ValueDecl *D);
// Implemented in TypeCheckerOverride.cpp
-bool checkOverrides(TypeChecker &TC, ValueDecl *decl);
+bool checkOverrides(ValueDecl *decl);
// These are implemented in CodeSynthesis.cpp.
void maybeAddMaterializeForSet(AbstractStorageDecl *storage,
diff --git a/lib/Sema/ConstraintSystem.h b/lib/Sema/ConstraintSystem.h
index f7605a7..a2a2434 100644
--- a/lib/Sema/ConstraintSystem.h
+++ b/lib/Sema/ConstraintSystem.h
@@ -456,8 +456,6 @@
SK_CollectionUpcastConversion,
/// A value-to-optional conversion.
SK_ValueToOptional,
- /// Instantiating a function with archetype T as an Optional value.
- SK_BindOptionalToArchetype,
/// A conversion to an empty existential type ('Any' or '{}').
SK_EmptyExistentialConversion,
/// A key path application subscript.
diff --git a/lib/Sema/TypeCheckAttr.cpp b/lib/Sema/TypeCheckAttr.cpp
index f21c4e6..687378d 100644
--- a/lib/Sema/TypeCheckAttr.cpp
+++ b/lib/Sema/TypeCheckAttr.cpp
@@ -355,11 +355,6 @@
}
void AttributeEarlyChecker::visitDynamicAttr(DynamicAttr *attr) {
- // Only instance members of classes can be dynamic.
- auto classDecl = D->getDeclContext()->getAsClassOrClassExtensionContext();
- if (!classDecl)
- diagnoseAndRemoveAttr(attr, diag::dynamic_not_in_class);
-
// Members cannot be both dynamic and final.
if (D->getAttrs().hasAttribute<FinalAttr>())
diagnoseAndRemoveAttr(attr, diag::dynamic_with_final);
@@ -1964,7 +1959,10 @@
// Symbols of dynamically-dispatched declarations are never referenced
// directly, so marking them as @usableFromInline does not make sense.
if (VD->isDynamic()) {
- diagnoseAndRemoveAttr(attr, diag::usable_from_inline_dynamic_not_supported);
+ if (attr->isImplicit())
+ attr->setInvalid();
+ else
+ diagnoseAndRemoveAttr(attr, diag::usable_from_inline_dynamic_not_supported);
return;
}
diff --git a/lib/Sema/TypeCheckDecl.cpp b/lib/Sema/TypeCheckDecl.cpp
index bf5c5b2..ee993b9 100644
--- a/lib/Sema/TypeCheckDecl.cpp
+++ b/lib/Sema/TypeCheckDecl.cpp
@@ -1117,12 +1117,6 @@
}
}
-void swift::makeDynamic(ASTContext &ctx, ValueDecl *D) {
- if (D && !D->isDynamic()) {
- D->getAttrs().add(new (ctx) DynamicAttr(/*IsImplicit=*/true));
- }
-}
-
namespace {
// The raw values of this enum must be kept in sync with
// diag::implicitly_final_cannot_be_open.
@@ -1222,61 +1216,108 @@
}
}
-/// If we need to infer 'dynamic', do so now.
+/// Try to make the given declaration 'dynamic', checking any semantic
+/// constraints before doing so.
///
-/// This occurs when
-/// - it is implied by an attribute like @NSManaged
-/// - when we have an override of an imported method
-/// - we need to dynamically dispatch to a method in an extension
-///
-/// FIXME: The latter reason is a hack. We should figure out how to safely
-/// put extension methods into the class vtable.
-static void inferDynamic(ASTContext &ctx, ValueDecl *D) {
+/// \returns true if it can be made dynamic, false otherwise.
+static bool makeDynamic(ValueDecl *decl) {
+ // Only members of classes can be dynamic.
+ auto classDecl = decl->getDeclContext()->getAsClassOrClassExtensionContext();
+ if (!classDecl) {
+ auto attr = decl->getAttrs().getAttribute<DynamicAttr>();
+ decl->diagnose(diag::dynamic_not_in_class)
+ .fixItRemove(attr ? SourceRange(attr->getLocation()) : SourceRange());
+ return false;
+ }
+
+ // 'dynamic' is only supported through the Objective-C runtime.
+ if (!decl->isObjC()) {
+ decl->diagnose(diag::dynamic_requires_objc,
+ decl->getDescriptiveKind(), decl->getFullName())
+ .fixItInsert(decl->getAttributeInsertionLoc(/*forModifier=*/false),
+ "@objc ");
+ return false;
+ }
+
+ // If there isn't already a 'dynamic' attribute, add an inferred one.
+ if (!decl->getAttrs().hasAttribute<DynamicAttr>()) {
+ auto attr = new (decl->getASTContext()) DynamicAttr(/*implicit=*/true);
+ decl->getAttrs().add(attr);
+ }
+
+ return true;
+}
+
+bool IsDynamicRequest::evaluate(Evaluator &evaluator, ValueDecl *decl) const {
// If we can't infer dynamic here, don't.
- if (!DeclAttribute::canAttributeAppearOnDecl(DAK_Dynamic, D))
- return;
+ if (!DeclAttribute::canAttributeAppearOnDecl(DAK_Dynamic, decl))
+ return false;
- // The presence of 'dynamic' blocks the inference of 'dynamic'.
- if (D->isDynamic())
- return;
+ // If 'dynamic' was explicitly specified, check it.
+ if (auto dynamicAttr = decl->getAttrs().getAttribute<DynamicAttr>()) {
+ return makeDynamic(decl);
+ }
- // Only 'objc' declarations use 'dynamic'.
- if (!D->isObjC() || D->hasClangNode())
- return;
+ // Runtime-replacable accessors are dynamic when their storage declaration
+ // is dynamic. Other accessors are never dynamic.
+ if (auto accessor = dyn_cast<AccessorDecl>(decl)) {
+ switch (accessor->getAccessorKind()) {
+ case AccessorKind::Get:
+ case AccessorKind::Set:
+ if (evaluator(IsDynamicRequest{accessor->getStorage()}))
+ return makeDynamic(decl);
- bool overridesImportedMethod =
- (D->getOverriddenDecl() &&
- D->getOverriddenDecl()->hasClangNode());
+ return false;
- bool overridesDyanmic =
- (D->getOverriddenDecl() &&
- D->getOverriddenDecl()->isDynamic());
+ case AccessorKind::Address:
+ case AccessorKind::DidSet:
+ case AccessorKind::MaterializeForSet:
+ case AccessorKind::MutableAddress:
+ case AccessorKind::WillSet:
+ return false;
+ }
+ }
- bool isNSManaged = D->getAttrs().hasAttribute<NSManagedAttr>();
-
- bool isExtension = isa<ExtensionDecl>(D->getDeclContext());
-
- // We only infer 'dynamic' in these three cases.
- if (!isExtension && !isNSManaged && !overridesImportedMethod &&
- !overridesDyanmic)
- return;
+ // The 'NSManaged' attribute implies 'dynamic'.
+ // FIXME: Use a semantic check for NSManaged rather than looking for the
+ // attribute (which could be ill-formed).
+ if (decl->getAttrs().hasAttribute<NSManagedAttr>()) {
+ return makeDynamic(decl);
+ }
// The presence of 'final' blocks the inference of 'dynamic'.
- if (D->isFinal() && !isNSManaged)
- return;
+ if (decl->isFinal())
+ return false;
- // Accessors should not infer 'dynamic' on their own; they can get it from
- // their storage decls.
- if (isa<AccessorDecl>(D))
- return;
+ // Types are never 'dynamic'.
+ if (isa<TypeDecl>(decl))
+ return false;
- // Only classes can use 'dynamic'.
- auto classDecl = D->getDeclContext()->getAsClassOrClassExtensionContext();
- if (!classDecl)
- return;
+ // A non-@objc entity is never 'dynamic'.
+ if (!decl->isObjC())
+ return false;
- // Add the 'dynamic' attribute.
- D->getAttrs().add(new (ctx) DynamicAttr(/*IsImplicit=*/true));
+ // @objc declarations in class extensions are implicitly dynamic.
+ // This is intended to enable overriding the declarations.
+ auto dc = decl->getDeclContext();
+ if (isa<ExtensionDecl>(dc) && dc->getAsClassOrClassExtensionContext()) {
+ return makeDynamic(decl);
+ }
+
+ // If any of the declarations overridden by this declaration are dynamic
+ // or were imported from Objective-C, this declaration is dynamic.
+ // Don't do this if the declaration is not exposed to Objective-C; that's
+ // currently the (only) manner in which one can make an override of a
+ // dynamic declaration non-dynamic.
+ for (auto overridden : evaluator(OverriddenDeclsRequest{decl})) {
+ if (overridden->isDynamic())
+ return makeDynamic(decl);
+
+ if (overridden->hasClangNode())
+ return makeDynamic(decl);
+ }
+
+ return false;
}
namespace {
@@ -2227,16 +2268,6 @@
// Add any mandatory accessors now.
maybeAddAccessorsToStorage(TC, storage);
- // We can't delay validation of getters and setters on @objc properties,
- // because if they never get validated at all then conformance checkers
- // will complain about selector mismatches.
- if (storage->isObjC()) {
- if (auto *getter = storage->getGetter())
- TC.validateDecl(getter);
- if (auto *setter = storage->getSetter())
- TC.validateDecl(setter);
- }
-
// Everything else about the accessors can wait until finalization.
// This will validate all the accessors.
TC.DeclsToFinalize.insert(storage);
@@ -2267,7 +2298,10 @@
if (auto VD = dyn_cast<ValueDecl>(decl)) {
checkRedeclaration(TC, VD);
-
+
+ (void)VD->isObjC();
+ (void)VD->isDynamic();
+
// If this is a member of a nominal type, don't allow it to have a name of
// "Type" or "Protocol" since we reserve the X.Type and X.Protocol
// expressions to mean something builtin to the language. We *do* allow
@@ -2382,7 +2416,7 @@
}
}
- if (!checkOverrides(TC, VD)) {
+ if (!checkOverrides(VD)) {
// If a property has an override attribute but does not override
// anything, complain.
auto overridden = VD->getOverriddenDecl();
@@ -2398,6 +2432,24 @@
TC.checkDeclAttributes(VD);
triggerAccessorSynthesis(TC, VD);
+
+ // Under the Swift 3 inference rules, if we have @IBInspectable or
+ // @GKInspectable but did not infer @objc, warn that the attribute is
+ if (!VD->isObjC() && TC.Context.LangOpts.EnableSwift3ObjCInference) {
+ if (auto attr = VD->getAttrs().getAttribute<IBInspectableAttr>()) {
+ TC.diagnose(attr->getLocation(),
+ diag::attribute_meaningless_when_nonobjc,
+ attr->getAttrName())
+ .fixItRemove(attr->getRange());
+ }
+
+ if (auto attr = VD->getAttrs().getAttribute<GKInspectableAttr>()) {
+ TC.diagnose(attr->getLocation(),
+ diag::attribute_meaningless_when_nonobjc,
+ attr->getAttrName())
+ .fixItRemove(attr->getRange());
+ }
+ }
}
@@ -2540,7 +2592,7 @@
AccessControlChecker::checkAccessControl(TC, SD);
UsableFromInlineChecker::checkUsableFromInline(TC, SD);
- if (!checkOverrides(TC, SD)) {
+ if (!checkOverrides(SD)) {
// If a subscript has an override attribute but does not override
// anything, complain.
if (auto *OA = SD->getAttrs().getAttribute<OverrideAttr>()) {
@@ -3042,7 +3094,7 @@
AccessControlChecker::checkAccessControl(TC, FD);
UsableFromInlineChecker::checkUsableFromInline(TC, FD);
- if (!checkOverrides(TC, FD)) {
+ if (!checkOverrides(FD)) {
// If a method has an 'override' keyword but does not
// override anything, complain.
if (auto *OA = FD->getAttrs().getAttribute<OverrideAttr>()) {
@@ -3183,7 +3235,7 @@
// Check whether this initializer overrides an initializer in its
// superclass.
- if (!checkOverrides(TC, CD)) {
+ if (!checkOverrides(CD)) {
// If an initializer has an override attribute but does not override
// anything or overrides something that doesn't need an 'override'
// keyword (e.g., a convenience initializer), complain.
@@ -3801,10 +3853,6 @@
validateAttributes(*this, D);
if (auto CD = dyn_cast<ClassDecl>(nominal)) {
- // Mark a class as @objc. This must happen before checking its members.
- Optional<ObjCReason> isObjC = shouldMarkAsObjC(*this, CD);
- markAsObjC(*this, CD, isObjC);
-
// Determine whether we require in-class initializers.
if (CD->getAttrs().hasAttribute<RequiresStoredPropertyInitsAttr>() ||
(CD->hasSuperclass() &&
@@ -3824,7 +3872,6 @@
if (auto *ED = dyn_cast<EnumDecl>(nominal)) {
// @objc enums use their raw values as the value representation, so we
// need to force the values to be checked.
- resolveIsObjC(ED);
if (ED->isObjC())
checkEnumRawValues(*this, ED);
}
@@ -3880,25 +3927,6 @@
validateAttributes(*this, D);
- // If the protocol is @objc, it may only refine other @objc protocols.
- // FIXME: Revisit this restriction.
- if (proto->getAttrs().hasAttribute<ObjCAttr>()) {
- Optional<ObjCReason> isObjC = ObjCReason(ObjCReason::ImplicitlyObjC);
-
- for (auto inherited : proto->getInheritedProtocols()) {
- if (!inherited->isObjC()) {
- diagnose(proto->getLoc(),
- diag::objc_protocol_inherits_non_objc_protocol,
- proto->getDeclaredType(), inherited->getDeclaredType());
- diagnose(inherited->getLoc(), diag::kind_identifier_declared_here,
- DescriptiveDeclKind::Protocol, inherited->getName());
- isObjC = None;
- }
- }
-
- markAsObjC(*this, proto, isObjC);
- }
-
// FIXME: IRGen likes to emit @objc protocol descriptors even if the
// protocol comes from a different module or translation unit.
//
@@ -3975,33 +4003,6 @@
// Properties need some special validation logic.
if (auto *nominalDecl = VD->getDeclContext()
->getAsNominalTypeOrNominalTypeExtensionContext()) {
- // If this is a property, check if it needs to be exposed to
- // Objective-C.
- Optional<ObjCReason> isObjC = shouldMarkAsObjC(*this, VD);
-
- if (isObjC && !swift::isRepresentableInObjC(VD, *isObjC))
- isObjC = None;
-
- markAsObjC(*this, VD, isObjC);
-
- // Under the Swift 3 inference rules, if we have @IBInspectable or
- // @GKInspectable but did not infer @objc, warn that the attribute is
- if (!isObjC && Context.LangOpts.EnableSwift3ObjCInference) {
- if (auto attr = VD->getAttrs().getAttribute<IBInspectableAttr>()) {
- diagnose(attr->getLocation(),
- diag::attribute_meaningless_when_nonobjc,
- attr->getAttrName())
- .fixItRemove(attr->getRange());
- }
-
- if (auto attr = VD->getAttrs().getAttribute<GKInspectableAttr>()) {
- diagnose(attr->getLocation(),
- diag::attribute_meaningless_when_nonobjc,
- attr->getAttrName())
- .fixItRemove(attr->getRange());
- }
- }
-
// If this variable is a class member, mark it final if the
// class is final, or if it was declared with 'let'.
auto staticSpelling =
@@ -4021,9 +4022,6 @@
fixItAccess(inFlightDiag, D, AccessLevel::Public);
}
}
-
- // Infer 'dynamic' after 'final' but before touching accessors.
- inferDynamic(Context, VD);
}
// Perform accessor-related validation.
@@ -4206,16 +4204,8 @@
if (FD->isOperator())
checkMemberOperator(*this, FD);
- Optional<ObjCReason> isObjC = shouldMarkAsObjC(*this, FD);
auto accessor = dyn_cast<AccessorDecl>(FD);
- auto *protocolContext = dyn_cast<ProtocolDecl>(
- FD->getDeclContext());
- if (protocolContext && accessor) {
- if (isObjC)
- isObjC = ObjCReason::Accessor;
- }
-
if (accessor && accessor->isGetterOrSetter()) {
// If the property decl is an instance property, its accessors will
// be instance methods and the above condition will mark them ObjC.
@@ -4224,48 +4214,12 @@
AbstractStorageDecl *storage = accessor->getStorage();
- if (storage->getAttrs().hasAttribute<NonObjCAttr>())
- isObjC = None;
- else if (storage->isObjC()) {
- if (!isObjC) {
- // Make this accessor @objc because its property is @objc.
- isObjC = ObjCReason::Accessor;
- } else if (auto storageObjCAttr =
- storage->getAttrs().getAttribute<ObjCAttr>()) {
- // If @objc on the storage declaration was inferred using a
- // deprecated rule, but this accessor is @objc in its own right,
- // complain.
- ;
- if (storageObjCAttr && storageObjCAttr->isSwift3Inferred() &&
- shouldDiagnoseObjCReason(*isObjC, Context)) {
- diagnose(storage, diag::accessor_swift3_objc_inference,
- storage->getDescriptiveKind(), storage->getFullName(),
- isa<SubscriptDecl>(storage), accessor->isSetter())
- .fixItInsert(storage->getAttributeInsertionLoc(
- /*forModifier=*/false),
- "@objc ");
- }
- }
- }
-
- // If the storage is dynamic or final, propagate to this accessor.
- if (isObjC &&
- storage->isDynamic())
- makeDynamic(Context, FD);
-
+ // If the storage is final, propagate to this accessor.
if (storage->isFinal())
makeFinal(Context, FD);
}
- Optional<ForeignErrorConvention> errorConvention;
- if (isObjC &&
- (FD->isInvalid() || !isRepresentableInObjC(FD, *isObjC,
- errorConvention)))
- isObjC = None;
- markAsObjC(*this, FD, isObjC, errorConvention);
-
inferFinalAndDiagnoseIfNeeded(*this, FD, FD->getStaticSpelling());
- inferDynamic(Context, FD);
}
// If the function is exported to C, it must be representable in (Obj-)C.
@@ -4354,22 +4308,6 @@
validateAttributes(*this, CD);
- // An initializer is ObjC-compatible if it's explicitly @objc or a member
- // of an ObjC-compatible class.
- if (CD->getDeclContext()->isTypeContext()) {
- Optional<ObjCReason> isObjC = shouldMarkAsObjC(*this, CD,
- /*allowImplicit=*/true);
-
- Optional<ForeignErrorConvention> errorConvention;
- if (isObjC &&
- (CD->isInvalid() ||
- !isRepresentableInObjC(CD, *isObjC, errorConvention)))
- isObjC = None;
- markAsObjC(*this, CD, isObjC, errorConvention);
- }
-
- inferDynamic(Context, CD);
-
if (CD->getFailability() == OTK_ImplicitlyUnwrappedOptional) {
auto &C = CD->getASTContext();
CD->getAttrs().add(
@@ -4405,16 +4343,7 @@
DD->setSignatureIsValidated();
- // Do this before markAsObjC() to diagnose @nonobjc better
validateAttributes(*this, DD);
-
- // Destructors are always @objc, because their Objective-C entry point is
- // -dealloc.
- if (Context.LangOpts.EnableObjCInterop)
- markAsObjC(*this, DD, ObjCReason(ObjCReason::ImplicitlyObjC));
- else
- DD->setIsObjC(false);
-
break;
}
@@ -4443,17 +4372,6 @@
if (SD->getDeclContext()->isTypeContext()) {
// If this is a class member, mark it final if the class is final.
inferFinalAndDiagnoseIfNeeded(*this, SD, StaticSpellingKind::None);
-
- // A subscript is ObjC-compatible if it's explicitly @objc, or a
- // member of an ObjC-compatible class or protocol.
- Optional<ObjCReason> isObjC = shouldMarkAsObjC(*this, SD);
-
- if (isObjC && !swift::isRepresentableInObjC(SD, *isObjC))
- isObjC = None;
- markAsObjC(*this, SD, isObjC);
-
- // Infer 'dynamic' before touching accessors.
- inferDynamic(Context, SD);
}
// Perform accessor-related validation.
@@ -4673,6 +4591,28 @@
requestNominalLayout(classDecl);
if (auto *protocolDecl = dyn_cast<ProtocolDecl>(dc))
requestNominalLayout(protocolDecl);
+
+ // Compute overrides.
+ (void)member->getOverriddenDecls();
+
+ // Check whether the member is @objc or dynamic.
+ (void)member->isObjC();
+ (void)member->isDynamic();
+
+ // If this represents (abstract) storage, form the appropriate accessors.
+ if (auto storage = dyn_cast<AbstractStorageDecl>(member)) {
+ validateAbstractStorageDecl(*this, storage);
+
+ // Request layout of the accessors for an @objc declaration.
+ // We can't delay validation of getters and setters on @objc properties,
+ // because if they never get validated at all then conformance checkers
+ // will complain about selector mismatches.
+ if (storage->isObjC()) {
+ for (auto accessor : storage->getAllAccessors()) {
+ requestMemberLayout(accessor);
+ }
+ }
+ }
}
void TypeChecker::requestNominalLayout(NominalTypeDecl *nominalDecl) {
@@ -4708,6 +4648,8 @@
TC.validateDecl(VD);
+ TC.requestMemberLayout(VD);
+
// The only thing left to do is synthesize storage for lazy variables.
auto *prop = dyn_cast<VarDecl>(D);
if (!prop)
diff --git a/lib/Sema/TypeCheckDeclObjC.cpp b/lib/Sema/TypeCheckDeclObjC.cpp
index c8b6b6a..3b545a8 100644
--- a/lib/Sema/TypeCheckDeclObjC.cpp
+++ b/lib/Sema/TypeCheckDeclObjC.cpp
@@ -16,11 +16,13 @@
//===----------------------------------------------------------------------===//
#include "TypeCheckObjC.h"
#include "TypeChecker.h"
+#include "TypeCheckProtocol.h"
#include "swift/AST/ASTContext.h"
#include "swift/AST/Decl.h"
#include "swift/AST/ExistentialLayout.h"
#include "swift/AST/ForeignErrorConvention.h"
#include "swift/AST/ParameterList.h"
+#include "swift/AST/TypeCheckRequests.h"
#include "swift/Basic/StringExtras.h"
using namespace swift;
@@ -232,6 +234,11 @@
ASTContext &ctx = AFD->getASTContext();
auto &diags = ctx.Diags;
+ if (!AFD->hasInterfaceType()) {
+ ctx.getLazyResolver()->resolveDeclSignature(
+ const_cast<AbstractFunctionDecl *>(AFD));
+ }
+
bool Diagnose = shouldDiagnoseObjCReason(Reason, ctx);
bool IsObjC = true;
unsigned NumParams = PL->size();
@@ -262,6 +269,9 @@
return false;
}
+ if (param->getType()->hasError())
+ return false;
+
if (param->getType()->isRepresentableIn(
ForeignLanguage::ObjectiveC,
const_cast<AbstractFunctionDecl *>(AFD)))
@@ -434,7 +444,8 @@
// Global computed properties may however @_cdecl their accessors.
auto storage = accessor->getStorage();
if (!storage->isObjC() && Reason != ObjCReason::ExplicitlyCDecl &&
- Reason != ObjCReason::WitnessToObjC) {
+ Reason != ObjCReason::WitnessToObjC &&
+ Reason != ObjCReason::MemberOfObjCProtocol) {
if (Diagnose) {
auto error = accessor->isGetter()
? (isa<VarDecl>(storage)
@@ -498,10 +509,7 @@
!isParamListRepresentableInObjC(AFD,
AFD->getParameterLists().back(),
Reason)) {
- if (!Diagnose) {
- // Return as soon as possible if we are not producing diagnostics.
- return false;
- }
+ return false;
}
if (auto FD = dyn_cast<FuncDecl>(AFD)) {
@@ -742,6 +750,11 @@
if (VD->isInvalid())
return false;
+ if (!VD->hasInterfaceType()) {
+ VD->getASTContext().getLazyResolver()->resolveDeclSignature(
+ const_cast<VarDecl *>(VD));
+ }
+
Type T = VD->getDeclContext()->mapTypeIntoContext(VD->getInterfaceType());
if (auto *RST = T->getAs<ReferenceStorageType>()) {
// In-memory layout of @weak and @unowned does not correspond to anything
@@ -787,6 +800,11 @@
if (checkObjCInForeignClassContext(SD, Reason))
return false;
+ if (!SD->hasInterfaceType()) {
+ SD->getASTContext().getLazyResolver()->resolveDeclSignature(
+ const_cast<SubscriptDecl *>(SD));
+ }
+
// Figure out the type of the indices.
Type IndicesType = SD->getIndicesInterfaceType()->getWithoutImmediateLabel();
@@ -1010,13 +1028,19 @@
}
/// Figure out if a declaration should be exported to Objective-C.
-Optional<ObjCReason> swift::shouldMarkAsObjC(TypeChecker &TC,
- const ValueDecl *VD,
- bool allowImplicit) {
+Optional<ObjCReason> shouldMarkAsObjC(const ValueDecl *VD, bool allowImplicit) {
+ // If Objective-C interoperability is disabled, nothing gets marked as @objc.
+ if (!VD->getASTContext().LangOpts.EnableObjCInterop)
+ return None;
+
if (auto classDecl = dyn_cast<ClassDecl>(VD)) {
return shouldMarkClassAsObjC(classDecl);
}
+ // Destructors are always @objc, with -dealloc as their entry point.
+ if (auto deinit = dyn_cast<DestructorDecl>(VD))
+ return ObjCReason(ObjCReason::ImplicitlyObjC);
+
ProtocolDecl *protocolContext =
dyn_cast<ProtocolDecl>(VD->getDeclContext());
bool isMemberOfObjCProtocol =
@@ -1042,6 +1066,16 @@
// explicitly declared @objc.
if (VD->getAttrs().hasAttribute<ObjCAttr>())
return ObjCReason(ObjCReason::ExplicitlyObjC);
+ // Getter or setter for an @objc property or subscript.
+ if (auto accessor = dyn_cast<AccessorDecl>(VD)) {
+ if (accessor->getAccessorKind() == AccessorKind::Get ||
+ accessor->getAccessorKind() == AccessorKind::Set) {
+ if (accessor->getStorage()->isObjC())
+ return ObjCReason(ObjCReason::Accessor);
+
+ return None;
+ }
+ }
// @IBOutlet, @IBAction, @NSManaged, and @GKInspectable imply @objc.
//
// @IBInspectable and @GKInspectable imply @objc quietly in Swift 3
@@ -1076,23 +1110,18 @@
// A witness to an @objc protocol requirement is implicitly @objc.
if (VD->getDeclContext()->getAsClassOrClassExtensionContext()) {
auto requirements =
- TC.findWitnessedObjCRequirements(VD, /*anySingleRequirement=*/true);
+ findWitnessedObjCRequirements(VD, /*anySingleRequirement=*/true);
if (!requirements.empty())
return ObjCReason::witnessToObjC(requirements.front());
}
ASTContext &ctx = VD->getASTContext();
- // Infer '@objc' for 'dynamic' members.
+ // Under Swift 3's @objc inference rules, 'dynamic' infers '@objc'.
if (auto attr = VD->getAttrs().getAttribute<DynamicAttr>()) {
- // For implicit 'dynamic', just infer '@objc' implicitly.
- if (attr->isImplicit())
- return ObjCReason(ObjCReason::ImplicitlyObjC);
-
bool isGetterOrSetter =
isa<AccessorDecl>(VD) && cast<AccessorDecl>(VD)->isGetterOrSetter();
- // Under Swift 3's @objc inference rules, 'dynamic' infers '@objc'.
if (ctx.LangOpts.EnableSwift3ObjCInference) {
// If we've been asked to warn about deprecated @objc inference, do so
// now.
@@ -1112,10 +1141,8 @@
// anyway for better recovery.
VD->diagnose(diag::dynamic_requires_objc,
VD->getDescriptiveKind(), VD->getFullName())
- .highlight(attr->getRange())
.fixItInsert(VD->getAttributeInsertionLoc(/*forModifier=*/false),
- "@objc ");
-
+ "@objc ");
return ObjCReason(ObjCReason::ImplicitlyObjC);
}
@@ -1140,8 +1167,7 @@
return None;
if (classDecl->checkObjCAncestry() != ObjCClassKind::NonObjC) {
- return VD->isImplicit() ? ObjCReason(ObjCReason::ImplicitlyObjC)
- : ObjCReason(ObjCReason::MemberOfObjCSubclass);
+ return ObjCReason(ObjCReason::MemberOfObjCSubclass);
}
}
@@ -1223,47 +1249,118 @@
return true;
}
-void TypeChecker::resolveIsObjC(ValueDecl *VD) {
+/// Record that a declaration is @objc.
+static void markAsObjC(ValueDecl *D, ObjCReason reason,
+ Optional<ForeignErrorConvention> errorConvention);
+
+
+bool IsObjCRequest::evaluate(Evaluator &evaluator, ValueDecl *VD) const {
auto dc = VD->getDeclContext();
- if (dc->getAsClassOrClassExtensionContext()) {
+ Optional<ObjCReason> isObjC;
+ if (dc->getAsClassOrClassExtensionContext() && !isa<TypeDecl>(VD)) {
// Members of classes can be @objc.
+ isObjC = shouldMarkAsObjC(VD, isa<ConstructorDecl>(VD));
}
else if (isa<ClassDecl>(VD)) {
// Classes can be @objc.
// Protocols and enums can also be @objc, but this is covered by the
- // isObjC() check at the beginning.
+ // isObjC() check a the beginning.;
+ isObjC = shouldMarkAsObjC(VD, /*allowImplicit=*/false);
} else if (auto enumDecl = dyn_cast<EnumDecl>(VD)) {
// Enums can be @objc so long as they have a raw type that is representable
// as an arithmetic type in C.
- auto isObjC = isEnumObjC(enumDecl);
- VD->setIsObjC(isObjC);
- if (!isObjC) {
- if (auto objcAttr = enumDecl->getAttrs().getAttribute<ObjCAttr>()) {
- objcAttr->setInvalid();
+ if (isEnumObjC(enumDecl))
+ isObjC = ObjCReason(ObjCReason::ExplicitlyObjC);
+ } else if (auto proto = dyn_cast<ProtocolDecl>(VD)) {
+ if (proto->getAttrs().hasAttribute<ObjCAttr>()) {
+ isObjC = ObjCReason(ObjCReason::ExplicitlyObjC);
+
+ // If the protocol is @objc, it may only refine other @objc protocols.
+ // FIXME: Revisit this restriction.
+ for (auto inherited : proto->getInheritedProtocols()) {
+ if (!inherited->isObjC()) {
+ proto->diagnose(diag::objc_protocol_inherits_non_objc_protocol,
+ proto->getDeclaredType(),
+ inherited->getDeclaredType());
+ inherited->diagnose(diag::kind_identifier_declared_here,
+ DescriptiveDeclKind::Protocol,
+ inherited->getName());
+ isObjC = None;
+ }
}
}
} else if (isa<ProtocolDecl>(dc) && cast<ProtocolDecl>(dc)->isObjC()) {
// Members of @objc protocols are @objc.
+ isObjC = shouldMarkAsObjC(VD, isa<ConstructorDecl>(VD));
} else {
- // Cannot be @objc; do nothing.
- return;
+ // Cannot be @objc.
}
- // Short-circuit this operation if we already know that the entity is @objc.
- if (VD->isObjC()) return;
+ // Perform some icky stateful hackery to mark this declaration as
+ // not being @objc.
+ auto makeNotObjC = [&] {
+ if (auto objcAttr = VD->getAttrs().getAttribute<ObjCAttr>()) {
+ objcAttr->setInvalid();
+ }
+ };
+ // If this declaration should not be exposed to Objective-C, we're done.
+ if (!isObjC) {
+ makeNotObjC();
+ return false;
+ }
- // FIXME: Narrow this computation to just the @objc bits.
- validateDeclForNameLookup(VD);
+ if (auto accessor = dyn_cast<AccessorDecl>(VD)) {
+ auto storage = accessor->getStorage();
+ if (auto storageObjCAttr = storage->getAttrs().getAttribute<ObjCAttr>()) {
+ // If @objc on the storage declaration was inferred using a
+ // deprecated rule, but this accessor is @objc in its own right,
+ // complain.
+ ASTContext &ctx = dc->getASTContext();
+ if (storageObjCAttr && storageObjCAttr->isSwift3Inferred() &&
+ shouldDiagnoseObjCReason(*isObjC, ctx)) {
+ storage->diagnose(diag::accessor_swift3_objc_inference,
+ storage->getDescriptiveKind(), storage->getFullName(),
+ isa<SubscriptDecl>(storage), accessor->isSetter())
+ .fixItInsert(storage->getAttributeInsertionLoc(/*forModifier=*/false),
+ "@objc ");
+ }
+ }
+ }
+
+ // If needed, check whether this declaration is representable in Objective-C.
+ Optional<ForeignErrorConvention> errorConvention;
+ if (auto var = dyn_cast<VarDecl>(VD)) {
+ if (!isRepresentableInObjC(var, *isObjC)) {
+ makeNotObjC();
+ return false;
+ }
+ } else if (auto subscript = dyn_cast<SubscriptDecl>(VD)) {
+ if (!isRepresentableInObjC(subscript, *isObjC)) {
+ makeNotObjC();
+ return false;
+ }
+ } else if (isa<DestructorDecl>(VD)) {
+ // Destructors need no additional checking.
+ } else if (auto func = dyn_cast<AbstractFunctionDecl>(VD)) {
+ if (!isRepresentableInObjC(func, *isObjC, errorConvention)) {
+ makeNotObjC();
+ return false;
+ }
+ }
+
+ // Note that this declaration is exposed to Objective-C.
+ markAsObjC(VD, *isObjC, errorConvention);
+
+ return true;
}
/// Infer the Objective-C name for a given declaration.
-static void inferObjCName(TypeChecker &tc, ValueDecl *decl) {
+static void inferObjCName(ValueDecl *decl) {
if (isa<DestructorDecl>(decl))
return;
- assert(decl->isObjC() && "Must be known to be @objc");
auto attr = decl->getAttrs().getAttribute<ObjCAttr>();
/// Set the @objc name.
@@ -1356,7 +1453,7 @@
// requirements for which this declaration is a witness.
Optional<ObjCSelector> requirementObjCName;
ValueDecl *firstReq = nullptr;
- for (auto req : tc.findWitnessedObjCRequirements(decl)) {
+ for (auto req : findWitnessedObjCRequirements(decl)) {
// If this is the first requirement, take its name.
if (!requirementObjCName) {
requirementObjCName = req->getObjCRuntimeName();
@@ -1402,35 +1499,31 @@
///
/// If the declaration has a @nonobjc attribute, diagnose an error
/// using the given Reason, if present.
-void swift::markAsObjC(TypeChecker &TC, ValueDecl *D,
- Optional<ObjCReason> isObjC,
- Optional<ForeignErrorConvention> errorConvention) {
- D->setIsObjC(isObjC.hasValue());
-
- if (!isObjC) {
- // FIXME: For now, only @objc declarations can be dynamic.
- if (auto attr = D->getAttrs().getAttribute<DynamicAttr>())
- attr->setInvalid();
- return;
- }
-
+void markAsObjC(ValueDecl *D, ObjCReason reason,
+ Optional<ForeignErrorConvention> errorConvention) {
ASTContext &ctx = D->getASTContext();
// By now, the caller will have handled the case where an implicit @objc
// could be overridden by @nonobjc. If we see a @nonobjc and we are trying
// to add an @objc for whatever reason, diagnose an error.
if (auto *attr = D->getAttrs().getAttribute<NonObjCAttr>()) {
- if (!shouldDiagnoseObjCReason(*isObjC, ctx))
- isObjC = ObjCReason::ImplicitlyObjC;
+ if (!shouldDiagnoseObjCReason(reason, ctx))
+ reason = ObjCReason::ImplicitlyObjC;
D->diagnose(diag::nonobjc_not_allowed,
- getObjCDiagnosticAttrKind(*isObjC));
+ getObjCDiagnosticAttrKind(reason));
attr->setInvalid();
}
- TC.useObjectiveCBridgeableConformances(D->getInnermostDeclContext(),
- D->getInterfaceType());
+ if (!D->hasInterfaceType()) {
+ ctx.getLazyResolver()->resolveDeclSignature(D);
+ }
+
+ if (!isa<AccessorDecl>(D)) {
+ useObjectiveCBridgeableConformances(D->getInnermostDeclContext(),
+ D->getInterfaceType());
+ }
// Record the name of this Objective-C method in its class.
if (auto classDecl
@@ -1458,7 +1551,7 @@
}
// Infer the Objective-C name for this method.
- inferObjCName(TC, method);
+ inferObjCName(method);
// ... then record it.
classDecl->recordObjCMethod(method);
@@ -1500,7 +1593,7 @@
}
} else if (isa<VarDecl>(D)) {
// Infer the Objective-C name for this property.
- inferObjCName(TC, D);
+ inferObjCName(D);
}
} else if (auto method = dyn_cast<AbstractFunctionDecl>(D)) {
if (method->hasThrows()) {
@@ -1520,7 +1613,7 @@
// Special handling for Swift 3 @objc inference rules that are no longer
// present in later versions of Swift.
- if (*isObjC == ObjCReason::MemberOfObjCSubclass) {
+ if (reason == ObjCReason::MemberOfObjCSubclass) {
// If we've been asked to unconditionally warn about these deprecated
// @objc inference rules, do so now. However, we don't warn about
// accessors---just the main storage declarations.
diff --git a/lib/Sema/TypeCheckDeclOverride.cpp b/lib/Sema/TypeCheckDeclOverride.cpp
index 3bede61..ac1ed80 100644
--- a/lib/Sema/TypeCheckDeclOverride.cpp
+++ b/lib/Sema/TypeCheckDeclOverride.cpp
@@ -21,6 +21,7 @@
#include "swift/AST/Availability.h"
#include "swift/AST/Decl.h"
#include "swift/AST/ParameterList.h"
+#include "swift/AST/TypeCheckRequests.h"
using namespace swift;
static void adjustFunctionTypeForOverride(Type &type) {
@@ -356,8 +357,7 @@
/// \c overridden declaration.
///
/// \returns true if an error occurred.
-static bool recordOverride(TypeChecker &TC, ValueDecl *override,
- ValueDecl *base, bool isKnownObjC = false);
+static bool checkSingleOverride(ValueDecl *override, ValueDecl *base);
/// If the difference between the types of \p decl and \p base is something
/// we feel confident about fixing (even partially), emit a note with fix-its
@@ -536,7 +536,6 @@
/// Class that handles the checking of a particular declaration against
/// superclass entities that it could override.
class OverrideMatcher {
- TypeChecker &tc;
ASTContext &ctx;
ValueDecl *decl;
@@ -553,7 +552,7 @@
Type cachedDeclType;
public:
- OverrideMatcher(TypeChecker &tc, ValueDecl *decl);
+ OverrideMatcher(ValueDecl *decl);
/// Returns true when it's possible to perform any override matching.
explicit operator bool() const {
@@ -582,8 +581,8 @@
};
}
-OverrideMatcher::OverrideMatcher(TypeChecker &tc, ValueDecl *decl)
- : tc(tc), ctx(decl->getASTContext()), decl(decl) {
+OverrideMatcher::OverrideMatcher(ValueDecl *decl)
+ : ctx(decl->getASTContext()), decl(decl) {
// The final step for this constructor is to set up the superclass type,
// without which we will not perform an matching. Early exits therefore imply
// that there is no way we can match this declaration.
@@ -644,7 +643,8 @@
lookupOptions -= NameLookupFlags::PerformConformanceCheck;
membersName = name;
- members = tc.lookupMember(dc, superclass, membersName, lookupOptions);
+ members = TypeChecker::lookupMember(dc, superclass, membersName,
+ lookupOptions);
}
// Check each member we found.
@@ -783,6 +783,8 @@
diags.diagnose(baseDecl, diag::overridden_here);
}
+ bool isAccessor = isa<AccessorDecl>(decl);
+
// Check that the override has the required access level.
// Overrides have to be at least as accessible as what they
// override, except:
@@ -793,7 +795,8 @@
// never really "overridden" in the intended sense here, because of
// course derived classes will change how the class is initialized.
AccessLevel matchAccess = baseDecl->getFormalAccess(dc);
- if (matchAccess < AccessLevel::Open &&
+ if (!isAccessor &&
+ matchAccess < AccessLevel::Open &&
baseDecl->getModuleContext() != decl->getModuleContext() &&
!isa<ConstructorDecl>(decl)) {
diags.diagnose(decl, diag::override_of_non_open,
@@ -955,21 +958,35 @@
}
}
+ if (emittedMatchError)
+ return true;
+
// Catch-all to make sure we don't silently accept something we shouldn't.
- if (attempt != OverrideCheckingAttempt::PerfectMatch &&
- !emittedMatchError) {
+ if (attempt != OverrideCheckingAttempt::PerfectMatch) {
OverrideMatch match{decl, /*isExact=*/false, declTy};
diagnoseGeneralOverrideFailure(decl, match, attempt);
}
- return recordOverride(tc, decl, baseDecl);
+ return checkSingleOverride(decl, baseDecl);
+}
+
+// Invalidate an existing "override" attribute or add a new invalid "override"
+// attribute, which will suppress additional checking.
+static void invalidateOverrideAttribute(ValueDecl *decl) {
+ auto overrideAttr = decl->getAttrs().getAttribute<OverrideAttr>(true);
+ if (!overrideAttr) {
+ overrideAttr = new (decl->getASTContext()) OverrideAttr(true);
+ decl->getAttrs().add(overrideAttr);
+ }
+
+ overrideAttr->setInvalid();
}
/// Determine which method or subscript this method or subscript overrides
/// (if any).
///
/// \returns true if an error occurred.
-bool swift::checkOverrides(TypeChecker &TC, ValueDecl *decl) {
+bool swift::checkOverrides(ValueDecl *decl) {
// If we already computed overridden declarations and either succeeded
// or invalidated the attribute, there's nothing more to do.
if (decl->overriddenDeclsComputed()) {
@@ -986,16 +1003,16 @@
// Otherwise, we have more checking to do.
}
- // Set up matching, but bail out if there's nothing to match.
- OverrideMatcher matcher(TC, decl);
- if (!matcher) return false;
-
- // Ignore accessor methods (e.g. getters and setters), they will be handled
- // when their storage decl is processed.
- // FIXME: We should pull information from the storage declaration, but
- // that will be handled at a different point.
- if (isa<AccessorDecl>(decl))
+ // Accessor methods get overrides through their storage declaration, and
+ // all checking can be performed via that mechanism.
+ if (isa<AccessorDecl>(decl)) {
+ (void)decl->getOverriddenDecls();
return false;
+ }
+
+ // Set up matching, but bail out if there's nothing to match.
+ OverrideMatcher matcher(decl);
+ if (!matcher) return false;
// Look for members with the same name and matching types as this
// one.
@@ -1042,11 +1059,24 @@
// If we override more than one declaration, complain.
if (matches.size() > 1) {
diagnoseGeneralOverrideFailure(decl, matches, attempt);
+ invalidateOverrideAttribute(decl);
return true;
}
- // If we have a single match (exact or not), take it.
- return matcher.checkOverride(matches.front().Decl, attempt);
+ // Check the single match. If it's ill-formed, invalidate the override
+ // attribute so we don't try again.
+ if (matcher.checkOverride(matches.front().Decl, attempt)) {
+ invalidateOverrideAttribute(decl);
+ return true;
+ }
+
+ // FIXME: Check for missing 'override' keyword here?
+
+ // We performed override checking, so record the override.
+ // FIXME: It's weird to be pushing state here, but how do we say that
+ // this check subsumes the normal 'override' check?
+ decl->setOverriddenDecl(matches.front().Decl);
+ return false;
}
namespace {
@@ -1078,6 +1108,7 @@
UNINTERESTING_ATTR(Alignment)
UNINTERESTING_ATTR(CDecl)
UNINTERESTING_ATTR(Consuming)
+ UNINTERESTING_ATTR(Dynamic)
UNINTERESTING_ATTR(DynamicMemberLookup)
UNINTERESTING_ATTR(SILGenName)
UNINTERESTING_ATTR(Exported)
@@ -1092,6 +1123,7 @@
UNINTERESTING_ATTR(Optimize)
UNINTERESTING_ATTR(Inlinable)
UNINTERESTING_ATTR(Effects)
+ UNINTERESTING_ATTR(Final)
UNINTERESTING_ATTR(FixedLayout)
UNINTERESTING_ATTR(Lazy)
UNINTERESTING_ATTR(LLDBDebuggerFunction)
@@ -1162,46 +1194,6 @@
}
}
- void visitFinalAttr(FinalAttr *attr) {
- // If this is an accessor, don't complain if we would have
- // complained about the storage declaration.
- if (auto accessor = dyn_cast<AccessorDecl>(Override)) {
- if (auto storageDecl = accessor->getStorage()) {
- if (storageDecl->getOverriddenDecl() &&
- storageDecl->getOverriddenDecl()->isFinal())
- return;
- }
- }
-
- // FIXME: Customize message to the kind of thing.
- auto baseKind = Base->getDescriptiveKind();
- switch (baseKind) {
- case DescriptiveDeclKind::StaticLet:
- case DescriptiveDeclKind::StaticVar:
- case DescriptiveDeclKind::StaticMethod:
- Diags.diagnose(Override, diag::override_static, baseKind);
- break;
- default:
- Diags.diagnose(Override, diag::override_final,
- Override->getDescriptiveKind(), baseKind);
- break;
- }
-
- Diags.diagnose(Base, diag::overridden_here);
- }
-
- void visitDynamicAttr(DynamicAttr *attr) {
- // Final overrides are not dynamic.
- if (Override->isFinal())
- return;
-
- // Must be @objc to be 'dynamic'.
- if (!Override->isObjC())
- return;
-
- makeDynamic(Override->getASTContext(), Override);
- }
-
void visitObjCAttr(ObjCAttr *attr) {
// Checking for overrides of declarations that are implicitly @objc
// and occur in class extensions, because overriding will no longer be
@@ -1246,6 +1238,9 @@
return ctor->isDesignatedInit() && !ctor->isRequired();
}
+ if (isa<AccessorDecl>(overridden))
+ return false;
+
return true;
}
@@ -1343,9 +1338,10 @@
return true;
}
-static bool recordOverride(TypeChecker &TC, ValueDecl *override,
- ValueDecl *base, bool isKnownObjC) {
+static bool checkSingleOverride(ValueDecl *override, ValueDecl *base) {
// This can happen with circular inheritance.
+ // FIXME: This shouldn't be possible once name lookup goes through the
+ // request-evaluator.
if (override == base)
return true;
@@ -1357,7 +1353,8 @@
auto *overrideASD = cast<AbstractStorageDecl>(override);
// Make sure that the overriding property doesn't have storage.
- if (overrideASD->hasStorage() &&
+ if ((overrideASD->hasStorage() ||
+ overrideASD->getAttrs().hasAttribute<LazyAttr>()) &&
!(overrideASD->getWillSetFunc() || overrideASD->getDidSetFunc())) {
bool downgradeToWarning = false;
if (!ctx.isSwiftVersionAtLeast(5) &&
@@ -1417,11 +1414,17 @@
}
}
+ // Various properties are only checked for the storage declarations
+ // and not for the individual accessors. Otherwise, we end up with
+ // duplicated diagnostics.
+ bool isAccessor = isa<AccessorDecl>(override);
+
// Non-Objective-C declarations in extensions cannot override or
// be overridden.
- if ((base->getDeclContext()->isExtensionContext() ||
+ if (!isAccessor &&
+ (base->getDeclContext()->isExtensionContext() ||
override->getDeclContext()->isExtensionContext()) &&
- !base->isObjC() && !isKnownObjC) {
+ !base->isObjC()) {
bool baseCanBeObjC = canBeRepresentedInObjC(base);
diags.diagnose(override, diag::override_decl_extension, baseCanBeObjC,
!base->getDeclContext()->isExtensionContext());
@@ -1450,7 +1453,6 @@
else
diags.diagnose(override, diag::missing_override);
diags.diagnose(base, diag::overridden_here);
- override->getAttrs().add(new (ctx) OverrideAttr(SourceLoc()));
}
// If the overridden method is declared in a Swift Class Declaration,
@@ -1460,8 +1462,9 @@
// FIXME: Only warn if the extension is in another module, and if
// it is in the same module, update the vtable.
if (auto *baseDecl = dyn_cast<ClassDecl>(base->getDeclContext())) {
- if (baseDecl->hasKnownSwiftImplementation() &&
- !base->isDynamic() && !isKnownObjC &&
+ if (!isAccessor &&
+ baseDecl->hasKnownSwiftImplementation() &&
+ !base->isDynamic() &&
override->getDeclContext()->isExtensionContext()) {
// For compatibility, only generate a warning in Swift 3
diags.diagnose(override, (ctx.isSwiftVersion3()
@@ -1488,6 +1491,27 @@
}
}
+ // The overridden declaration cannot be 'final'.
+ if (base->isFinal() && !isAccessor) {
+ // FIXME: Customize message to the kind of thing.
+ auto baseKind = base->getDescriptiveKind();
+ switch (baseKind) {
+ case DescriptiveDeclKind::StaticLet:
+ case DescriptiveDeclKind::StaticVar:
+ case DescriptiveDeclKind::StaticMethod:
+ override->diagnose(diag::override_static, baseKind);
+ break;
+ default:
+ override->diagnose(diag::override_final,
+ override->getDescriptiveKind(), baseKind);
+ break;
+ }
+
+ base->diagnose(diag::overridden_here);
+
+ return true;
+ }
+
// FIXME: Possibly should extend to more availability checking.
if (auto *attr = base->getAttrs().getUnavailable(ctx)) {
diagnoseUnavailableOverride(override, base, attr);
@@ -1497,17 +1521,6 @@
diagnoseOverrideForAvailability(override, base);
}
- if (auto overridingFunc = dyn_cast<FuncDecl>(override)) {
- overridingFunc->setOverriddenDecl(cast<FuncDecl>(base));
- } else if (auto overridingCtor = dyn_cast<ConstructorDecl>(override)) {
- overridingCtor->setOverriddenDecl(cast<ConstructorDecl>(base));
- } else if (auto overridingASD = dyn_cast<AbstractStorageDecl>(override)) {
- auto *baseASD = cast<AbstractStorageDecl>(base);
- overridingASD->setOverriddenDecl(baseASD);
- } else {
- llvm_unreachable("Unexpected decl");
- }
-
/// Check attributes associated with the base; some may need to merged with
/// or checked against attributes in the overriding declaration.
AttributeOverrideChecker attrChecker(base, override);
@@ -1515,55 +1528,13 @@
attrChecker.visit(attr);
}
- if (auto overridingASD = dyn_cast<AbstractStorageDecl>(override)) {
- // Make sure we get consistent overrides for the accessors as well.
- auto *baseASD = cast<AbstractStorageDecl>(base);
- assert(baseASD->getGetter());
-
- auto recordAccessorOverride = [&](AccessorKind kind) {
- // We need the same accessor on both.
- auto baseAccessor = baseASD->getAccessor(kind);
- if (!baseAccessor) return;
- auto overridingAccessor = overridingASD->getAccessor(kind);
- if (!overridingAccessor) return;
-
- // For setter accessors, we need the base's setter to be
- // accessible from the overriding context, or it's not an override.
- if ((kind == AccessorKind::Set ||
- kind == AccessorKind::MaterializeForSet) &&
- !baseASD->isSetterAccessibleFrom(overridingASD->getDeclContext()))
- return;
-
- // A materializeForSet for an override of storage with a
- // forced static dispatch materializeForSet is not itself an
- // override.
- if (kind == AccessorKind::MaterializeForSet &&
- baseAccessor->hasForcedStaticDispatch())
- return;
-
- // FIXME: Egregious hack to set an 'override' attribute.
- if (!overridingAccessor->getAttrs().hasAttribute<OverrideAttr>()) {
- auto loc = overridingASD->getOverrideLoc();
- overridingAccessor->getAttrs().add(
- new (ctx) OverrideAttr(loc));
- }
-
- recordOverride(TC, overridingAccessor, baseAccessor, baseASD->isObjC());
- };
-
- // FIXME: Another list of accessors, yay!
- recordAccessorOverride(AccessorKind::Get);
- recordAccessorOverride(AccessorKind::Set);
- recordAccessorOverride(AccessorKind::MaterializeForSet);
- }
-
return false;
}
/// Minimize the set of overridden associated types, eliminating any
/// associated types that are overridden by other associated types.
static void minimizeOverriddenAssociatedTypes(
- SmallVectorImpl<ValueDecl *> &assocTypes) {
+ llvm::TinyPtrVector<ValueDecl *> &assocTypes) {
// Mark associated types that are "worse" than some other associated type,
// because they come from an inherited protocol.
bool anyWorse = false;
@@ -1591,9 +1562,10 @@
// Copy in the associated types that aren't worse than any other associated
// type.
unsigned nextIndex = 0;
- for (unsigned i : indices(assocTypes)) {
+ MutableArrayRef<ValueDecl *> buffer = assocTypes;
+ for (unsigned i : indices(buffer)) {
if (worseThanAny[i]) continue;
- assocTypes[nextIndex++] = assocTypes[i];
+ buffer[nextIndex++] = buffer[i];
}
assocTypes.erase(assocTypes.begin() + nextIndex, assocTypes.end());
@@ -1609,11 +1581,11 @@
/// Compute the set of associated types that are overridden by the given
/// associated type.
-static SmallVector<ValueDecl *, 4>
+static llvm::TinyPtrVector<ValueDecl *>
computeOverriddenAssociatedTypes(AssociatedTypeDecl *assocType) {
// Find associated types with the given name in all of the inherited
// protocols.
- SmallVector<ValueDecl *, 4> overriddenAssocTypes;
+ llvm::TinyPtrVector<ValueDecl *> overriddenAssocTypes;
auto proto = assocType->getProtocol();
proto->walkInheritedProtocols([&](ProtocolDecl *inheritedProto) {
if (proto == inheritedProto) return TypeWalker::Action::Continue;
@@ -1648,78 +1620,109 @@
return overriddenAssocTypes;
}
-void TypeChecker::resolveOverriddenDecl(ValueDecl *VD) {
- // If this function or something it calls didn't set any overridden
- // declarations, it means that there are no overridden declarations. Set
- // the empty list.
- // Note: the request-evaluator would do this for free, but this function
- // is still fundamentally stateful.
- SWIFT_DEFER {
- if (!VD->overriddenDeclsComputed())
- (void)VD->setOverriddenDecls({ });
- };
-
+llvm::TinyPtrVector<ValueDecl *>
+OverriddenDeclsRequest::evaluate(Evaluator &evaluator, ValueDecl *decl) const {
// For an associated type, compute the (minimized) set of overridden
// declarations.
- if (auto assocType = dyn_cast<AssociatedTypeDecl>(VD)) {
- // Assume there are no overridden declarations for the purposes of this
- // computation.
- // FIXME: The request-evaluator will eventually handle this for us.
- (void)assocType->setOverriddenDecls({ });
-
- auto overriddenAssocTypes = computeOverriddenAssociatedTypes(assocType);
- (void)assocType->setOverriddenDecls(overriddenAssocTypes);
- return;
+ if (auto assocType = dyn_cast<AssociatedTypeDecl>(decl)) {
+ return computeOverriddenAssociatedTypes(assocType);
}
// Only members of classes can override other declarations.
- if (!VD->getDeclContext()->getAsClassOrClassExtensionContext())
- return;
+ if (!decl->getDeclContext()->getAsClassOrClassExtensionContext())
+ return { };
// Types that aren't associated types cannot be overridden.
- if (isa<TypeDecl>(VD))
- return;
+ if (isa<TypeDecl>(decl))
+ return { };
+
+ // Accessors determine their overrides based on their abstract storage
+ // declarations.
+ if (auto accessor = dyn_cast<AccessorDecl>(decl)) {
+ auto overridingASD = accessor->getStorage();
+
+ // Find the overidden storage declaration. If there isn't one, we're done.
+ auto baseASD = overridingASD->getOverriddenDecl();
+ if (!baseASD) return { };
+
+ auto kind = accessor->getAccessorKind();
+
+ // Find the base accessor; if there isn't one, we're done.
+ auto baseAccessor = baseASD->getAccessor(kind);
+ if (!baseAccessor) return { };
+
+ switch (kind) {
+ case AccessorKind::Get:
+ break;
+
+ case AccessorKind::MaterializeForSet:
+ // A materializeForSet for an override of storage with a
+ // forced static dispatch materializeForSet is not itself an
+ // override.
+ if (baseAccessor->hasForcedStaticDispatch())
+ return { };
+
+ LLVM_FALLTHROUGH;
+
+ case AccessorKind::Set:
+ // For setter accessors, we need the base's setter to be
+ // accessible from the overriding context, or it's not an override.
+ if (!baseASD->isSetterAccessibleFrom(overridingASD->getDeclContext()))
+ return { };
+ break;
+
+ case AccessorKind::Address:
+ case AccessorKind::DidSet:
+ case AccessorKind::MutableAddress:
+ case AccessorKind::WillSet:
+ return { };
+ }
+
+ // We are overriding the base accessor.
+
+ // Check the correctness of the override.
+ OverrideMatcher matcher(accessor);
+ if (matcher.checkOverride(baseAccessor,
+ OverrideCheckingAttempt::PerfectMatch)) {
+ invalidateOverrideAttribute(decl);
+ return { };
+ }
+
+ return llvm::TinyPtrVector<ValueDecl *>{baseAccessor};
+ }
// Only initializers and declarations marked with the 'override' declaration
// modifier can override declarations.
- if (!isa<ConstructorDecl>(VD) && !VD->getAttrs().hasAttribute<OverrideAttr>())
- return;
-
- // Invalidate an existing "override" attribute or add a new invalid "override"
- // attribute, which will suppress additional checking.
- auto invalidateOverrideAttribute = [VD]() {
- auto overrideAttr = VD->getAttrs().getAttribute<OverrideAttr>(true);
- if (!overrideAttr) {
- overrideAttr = new (VD->getASTContext()) OverrideAttr(true);
- VD->getAttrs().add(overrideAttr);
- }
-
- overrideAttr->setInvalid();
- };
+ if (!isa<ConstructorDecl>(decl) &&
+ !decl->getAttrs().hasAttribute<OverrideAttr>())
+ return { };
// Try to match potential overridden declarations.
- OverrideMatcher matcher(*this, VD);
+ OverrideMatcher matcher(decl);
if (!matcher) {
- return;
+ return { };
}
auto matches = matcher.match(OverrideCheckingAttempt::PerfectMatch);
if (matches.empty()) {
- return;
+ return { };
}
// If we have more than one potential match, diagnose the ambiguity and
// fail.
if (matches.size() > 1) {
- diagnoseGeneralOverrideFailure(VD, matches,
+ diagnoseGeneralOverrideFailure(decl, matches,
OverrideCheckingAttempt::PerfectMatch);
- invalidateOverrideAttribute();
- return;
+ invalidateOverrideAttribute(decl);
+ return { };
}
// Check the correctness of the override.
- // FIXME: This also records the override.
if (matcher.checkOverride(matches.front().Decl,
- OverrideCheckingAttempt::PerfectMatch))
- invalidateOverrideAttribute();
+ OverrideCheckingAttempt::PerfectMatch)) {
+ invalidateOverrideAttribute(decl);
+ return { };
+ }
+
+ return llvm::TinyPtrVector<ValueDecl *>{matches.front().Decl};
}
diff --git a/lib/Sema/TypeCheckNameLookup.cpp b/lib/Sema/TypeCheckNameLookup.cpp
index 0e65a4a..9f0f0be 100644
--- a/lib/Sema/TypeCheckNameLookup.cpp
+++ b/lib/Sema/TypeCheckNameLookup.cpp
@@ -71,7 +71,6 @@
/// Builder that helps construct a lookup result from the raw lookup
/// data.
class LookupResultBuilder {
- TypeChecker &TC;
LookupResult &Result;
DeclContext *DC;
NameLookupOptions Options;
@@ -86,12 +85,12 @@
llvm::SmallDenseMap<std::pair<ValueDecl *, DeclContext *>, bool, 4> Known;
public:
- LookupResultBuilder(TypeChecker &tc, LookupResult &result, DeclContext *dc,
+ LookupResultBuilder(LookupResult &result, DeclContext *dc,
NameLookupOptions options,
bool isMemberLookup)
- : TC(tc), Result(result), DC(dc), Options(options),
+ : Result(result), DC(dc), Options(options),
IsMemberLookup(isMemberLookup) {
- if (!TC.Context.LangOpts.EnableAccessControl)
+ if (!dc->getASTContext().LangOpts.EnableAccessControl)
Options |= NameLookupFlags::IgnoreAccessControl;
}
@@ -132,8 +131,8 @@
removeOverriddenDecls(FoundOuterDecls);
// Remove any shadowed declarations from the found-declarations set.
- removeShadowedDecls(FoundDecls, DC->getParentModule(), &TC);
- removeShadowedDecls(FoundOuterDecls, DC->getParentModule(), &TC);
+ removeShadowedDecls(FoundDecls, DC->getParentModule());
+ removeShadowedDecls(FoundOuterDecls, DC->getParentModule());
// Filter out those results that have been removed from the
// found-declarations set.
@@ -232,7 +231,10 @@
// Dig out the protocol conformance.
auto *foundProto = cast<ProtocolDecl>(foundDC);
- auto conformance = TC.conformsToProtocol(conformingType, foundProto, DC,
+ auto resolver = DC->getASTContext().getLazyResolver();
+ assert(resolver && "Need an active resolver");
+ auto &tc = *static_cast<TypeChecker *>(resolver);
+ auto conformance = tc.conformsToProtocol(conformingType, foundProto, DC,
conformanceOptions);
if (!conformance) {
// If there's no conformance, we have an existential
@@ -254,10 +256,10 @@
ValueDecl *witness = nullptr;
auto concrete = conformance->getConcrete();
if (auto assocType = dyn_cast<AssociatedTypeDecl>(found)) {
- witness = concrete->getTypeWitnessAndDecl(assocType, &TC)
+ witness = concrete->getTypeWitnessAndDecl(assocType, nullptr)
.second;
} else if (found->isProtocolRequirement()) {
- witness = concrete->getWitnessDecl(found, &TC);
+ witness = concrete->getWitnessDecl(found, nullptr);
// It is possible that a requirement is visible to us, but
// not the witness. In this case, just return the requirement;
@@ -300,12 +302,11 @@
LookupResult TypeChecker::lookupUnqualified(DeclContext *dc, DeclName name,
SourceLoc loc,
NameLookupOptions options) {
- UnqualifiedLookup lookup(name, dc, this, loc,
+ UnqualifiedLookup lookup(name, dc, nullptr, loc,
convertToUnqualifiedLookupOptions(options));
LookupResult result;
- LookupResultBuilder builder(*this, result, dc, options,
- /*memberLookup*/false);
+ LookupResultBuilder builder(result, dc, options, /*memberLookup*/false);
for (auto idx : indices(lookup.Results)) {
const auto &found = lookup.Results[idx];
// Determine which type we looked through to find this result.
@@ -336,7 +337,7 @@
{
// Try lookup without ProtocolMembers first.
UnqualifiedLookup lookup(
- name, dc, this, loc,
+ name, dc, nullptr, loc,
ulOptions - UnqualifiedLookup::Flags::AllowProtocolMembers);
if (!lookup.Results.empty() ||
@@ -352,7 +353,7 @@
// is called too early, we start resolving extensions -- even those
// which do provide not conformances.
UnqualifiedLookup lookup(
- name, dc, this, loc,
+ name, dc, nullptr, loc,
ulOptions | UnqualifiedLookup::Flags::AllowProtocolMembers);
return LookupResult(lookup.Results, lookup.IndexOfFirstOuterResult);
@@ -380,10 +381,10 @@
subOptions &= ~NL_RemoveOverridden;
subOptions &= ~NL_RemoveNonVisible;
- LookupResultBuilder builder(*this, result, dc, options,
+ LookupResultBuilder builder(result, dc, options,
/*memberLookup*/true);
SmallVector<ValueDecl *, 4> lookupResults;
- dc->lookupQualified(type, name, subOptions, this, lookupResults);
+ dc->lookupQualified(type, name, subOptions, nullptr, lookupResults);
for (auto found : lookupResults)
builder.add(found, nullptr, type, /*isOuter=*/false);
diff --git a/lib/Sema/TypeCheckObjC.h b/lib/Sema/TypeCheckObjC.h
index 58f5630..117369c 100644
--- a/lib/Sema/TypeCheckObjC.h
+++ b/lib/Sema/TypeCheckObjC.h
@@ -112,16 +112,6 @@
/// complain about the correct attribute during @objc inference.
unsigned getObjCDiagnosticAttrKind(ObjCReason reason);
-/// Figure out if a declaration should be exported to Objective-C.
-Optional<ObjCReason> shouldMarkAsObjC(TypeChecker &TC,
- const ValueDecl *VD,
- bool allowImplicit = false);
-
-/// Record whether the given declaration is @objc, and why.
-void markAsObjC(TypeChecker &TC, ValueDecl *D,
- Optional<ObjCReason> isObjC,
- Optional<ForeignErrorConvention> errorConvention = llvm::None);
-
/// Determine whether the given function can be represented in Objective-C,
/// and figure out its foreign error convention (if any).
bool isRepresentableInObjC(const AbstractFunctionDecl *AFD,
diff --git a/lib/Sema/TypeCheckProtocol.cpp b/lib/Sema/TypeCheckProtocol.cpp
index aa534e3..0b894e2 100644
--- a/lib/Sema/TypeCheckProtocol.cpp
+++ b/lib/Sema/TypeCheckProtocol.cpp
@@ -2270,14 +2270,15 @@
// Record type witnesses for any "overridden" associated types.
llvm::SetVector<AssociatedTypeDecl *> overriddenAssocTypes;
- overriddenAssocTypes.insert(assocType->getOverriddenDecls().begin(),
- assocType->getOverriddenDecls().end());
+ auto assocOverriddenDecls = assocType->getOverriddenDecls();
+ overriddenAssocTypes.insert(assocOverriddenDecls.begin(),
+ assocOverriddenDecls.end());
for (unsigned idx = 0; idx < overriddenAssocTypes.size(); ++idx) {
auto overridden = overriddenAssocTypes[idx];
// Note all of the newly-discovered overridden associated types.
- overriddenAssocTypes.insert(overridden->getOverriddenDecls().begin(),
- overridden->getOverriddenDecls().end());
+ auto overriddenDecls = overridden->getOverriddenDecls();
+ overriddenAssocTypes.insert(overriddenDecls.begin(), overriddenDecls.end());
// Find the conformance for this overridden protocol.
auto overriddenConformance =
@@ -3966,16 +3967,15 @@
/// These conformances might not appear in any substitution lists produced
/// by Sema, since bridging is done at the SILGen level, so we have to
/// force them here to ensure SILGen can find them.
-void TypeChecker::useObjectiveCBridgeableConformances(DeclContext *dc,
- Type type) {
+void swift::useObjectiveCBridgeableConformances(DeclContext *dc, Type type) {
class Walker : public TypeWalker {
- TypeChecker &TC;
+ ASTContext &Ctx;
DeclContext *DC;
ProtocolDecl *Proto;
public:
- Walker(TypeChecker &tc, DeclContext *dc, ProtocolDecl *proto)
- : TC(tc), DC(dc), Proto(proto) { }
+ Walker(DeclContext *dc, ProtocolDecl *proto)
+ : Ctx(dc->getASTContext()), DC(dc), Proto(proto) { }
Action walkToTypePre(Type ty) override {
ConformanceCheckOptions options =
@@ -3989,23 +3989,27 @@
if (isa<ClassDecl>(nominalDecl) || isa<ProtocolDecl>(nominalDecl))
return Action::Continue;
- (void)TC.conformsToProtocol(ty, Proto, DC, options,
+ auto lazyResolver = Ctx.getLazyResolver();
+ assert(lazyResolver &&
+ "Cannot do conforms-to-protocol check without a type checker");
+ TypeChecker &tc = *static_cast<TypeChecker *>(lazyResolver);
+ (void)tc.conformsToProtocol(ty, Proto, DC, options,
/*ComplainLoc=*/SourceLoc());
// Set and Dictionary bridging also requires the conformance
// of the key type to Hashable.
- if (nominalDecl == TC.Context.getSetDecl() ||
- nominalDecl == TC.Context.getDictionaryDecl()) {
+ if (nominalDecl == Ctx.getSetDecl() ||
+ nominalDecl == Ctx.getDictionaryDecl()) {
if (auto boundGeneric = ty->getAs<BoundGenericType>()) {
auto args = boundGeneric->getGenericArgs();
if (!args.empty()) {
auto keyType = args[0];
auto *hashableProto =
- TC.Context.getProtocol(KnownProtocolKind::Hashable);
+ Ctx.getProtocol(KnownProtocolKind::Hashable);
if (!hashableProto)
return Action::Stop;
- auto result = TC.conformsToProtocol(
+ auto result = tc.conformsToProtocol(
keyType, hashableProto, DC, options,
/*ComplainLoc=*/SourceLoc());
}
@@ -4017,18 +4021,18 @@
}
};
- auto proto = getProtocol(SourceLoc(),
- KnownProtocolKind::ObjectiveCBridgeable);
+ auto proto =
+ dc->getASTContext().getProtocol(KnownProtocolKind::ObjectiveCBridgeable);
if (!proto) return;
- Walker walker(*this, dc, proto);
+ Walker walker(dc, proto);
type.walk(walker);
}
-void TypeChecker::useObjectiveCBridgeableConformancesOfArgs(
+void swift::useObjectiveCBridgeableConformancesOfArgs(
DeclContext *dc, BoundGenericType *bound) {
- auto proto = getProtocol(SourceLoc(),
- KnownProtocolKind::ObjectiveCBridgeable);
+ ASTContext &ctx = dc->getASTContext();
+ auto proto = ctx.getProtocol(KnownProtocolKind::ObjectiveCBridgeable);
if (!proto) return;
// Check whether the bound generic type itself is bridged to
@@ -4036,7 +4040,10 @@
ConformanceCheckOptions options =
(ConformanceCheckFlags::InExpression |
ConformanceCheckFlags::SuppressDependencyTracking);
- (void)conformsToProtocol(
+ auto lazyResolver = ctx.getLazyResolver();
+ assert(lazyResolver && "Need a type checker to check conforms-to-protocol");
+ auto &tc = *static_cast<TypeChecker *>(lazyResolver);
+ (void)tc.conformsToProtocol(
bound->getDecl()->getDeclaredType(), proto, dc,
options, /*ComplainLoc=*/SourceLoc());
}
@@ -4877,8 +4884,8 @@
}
llvm::TinyPtrVector<ValueDecl *>
-TypeChecker::findWitnessedObjCRequirements(const ValueDecl *witness,
- bool anySingleRequirement) {
+swift::findWitnessedObjCRequirements(const ValueDecl *witness,
+ bool anySingleRequirement) {
llvm::TinyPtrVector<ValueDecl *> result;
// Types don't infer @objc this way.
@@ -4910,6 +4917,7 @@
}
}
+ ASTContext &ctx = nominal->getASTContext();
for (auto proto : nominal->getAllProtocols()) {
// We only care about Objective-C protocols.
if (!proto->isObjC()) continue;
@@ -4923,7 +4931,7 @@
if (isa<TypeDecl>(req)) continue;
// Skip unavailable requirements.
- if (req->getAttrs().isUnavailable(Context)) continue;
+ if (req->getAttrs().isUnavailable(ctx)) continue;
// Dig out the conformance.
if (!conformance.hasValue()) {
@@ -4937,7 +4945,7 @@
}
if (!*conformance) continue;
- const Decl *found = (*conformance)->getWitnessDecl(req, this);
+ const Decl *found = (*conformance)->getWitnessDecl(req, nullptr);
if (!found) {
// If we have an optional requirement in an inherited conformance,
@@ -4961,7 +4969,10 @@
if (accessorKind)
witnessToMatch = cast<AccessorDecl>(witness)->getStorage();
- if (matchWitness(*this, proto, *conformance,
+ auto lazyResolver = ctx.getLazyResolver();
+ assert(lazyResolver && "Need a type checker to match witnesses");
+ auto &tc = *static_cast<TypeChecker *>(lazyResolver);
+ if (matchWitness(tc, proto, *conformance,
witnessToMatch->getDeclContext(), req,
const_cast<ValueDecl *>(witnessToMatch))
.Kind == MatchKind::ExactMatch) {
diff --git a/lib/Sema/TypeCheckProtocol.h b/lib/Sema/TypeCheckProtocol.h
index 3a25dc0..c11ddb4 100644
--- a/lib/Sema/TypeCheckProtocol.h
+++ b/lib/Sema/TypeCheckProtocol.h
@@ -858,6 +858,28 @@
/// the noescape-to-escaping adjustment.
Type adjustInferredAssociatedType(Type type, bool &noescapeToEscaping);
+/// Find the @objc requirement that are witnessed by the given
+/// declaration.
+///
+/// \param anySingleRequirement If true, returns at most a single requirement,
+/// which might be any of the requirements that match.
+///
+/// \returns the set of requirements to which the given witness is a
+/// witness.
+llvm::TinyPtrVector<ValueDecl *> findWitnessedObjCRequirements(
+ const ValueDecl *witness,
+ bool anySingleRequirement = false);
+
+/// Mark any _ObjectiveCBridgeable conformances in the given type as "used".
+void useObjectiveCBridgeableConformances(
+ DeclContext *dc, Type type);
+
+/// If this bound-generic type is bridged, mark any
+/// _ObjectiveCBridgeable conformances in the generic arguments of
+/// the given type as "used".
+void useObjectiveCBridgeableConformancesOfArgs(
+ DeclContext *dc, BoundGenericType *bound);
+
}
#endif // SWIFT_SEMA_PROTOCOL_H
diff --git a/lib/Sema/TypeCheckType.cpp b/lib/Sema/TypeCheckType.cpp
index 793e978..6293ae6 100644
--- a/lib/Sema/TypeCheckType.cpp
+++ b/lib/Sema/TypeCheckType.cpp
@@ -18,6 +18,7 @@
#include "TypeChecker.h"
#include "GenericTypeResolver.h"
#include "TypeCheckAvailability.h"
+#include "TypeCheckProtocol.h"
#include "swift/Strings.h"
#include "swift/AST/ASTVisitor.h"
@@ -2623,7 +2624,7 @@
if (!options.contains(TypeResolutionFlags::ResolveStructure)) {
// Check for _ObjectiveCBridgeable conformances in the element type.
- TC.useObjectiveCBridgeableConformances(DC, baseTy);
+ useObjectiveCBridgeableConformances(DC, baseTy);
}
return sliceTy;
@@ -2658,8 +2659,8 @@
// Check for _ObjectiveCBridgeable conformances in the key and value
// types.
- TC.useObjectiveCBridgeableConformances(DC, keyTy);
- TC.useObjectiveCBridgeableConformances(DC, valueTy);
+ useObjectiveCBridgeableConformances(DC, keyTy);
+ useObjectiveCBridgeableConformances(DC, valueTy);
}
return dictTy;
diff --git a/lib/Sema/TypeChecker.h b/lib/Sema/TypeChecker.h
index 470aacb..c3557c5 100644
--- a/lib/Sema/TypeChecker.h
+++ b/lib/Sema/TypeChecker.h
@@ -1234,12 +1234,6 @@
validateDeclForNameLookup(VD);
}
- /// Resolve the "overridden" declaration of the given declaration.
- virtual void resolveOverriddenDecl(ValueDecl *VD) override;
-
- /// Resolve the "is Objective-C" bit for the given declaration.
- virtual void resolveIsObjC(ValueDecl *VD) override;
-
virtual void bindExtension(ExtensionDecl *ext) override;
virtual void resolveExtension(ExtensionDecl *ext) override {
@@ -1925,28 +1919,6 @@
/// Return true if there was an error.
bool checkConformanceToNSCopying(VarDecl *var);
- /// Find the @objc requirement that are witnessed by the given
- /// declaration.
- ///
- /// \param anySingleRequirement If true, returns at most a single requirement,
- /// which might be any of the requirements that match.
- ///
- /// \returns the set of requirements to which the given witness is a
- /// witness.
- llvm::TinyPtrVector<ValueDecl *> findWitnessedObjCRequirements(
- const ValueDecl *witness,
- bool anySingleRequirement = false);
-
- /// Mark any _ObjectiveCBridgeable conformances in the given type as "used".
- void useObjectiveCBridgeableConformances(
- DeclContext *dc, Type type);
-
- /// If this bound-generic type is bridged, mark any
- /// _ObjectiveCBridgeable conformances in the generic arguments of
- /// the given type as "used".
- void useObjectiveCBridgeableConformancesOfArgs(
- DeclContext *dc, BoundGenericType *bound);
-
/// Mark any _BridgedNSError/_BridgedStoredNSError/related
/// conformances in the given type as "used".
void useBridgedNSErrorConformances(DeclContext *dc, Type type);
@@ -1989,9 +1961,10 @@
/// \param name The name of the entity to look for.
/// \param loc The source location at which name lookup occurs.
/// \param options Options that control name lookup.
- LookupResult lookupUnqualified(DeclContext *dc, DeclName name, SourceLoc loc,
- NameLookupOptions options
- = defaultUnqualifiedLookupOptions);
+ static LookupResult lookupUnqualified(DeclContext *dc, DeclName name,
+ SourceLoc loc,
+ NameLookupOptions options
+ = defaultUnqualifiedLookupOptions);
/// Perform unqualified type lookup at the given source location
/// within a particular declaration context.
@@ -2001,9 +1974,9 @@
/// \param loc The source location at which name lookup occurs.
/// \param options Options that control name lookup.
LookupResult
- lookupUnqualifiedType(DeclContext *dc, DeclName name, SourceLoc loc,
- NameLookupOptions options
- = defaultUnqualifiedLookupOptions);
+ static lookupUnqualifiedType(DeclContext *dc, DeclName name, SourceLoc loc,
+ NameLookupOptions options
+ = defaultUnqualifiedLookupOptions);
/// \brief Lookup a member in the given type.
///
@@ -2013,9 +1986,9 @@
/// \param options Options that control name lookup.
///
/// \returns The result of name lookup.
- LookupResult lookupMember(DeclContext *dc, Type type, DeclName name,
- NameLookupOptions options
- = defaultMemberLookupOptions);
+ static LookupResult lookupMember(DeclContext *dc, Type type, DeclName name,
+ NameLookupOptions options
+ = defaultMemberLookupOptions);
/// \brief Check whether the given declaration can be written as a
/// member of the given base type.
diff --git a/lib/Serialization/Deserialization.cpp b/lib/Serialization/Deserialization.cpp
index 0f5ad9f..865a087 100644
--- a/lib/Serialization/Deserialization.cpp
+++ b/lib/Serialization/Deserialization.cpp
@@ -2709,7 +2709,7 @@
overriddenAssocTypes.push_back(overriddenAssocType);
}
}
- (void)assocType->setOverriddenDecls(overriddenAssocTypes);
+ assocType->setOverriddenDecls(overriddenAssocTypes);
break;
}
diff --git a/stdlib/public/SDK/Foundation/NSDictionary.swift b/stdlib/public/SDK/Foundation/NSDictionary.swift
index eeb3de3..387defc 100644
--- a/stdlib/public/SDK/Foundation/NSDictionary.swift
+++ b/stdlib/public/SDK/Foundation/NSDictionary.swift
@@ -192,7 +192,8 @@
extension NSMutableDictionary {
// Bridging subscript.
- override public subscript(key: Any) -> Any? {
+ @objc override public subscript(key: Any) -> Any? {
+ @objc(_swift_objectForKeyedSubscript:)
get {
return self.object(forKey: key)
}
diff --git a/test/ClangImporter/objc_override.swift b/test/ClangImporter/objc_override.swift
index f27995f..bf8bdd7 100644
--- a/test/ClangImporter/objc_override.swift
+++ b/test/ClangImporter/objc_override.swift
@@ -19,8 +19,7 @@
@objc func initWithString(_ string: String) { }
var isEnabled: Bool { // expected-error{{overriding declaration requires an 'override' keyword}}
- // FIXE: The error that follows is a bit strange.
- get { return super.isEnabled } // expected-error{{'@objc' getter for non-'@objc' property}}
+ get { return super.isEnabled }
}
@objc(enabled)
diff --git a/test/Constraints/diag_ambiguities.swift b/test/Constraints/diag_ambiguities.swift
index e9e266c..3e399f8 100644
--- a/test/Constraints/diag_ambiguities.swift
+++ b/test/Constraints/diag_ambiguities.swift
@@ -29,19 +29,11 @@
func h<T>(_ x: T) -> () {}
C(h) // expected-error{{ambiguous use of 'init'}}
-func rdar29691909_callee(_ o: AnyObject?) -> Any? { return o }
-func rdar29691909_callee(_ o: AnyObject) -> Any { return o }
+func rdar29691909_callee(_ o: AnyObject?) -> Any? { return o } // expected-note {{found this candidate}}
+func rdar29691909_callee(_ o: AnyObject) -> Any { return o } // expected-note {{found this candidate}}
func rdar29691909(o: AnyObject) -> Any? {
- return rdar29691909_callee(o)
-}
-
-func rdar29691909_callee_alt(_ o: AnyObject?) -> Int? { fatalError() }
-func rdar29691909_callee_alt(_ o: AnyObject) -> Int { fatalError() }
-
-func rdar29691909_1(o: AnyObject) -> Int {
- let r = rdar29691909_callee_alt(o)
- return r
+ return rdar29691909_callee(o) // expected-error{{ambiguous use of 'rdar29691909_callee'}}
}
func rdar29907555(_ value: Any!) -> String {
diff --git a/test/Constraints/overload.swift b/test/Constraints/overload.swift
index fb03975..8e5e666 100644
--- a/test/Constraints/overload.swift
+++ b/test/Constraints/overload.swift
@@ -236,53 +236,3 @@
func test_autoclosure1(ia: [Int]) {
autoclosure1(ia, X()) // okay: resolves to the second function
}
-
-// Ensure that we select the (T?, T) -> T overload of '??' in coalesce() below.
-func apply<T>(_ fn: () -> T) -> T { return fn() }
-func opt(x: String) -> String { return x }
-func opt() -> String? { return "hi" }
-
-func coalesce() {
- let _ = apply{
- _ = opt()
- return opt()
- } ?? ""
-}
-
-// Ensure that we do not select the (T?, T) -> T version of ??, which
-// would result in a warning about RHS never being selected.
-func rdar19748710_0(_ value: Int?) -> Int? {
- return value ?? value
-}
-
-// Again, ensure we do not select (T?, T) -> T, despite forcing the result.
-func rdar19748710_1(_ value: Int?) -> Int? {
- return (value ?? value)!
-}
-
-// FIXME: We choose to inject the LHS, which really doesn't seem like
-// the reasonable choice here. It seems more predictable and safe to
-// either inject the result of ??, or treat this as an error since the
-// current behavior will result in .some(nil) being force-unwrapped
-// rather than the RHS value. The diagnostic is problematic, too,
-// since it claims 'Int?' is a non-optional type.
-func rdar19748710_2(_ value: Int?) -> Int? {
- return (value ?? value)!! // expected-warning {{left side of nil coalescing operator '??' has non-optional type 'Int?', so the right side is never used}}
-}
-
-// Ensure that we select the more closely matching function between
-// the two _g overloads.
-func giveAny() -> Any { fatalError() }
-func giveAnyOptional() -> Any? { fatalError() }
-func takeAny(_ a: Any?) -> Any? { fatalError() }
-func takeAny(_ a: Any) -> Any { fatalError() }
-
-func testAnyOptional() {
- let r = takeAny(giveAnyOptional())
- let _ = r!
-}
-
-func testAny() {
- let r = takeAny(giveAny())
- let _ = r! // expected-error {{cannot force unwrap value of non-optional type 'Any'}}
-}
diff --git a/test/Constraints/overload_silgen.swift b/test/Constraints/overload_silgen.swift
deleted file mode 100644
index ae0e1ed..0000000
--- a/test/Constraints/overload_silgen.swift
+++ /dev/null
@@ -1,10 +0,0 @@
-// RUN: %target-swift-emit-silgen %s | %FileCheck %s
-
-// CHECK: sil hidden @$S15overload_silgen8anyToIntySiypF
-// CHECK: end sil function '$S15overload_silgen8anyToIntySiypF'
-func anyToInt(_: Any) -> Int { fatalError() }
-
-// CHECK: sil hidden @$S15overload_silgen8anyToIntySiSgypSgF
-// CHECK: function_ref @$S15overload_silgen8anyToIntySiypF
-// CHECK: end sil function '$S15overload_silgen8anyToIntySiSgypSgF'
-func anyToInt(_ value: Any?) -> Int? { return anyToInt(value!) }
diff --git a/test/Driver/Dependencies/only-skip-once.swift b/test/Driver/Dependencies/only-skip-once.swift
index c98052f..b2647a4 100644
--- a/test/Driver/Dependencies/only-skip-once.swift
+++ b/test/Driver/Dependencies/only-skip-once.swift
@@ -4,8 +4,6 @@
// RUN: cd %t && %target-swiftc_driver -driver-show-job-lifecycle -output-file-map %t/output-file-map.json -incremental main.swift file1.swift file2.swift -j1 2>&1 | %FileCheck -check-prefix=CHECK-INITIAL %s
-// CHECK-INITIAL-NOT: warning
-// CHECK-INITIAL: Queuing (initial):
// CHECK-INITIAL: Job finished: {compile: main.o <= main.swift}
// CHECK-INITIAL: Job finished: {compile: file1.o <= file1.swift}
// CHECK-INITIAL: Job finished: {compile: file2.o <= file2.swift}
@@ -15,7 +13,6 @@
// RUN: cd %t && %target-swiftc_driver -driver-show-job-lifecycle -output-file-map %t/output-file-map.json -incremental main.swift file1.swift file2.swift -j1 2>&1 | %FileCheck -check-prefix=CHECK-REBUILD %s
// We should skip the main and file1 rebuilds here, but we should only note skipping them _once_
-// CHECK-REBUILD: Queuing (initial):
// CHECK-REBUILD: Job finished: {compile: file2.o <= file2.swift}
// CHECK-REBUILD: Job skipped: {compile: main.o <= main.swift}
// CHECK-REBUILD: Job skipped: {compile: file1.o <= file1.swift}
diff --git a/test/IDE/complete_stdlib_optional.swift b/test/IDE/complete_stdlib_optional.swift
index 12252d8..c57c957 100644
--- a/test/IDE/complete_stdlib_optional.swift
+++ b/test/IDE/complete_stdlib_optional.swift
@@ -16,38 +16,14 @@
// RUN: %target-swift-ide-test -code-completion -source-filename %s -disable-objc-attr-requires-foundation-module -code-completion-token=UN_OPT_NO_DOT_1 > %t.opt.txt
// RUN: %FileCheck %s -check-prefix=UN_OPT_NO_DOT_FOOSTRUCT < %t.opt.txt
-// RUN: %target-swift-ide-test -code-completion -source-filename %s -disable-objc-attr-requires-foundation-module -code-completion-token=UN_OPT_NO_DOT_2 > %t.opt.txt
-// RUN: %FileCheck %s -check-prefix=UN_OPT_NO_DOT_FOOSTRUCT_RETURN < %t.opt.txt
-
-// RUN: %target-swift-ide-test -code-completion -source-filename %s -disable-objc-attr-requires-foundation-module -code-completion-token=UN_OPT_NO_DOT_3 > %t.opt.txt
-// RUN: %FileCheck %s -check-prefix=UN_OPT_NO_DOT_INT < %t.opt.txt
-
// RUN: %target-swift-ide-test -code-completion -source-filename %s -disable-objc-attr-requires-foundation-module -code-completion-token=UN_OPT_DOT_1 > %t.opt.txt
// RUN: %FileCheck %s -check-prefix=UN_OPT_DOT_FOOSTRUCT < %t.opt.txt
// RUN: %target-swift-ide-test -code-completion -source-filename %s -disable-objc-attr-requires-foundation-module -code-completion-token=UN_OPT_DOT_2 > %t.opt.txt
// RUN: %FileCheck %s -check-prefix=UN_OPT_DOT_FOOSTRUCT_RETURN < %t.opt.txt
-// RUN: %target-swift-ide-test -code-completion -source-filename %s -disable-objc-attr-requires-foundation-module -code-completion-token=UN_OPT_DOT_3 > %t.opt.txt
-// RUN: %FileCheck %s -check-prefix=UN_OPT_DOT_INT < %t.opt.txt
-
-// RUN: %target-swift-ide-test -code-completion -source-filename %s -disable-objc-attr-requires-foundation-module -code-completion-token=OPT_DL_NO_DOT_1 > %t.opt.txt
-// RUN: %FileCheck %s -check-prefix=OBJCCLASS_MEMBERS_NO_DOT < %t.opt.txt
-
-// RUN: %target-swift-ide-test -code-completion -source-filename %s -disable-objc-attr-requires-foundation-module -code-completion-token=OPT_DL_NO_DOT_2 > %t.opt.txt
-// RUN: %FileCheck %s -check-prefix=OBJCCLASS_MEMBERS_NO_DOT < %t.opt.txt
-
-// RUN: %target-swift-ide-test -code-completion -source-filename %s -disable-objc-attr-requires-foundation-module -code-completion-token=OPT_DL_DOT_1 > %t.opt.txt
-// RUN: %FileCheck %s -check-prefix=OBJCCLASS_MEMBERS_DOT < %t.opt.txt
-
-// RUN: %target-swift-ide-test -code-completion -source-filename %s -disable-objc-attr-requires-foundation-module -code-completion-token=OPT_DL_DOT_2 > %t.opt.txt
-// RUN: %FileCheck %s -check-prefix=OBJCCLASS_MEMBERS_DOT < %t.opt.txt
-
-// RUN: %target-swift-ide-test -code-completion -source-filename %s -disable-objc-attr-requires-foundation-module -code-completion-token=OPT_DL_FORCE_RETURN_OPTIONAL_1 > %t.opt.txt
-// RUN: %FileCheck %s -check-prefix=OPT_NO_DOT_OBJCCLASS < %t.opt.txt
-
-// RUN: %target-swift-ide-test -code-completion -source-filename %s -disable-objc-attr-requires-foundation-module -code-completion-token=OPT_CAST_AS_RESULT_1 > %t.opt.txt
-// RUN: %FileCheck %s -check-prefix=OPT_NO_DOT_OBJCCLASS < %t.opt.txt
+// RUN: %target-swift-ide-test -code-completion -source-filename %s -disable-objc-attr-requires-foundation-module -code-completion-token=UN_OPT_NO_DOT_2 > %t.opt.txt
+// RUN: %FileCheck %s -check-prefix=UN_OPT_NO_DOT_FOOSTRUCT_RETURN < %t.opt.txt
// RUN: %target-swift-ide-test -code-completion -source-filename %s -disable-objc-attr-requires-foundation-module -code-completion-token=OPT_TUPLE_1 | %FileCheck %s -check-prefix=OPT_TUPLE_1
// RUN: %target-swift-ide-test -code-completion -source-filename %s -disable-objc-attr-requires-foundation-module -code-completion-token=OPT_TUPLE_2 | %FileCheck %s -check-prefix=OPT_TUPLE_2
@@ -76,12 +52,6 @@
return FooStruct()
}
-@objc
-class ObjcClass {
- @objc var instanceVar: Int = 0
- @objc func instanceFunc() -> ObjcClass { return self }
-}
-
// OPT_NO_DOT_FOOSTRUCT: Begin completions
// OPT_NO_DOT_FOOSTRUCT-DAG: Decl[InstanceVar]/CurrNominal: ?.instanceVar[#Int#]{{; name=.+$}}
// OPT_NO_DOT_FOOSTRUCT-DAG: Decl[InstanceMethod]/CurrNominal: ?.instanceFunc()[#Void#]{{; name=.+$}}
@@ -97,16 +67,6 @@
// OPT_DOT_FOOSTRUCT_SPACES-DAG: Decl[InstanceMethod]/CurrNominal/Erase[3]: ?.instanceFunc()[#Void#]{{; name=.+$}}
// OPT_DOT_FOOSTRUCT_SPACES: End completions
-// UN_OPT_NO_DOT_FOOSTRUCT: Begin completions
-// UN_OPT_NO_DOT_FOOSTRUCT-DAG: Decl[InstanceVar]/CurrNominal: .instanceVar[#Int#]{{; name=.+$}}
-// UN_OPT_NO_DOT_FOOSTRUCT-DAG: Decl[InstanceMethod]/CurrNominal: .instanceFunc()[#Void#]{{; name=.+$}}
-// UN_OPT_NO_DOT_FOOSTRUCT: End completions
-
-// UN_OPT_NO_DOT_FOOSTRUCT_RETURN: Begin completions
-// UN_OPT_NO_DOT_FOOSTRUCT_RETURN-DAG: Decl[InstanceVar]/CurrNominal: ?.instanceVar[#Int#]{{; name=.+$}}
-// UN_OPT_NO_DOT_FOOSTRUCT_RETURN-DAG: Decl[InstanceMethod]/CurrNominal: ?.instanceFunc()[#Void#]{{; name=.+$}}
-// UN_OPT_NO_DOT_FOOSTRUCT_RETURN: End completions
-
// UN_OPT_DOT_FOOSTRUCT: Begin completions
// UN_OPT_DOT_FOOSTRUCT-DAG: Decl[InstanceVar]/CurrNominal: instanceVar[#Int#]{{; name=.+$}}
// UN_OPT_DOT_FOOSTRUCT-DAG: Decl[InstanceMethod]/CurrNominal: instanceFunc()[#Void#]{{; name=.+$}}
@@ -117,32 +77,6 @@
// UN_OPT_DOT_FOOSTRUCT_RETURN-DAG: Decl[InstanceMethod]/CurrNominal/Erase[1]: ?.instanceFunc()[#Void#]{{; name=.+$}}
// UN_OPT_DOT_FOOSTRUCT_RETURN: End completions
-// UN_OPT_NO_DOT_INT: Begin completions
-// UN_OPT_NO_DOT_INT-DAG: Decl[InstanceVar]/CurrNominal: ?.nonzeroBitCount[#Int#]{{; name=.+$}}
-// UN_OPT_NO_DOT_INT: End completions
-
-// UN_OPT_DOT_INT: Begin completions
-// UN_OPT_DOT_INT-DAG: Decl[InstanceVar]/CurrNominal/Erase[1]: ?.nonzeroBitCount[#Int#]{{; name=.+$}}
-// UN_OPT_DOT_INT: End completions
-
-// OPT_NO_DOT_OBJCCLASS: Begin completions
-// OPT_NO_DOT_OBJCCLASS-DAG: Decl[InstanceVar]/CurrNominal: ?.instanceVar[#Int#]{{; name=.+$}}
-// OPT_NO_DOT_OBJCCLASS-DAG: Decl[InstanceMethod]/CurrNominal: ?.instanceFunc()[#ObjcClass#]{{; name=.+$}}
-// OPT_NO_DOT_OBJCCLASS: End completions
-
-// OBJCCLASS_MEMBERS_NO_DOT: Begin completions
-// OBJCCLASS_MEMBERS_NO_DOT-NEXT: Decl[InstanceVar]/CurrNominal: .instanceVar[#Int#]
-// OBJCCLASS_MEMBERS_NO_DOT-NEXT: Decl[InstanceMethod]/CurrNominal: .instanceFunc()[#ObjcClass#]
-// OBJCCLASS_MEMBERS_NO_DOT-NEXT: Decl[InfixOperatorFunction]/OtherModule[Swift]: === {#AnyObject?#}[#Bool#]
-// OBJCCLASS_MEMBERS_NO_DOT-NEXT: Decl[InfixOperatorFunction]/OtherModule[Swift]: !== {#AnyObject?#}[#Bool#]
-// OBJCCLASS_MEMBERS_NO_DOT-NEXT: Keyword[self]/CurrNominal: .self[#ObjcClass#]; name=self
-// OBJCCLASS_MEMBERS_NO_DOT-NEXT: End completions
-
-// OBJCCLASS_MEMBERS_DOT: Begin completions
-// OBJCCLASS_MEMBERS_DOT-NEXT: Keyword[self]/CurrNominal: self[#ObjcClass#]; name=self
-// OBJCCLASS_MEMBERS_DOT-NEXT: Decl[InstanceVar]/CurrNominal: instanceVar[#Int#]
-// OBJCCLASS_MEMBERS_DOT-NEXT: Decl[InstanceMethod]/CurrNominal: instanceFunc()[#ObjcClass#]
-// OBJCCLASS_MEMBERS_DOT-NEXT: End completions
//===---
//===--- Tests.
@@ -184,38 +118,6 @@
returnsImplicitlyUnwrappedOptional().#^UN_OPT_DOT_2^#
}
-func testAnyObject1(a: AnyObject) {
- a.instanceVar#^UN_OPT_NO_DOT_3^#
-}
-
-func testAnyObject2(a: AnyObject) {
- a.instanceVar.#^UN_OPT_DOT_3^#
-}
-
-func testAnyObject3(a: AnyObject) {
- a.instanceFunc!()#^OPT_DL_NO_DOT_1^#
-}
-
-func testAnyObject4(a: AnyObject) {
- a.instanceFunc?()#^OPT_DL_NO_DOT_2^#
-}
-
-func testAnyObject5(a: AnyObject) {
- a.instanceFunc!().#^OPT_DL_DOT_1^#
-}
-
-func testAnyObject6(a: AnyObject) {
- a.instanceFunc?().#^OPT_DL_DOT_2^#
-}
-
-func testAnyObject7(a: AnyObject) {
- (a.instanceFunc?())#^OPT_DL_FORCE_RETURN_OPTIONAL_1^#
-}
-
-func testAnyObject8(a: AnyObject) {
- (a as? ObjcClass)#^OPT_CAST_AS_RESULT_1^#
-}
-
func testOptionalTuple1(a: (Int, String)?) {
a#^OPT_TUPLE_1^#
}
@@ -245,3 +147,13 @@
}
// OPT_TUPLE_5: Pattern/CurrNominal/Erase[1]: ?.x[#Int#]
// OPT_TUPLE_5: Pattern/CurrNominal/Erase[1]: ?.y[#String#]
+
+// UN_OPT_NO_DOT_FOOSTRUCT: Begin completions
+// UN_OPT_NO_DOT_FOOSTRUCT-DAG: Decl[InstanceVar]/CurrNominal: .instanceVar[#Int#]{{; name=.+$}}
+// UN_OPT_NO_DOT_FOOSTRUCT-DAG: Decl[InstanceMethod]/CurrNominal: .instanceFunc()[#Void#]{{; name=.+$}}
+// UN_OPT_NO_DOT_FOOSTRUCT: End completions
+
+// UN_OPT_NO_DOT_FOOSTRUCT_RETURN: Begin completions
+// UN_OPT_NO_DOT_FOOSTRUCT_RETURN-DAG: Decl[InstanceVar]/CurrNominal: ?.instanceVar[#Int#]{{; name=.+$}}
+// UN_OPT_NO_DOT_FOOSTRUCT_RETURN-DAG: Decl[InstanceMethod]/CurrNominal: ?.instanceFunc()[#Void#]{{; name=.+$}}
+// UN_OPT_NO_DOT_FOOSTRUCT_RETURN: End completions
diff --git a/test/IDE/complete_stdlib_optional_objc.swift b/test/IDE/complete_stdlib_optional_objc.swift
new file mode 100644
index 0000000..46c5692
--- /dev/null
+++ b/test/IDE/complete_stdlib_optional_objc.swift
@@ -0,0 +1,90 @@
+// REQUIRES: objc_interop
+
+// RUN: %target-swift-ide-test -code-completion -source-filename %s -disable-objc-attr-requires-foundation-module -code-completion-token=UN_OPT_NO_DOT_3 > %t.opt.txt
+// RUN: %FileCheck %s -check-prefix=UN_OPT_NO_DOT_INT < %t.opt.txt
+
+// RUN: %target-swift-ide-test -code-completion -source-filename %s -disable-objc-attr-requires-foundation-module -code-completion-token=UN_OPT_DOT_3 > %t.opt.txt
+// RUN: %FileCheck %s -check-prefix=UN_OPT_DOT_INT < %t.opt.txt
+
+// RUN: %target-swift-ide-test -code-completion -source-filename %s -disable-objc-attr-requires-foundation-module -code-completion-token=OPT_DL_NO_DOT_1 > %t.opt.txt
+// RUN: %FileCheck %s -check-prefix=OBJCCLASS_MEMBERS_NO_DOT < %t.opt.txt
+
+// RUN: %target-swift-ide-test -code-completion -source-filename %s -disable-objc-attr-requires-foundation-module -code-completion-token=OPT_DL_NO_DOT_2 > %t.opt.txt
+// RUN: %FileCheck %s -check-prefix=OBJCCLASS_MEMBERS_NO_DOT < %t.opt.txt
+
+// RUN: %target-swift-ide-test -code-completion -source-filename %s -disable-objc-attr-requires-foundation-module -code-completion-token=OPT_DL_DOT_1 > %t.opt.txt
+// RUN: %FileCheck %s -check-prefix=OBJCCLASS_MEMBERS_DOT < %t.opt.txt
+
+// RUN: %target-swift-ide-test -code-completion -source-filename %s -disable-objc-attr-requires-foundation-module -code-completion-token=OPT_DL_DOT_2 > %t.opt.txt
+// RUN: %FileCheck %s -check-prefix=OBJCCLASS_MEMBERS_DOT < %t.opt.txt
+
+// RUN: %target-swift-ide-test -code-completion -source-filename %s -disable-objc-attr-requires-foundation-module -code-completion-token=OPT_DL_FORCE_RETURN_OPTIONAL_1 > %t.opt.txt
+// RUN: %FileCheck %s -check-prefix=OPT_NO_DOT_OBJCCLASS < %t.opt.txt
+
+// RUN: %target-swift-ide-test -code-completion -source-filename %s -disable-objc-attr-requires-foundation-module -code-completion-token=OPT_CAST_AS_RESULT_1 > %t.opt.txt
+// RUN: %FileCheck %s -check-prefix=OPT_NO_DOT_OBJCCLASS < %t.opt.txt
+
+@objc
+class ObjcClass {
+ @objc var instanceVar: Int = 0
+ @objc func instanceFunc() -> ObjcClass { return self }
+}
+
+func testAnyObject1(a: AnyObject) {
+ a.instanceVar#^UN_OPT_NO_DOT_3^#
+}
+
+func testAnyObject2(a: AnyObject) {
+ a.instanceVar.#^UN_OPT_DOT_3^#
+}
+
+func testAnyObject3(a: AnyObject) {
+ a.instanceFunc!()#^OPT_DL_NO_DOT_1^#
+}
+
+func testAnyObject4(a: AnyObject) {
+ a.instanceFunc?()#^OPT_DL_NO_DOT_2^#
+}
+
+func testAnyObject5(a: AnyObject) {
+ a.instanceFunc!().#^OPT_DL_DOT_1^#
+}
+
+func testAnyObject6(a: AnyObject) {
+ a.instanceFunc?().#^OPT_DL_DOT_2^#
+}
+
+func testAnyObject7(a: AnyObject) {
+ (a.instanceFunc?())#^OPT_DL_FORCE_RETURN_OPTIONAL_1^#
+}
+
+func testAnyObject8(a: AnyObject) {
+ (a as? ObjcClass)#^OPT_CAST_AS_RESULT_1^#
+}
+
+// UN_OPT_NO_DOT_INT: Begin completions
+// UN_OPT_NO_DOT_INT-DAG: Decl[InstanceVar]/CurrNominal: ?.nonzeroBitCount[#Int#]{{; name=.+$}}
+// UN_OPT_NO_DOT_INT: End completions
+
+// UN_OPT_DOT_INT: Begin completions
+// UN_OPT_DOT_INT-DAG: Decl[InstanceVar]/CurrNominal/Erase[1]: ?.nonzeroBitCount[#Int#]{{; name=.+$}}
+// UN_OPT_DOT_INT: End completions
+
+// OBJCCLASS_MEMBERS_NO_DOT: Begin completions
+// OBJCCLASS_MEMBERS_NO_DOT-NEXT: Decl[InstanceVar]/CurrNominal: .instanceVar[#Int#]
+// OBJCCLASS_MEMBERS_NO_DOT-NEXT: Decl[InstanceMethod]/CurrNominal: .instanceFunc()[#ObjcClass#]
+// OBJCCLASS_MEMBERS_NO_DOT-NEXT: Decl[InfixOperatorFunction]/OtherModule[Swift]: === {#AnyObject?#}[#Bool#]
+// OBJCCLASS_MEMBERS_NO_DOT-NEXT: Decl[InfixOperatorFunction]/OtherModule[Swift]: !== {#AnyObject?#}[#Bool#]
+// OBJCCLASS_MEMBERS_NO_DOT-NEXT: Keyword[self]/CurrNominal: .self[#ObjcClass#]; name=self
+// OBJCCLASS_MEMBERS_NO_DOT-NEXT: End completions
+
+// OBJCCLASS_MEMBERS_DOT: Begin completions
+// OBJCCLASS_MEMBERS_DOT-NEXT: Keyword[self]/CurrNominal: self[#ObjcClass#]; name=self
+// OBJCCLASS_MEMBERS_DOT-NEXT: Decl[InstanceVar]/CurrNominal: instanceVar[#Int#]
+// OBJCCLASS_MEMBERS_DOT-NEXT: Decl[InstanceMethod]/CurrNominal: instanceFunc()[#ObjcClass#]
+// OBJCCLASS_MEMBERS_DOT-NEXT: End completions
+
+// OPT_NO_DOT_OBJCCLASS: Begin completions
+// OPT_NO_DOT_OBJCCLASS-DAG: Decl[InstanceVar]/CurrNominal: ?.instanceVar[#Int#]{{; name=.+$}}
+// OPT_NO_DOT_OBJCCLASS-DAG: Decl[InstanceMethod]/CurrNominal: ?.instanceFunc()[#ObjcClass#]{{; name=.+$}}
+// OPT_NO_DOT_OBJCCLASS: End completions
diff --git a/test/IRGen/objc_attr_NSManaged.sil b/test/IRGen/objc_attr_NSManaged.sil
index 288388d..a87587f 100644
--- a/test/IRGen/objc_attr_NSManaged.sil
+++ b/test/IRGen/objc_attr_NSManaged.sil
@@ -25,9 +25,7 @@
// CHECK: @_PROPERTIES__TtC19objc_attr_NSManaged10SwiftGizmo = private constant { {{.*}}i32, i32, [1 x { i8*, i8* }] } { i32 16, i32 1, [1 x { i8*, i8* }] [{ i8*, i8* } { i8* getelementptr inbounds ([2 x i8], [2 x i8]* [[X]], i64 0, i64 0),
// The getter/setter should not show up in the Swift metadata.
-/* FIXME: sil_vtable parser picks the wrong 'init' overload. Both vtable entries
- ought to be nonnull here. rdar://problem/19572342 */
-// CHECK: @"$S19objc_attr_NSManaged10SwiftGizmoCMf" = internal global <{ {{.*}} }> <{ void (%T19objc_attr_NSManaged10SwiftGizmoC*)* @"$S19objc_attr_NSManaged10SwiftGizmoCfD", i8** @"$SBOWV", i64 ptrtoint (%objc_class* @"OBJC_METACLASS_$__TtC19objc_attr_NSManaged10SwiftGizmo" to i64), %objc_class* @"OBJC_CLASS_$_Gizmo", %swift.opaque* @_objc_empty_cache, %swift.opaque* null, i64 add (i64 ptrtoint ({ i32, i32, i32, i32, i8*, i8*, { i32, i32, [2 x { i8*, i8*, i8* }] }*, i8*, i8*, i8*, { i32, i32, [1 x { i8*, i8* }] }* }* @_DATA__TtC19objc_attr_NSManaged10SwiftGizmo to i64), i64 {{1|2}}), i32 {{1|0}}, i32 0, i32 8, i16 7, i16 0, i32 112, i32 16, {{.*}}* @"$S19objc_attr_NSManaged10SwiftGizmoCMn", i8* null, %T19objc_attr_NSManaged10SwiftGizmoC* (i64, %T19objc_attr_NSManaged10SwiftGizmoC*)* @"$S19objc_attr_NSManaged10SwiftGizmoC7bellsOnACSi_tcfc", i8* bitcast (void ()* @swift_deletedMethodError to i8*) }>
+// CHECK: @"$S19objc_attr_NSManaged10SwiftGizmoCMf" = internal global <{ {{.*}} }> <{ void (%T19objc_attr_NSManaged10SwiftGizmoC*)* @"$S19objc_attr_NSManaged10SwiftGizmoCfD", i8** @"$SBOWV", i64 ptrtoint (%objc_class* @"OBJC_METACLASS_$__TtC19objc_attr_NSManaged10SwiftGizmo" to i64), %objc_class* @"OBJC_CLASS_$_Gizmo", %swift.opaque* @_objc_empty_cache, %swift.opaque* null, i64 add (i64 ptrtoint ({ i32, i32, i32, i32, i8*, i8*, { i32, i32, [2 x { i8*, i8*, i8* }] }*, i8*, i8*, i8*, { i32, i32, [1 x { i8*, i8* }] }* }* @_DATA__TtC19objc_attr_NSManaged10SwiftGizmo to i64), i64 {{1|2}}), i32 {{1|0}}, i32 0, i32 8, i16 7, i16 0, i32 96, i32 16, {{.*}}* @"$S19objc_attr_NSManaged10SwiftGizmoCMn", i8* null }>
@objc class SwiftGizmo : Gizmo {
@objc @NSManaged var x: X
@@ -62,8 +60,5 @@
sil @$S19objc_attr_NSManaged10SwiftGizmoC7bellsOnSQyACGSi_tcfc : $@convention(method) (Int, @owned SwiftGizmo) -> Int
-/* FIXME: sil_vtable parser picks the wrong 'init' overload. rdar://problem/19572342 */
sil_vtable SwiftGizmo {
- // #SwiftGizmo.init!initializer.1: $S19objc_attr_NSManaged10SwiftGizmoCACycfc
- #SwiftGizmo.init!initializer.1: @$S19objc_attr_NSManaged10SwiftGizmoC7bellsOnACSi_tcfc
}
diff --git a/test/IRGen/objc_super.swift b/test/IRGen/objc_super.swift
index c8b86cb..dc9bfb5 100644
--- a/test/IRGen/objc_super.swift
+++ b/test/IRGen/objc_super.swift
@@ -97,7 +97,7 @@
// CHECK: [[CLASS:%.*]] = and i64 [[ISA]], [[ISAMASK]]
// CHECK: [[TY:%.*]] = inttoptr i64 [[CLASS]] to %swift.type*
// CHECK: [[CAST:%.*]] = bitcast %swift.type* [[TY]] to i64*
-// CHECK: [[OFFSETADDR:%.*]] = getelementptr inbounds i64, i64* [[CAST]], i64 19
+// CHECK: [[OFFSETADDR:%.*]] = getelementptr inbounds i64, i64* [[CAST]], i64 17
// CHECK: [[FIELDOFFSET:%.*]] = load i64, i64* [[OFFSETADDR]]
// CHECK: [[BYTEADDR:%.*]] = bitcast %T10objc_super13GenericRuncerC* %0 to i8*
// CHECK: [[FIELDADDR:%.*]] = getelementptr inbounds i8, i8* [[BYTEADDR]], i64 [[FIELDOFFSET]]
diff --git a/test/Index/kinds.swift b/test/Index/kinds.swift
index 36ecf46..f37d67c 100644
--- a/test/Index/kinds.swift
+++ b/test/Index/kinds.swift
@@ -225,18 +225,6 @@
// CHECK: [[@LINE-1]]:8 | instance-method/Swift | testMeNot() |
}
-@objc class TargetForIBAction {}
-// CHECK: [[@LINE-1]]:13 | class/Swift | TargetForIBAction | [[TargetForIBAction_USR:.*]] | Def |
-class AttrAnnots {
- @IBOutlet var iboutletString: AnyObject?
- // CHECK: [[@LINE-1]]:17 | instance-property(IB)/Swift | iboutletString |
- @IBAction func someibaction(o: TargetForIBAction) {}
- // CHECK: [[@LINE-1]]:18 | instance-method(IB)/Swift | someibaction(o:) | {{.*}} | Def,Dyn,RelChild,RelIBType | rel: 2
- // CHECK-NEXT: RelIBType | class/Swift | TargetForIBAction | [[TargetForIBAction_USR]]
- @GKInspectable var gkString = "gk"
- // CHECK: [[@LINE-1]]:22 | instance-property(GKI)/Swift | gkString |
-}
-
// CHECK: [[@LINE+1]]:7 | class/Swift | C1 | [[C1_USR:.*]] | Def | rel: 0
class C1 {}
// CHECK: [[@LINE+1]]:11 | type-alias/Swift | C1Alias | [[C1Alias_USR:.*]] | Def | rel: 0
diff --git a/test/Index/kinds_objc.swift b/test/Index/kinds_objc.swift
new file mode 100644
index 0000000..1abc2a3
--- /dev/null
+++ b/test/Index/kinds_objc.swift
@@ -0,0 +1,15 @@
+// RUN: %target-swift-ide-test -print-indexed-symbols -source-filename %s | %FileCheck %s
+// REQUIRES: objc_interop
+
+@objc class TargetForIBAction {}
+// CHECK: [[@LINE-1]]:13 | class/Swift | TargetForIBAction | [[TargetForIBAction_USR:.*]] | Def |
+class AttrAnnots {
+ @IBOutlet var iboutletString: AnyObject?
+ // CHECK: [[@LINE-1]]:17 | instance-property(IB)/Swift | iboutletString |
+ @IBAction func someibaction(o: TargetForIBAction) {}
+ // CHECK: [[@LINE-1]]:18 | instance-method(IB)/Swift | someibaction(o:) | {{.*}} | Def,Dyn,RelChild,RelIBType | rel: 2
+ // CHECK-NEXT: RelIBType | class/Swift | TargetForIBAction | [[TargetForIBAction_USR]]
+ @GKInspectable var gkString = "gk"
+ // CHECK: [[@LINE-1]]:22 | instance-property(GKI)/Swift | gkString |
+}
+
diff --git a/test/SILGen/Inputs/UIKit.swift b/test/SILGen/Inputs/UIKit.swift
index 1079d7e..6c89222 100644
--- a/test/SILGen/Inputs/UIKit.swift
+++ b/test/SILGen/Inputs/UIKit.swift
@@ -1,3 +1,4 @@
import Foundation
@_exported import UIKit
+public func UIApplicationMain() {}
diff --git a/test/SILGen/Inputs/usr/include/UIKit.h b/test/SILGen/Inputs/usr/include/UIKit.h
index 67df73c..bba1a98 100644
--- a/test/SILGen/Inputs/usr/include/UIKit.h
+++ b/test/SILGen/Inputs/usr/include/UIKit.h
@@ -3,6 +3,12 @@
@protocol UIApplicationDelegate
@end
+#ifdef SILGEN_TEST_UIAPPLICATIONMAIN_NULLABILITY
+int UIApplicationMain(int argc, char *_Nullable *_Nonnull argv,
+ NSString *_Nullable principalClassName,
+ NSString *_Nullable delegateClassName);
+#else
int UIApplicationMain(int argc, char **argv,
NSString *principalClassName,
NSString *delegateClassName);
+#endif
diff --git a/test/SILGen/UIApplicationMain.swift b/test/SILGen/UIApplicationMain.swift
index 3a2f0ad..a5ac911 100644
--- a/test/SILGen/UIApplicationMain.swift
+++ b/test/SILGen/UIApplicationMain.swift
@@ -1,9 +1,13 @@
// RUN: %empty-directory(%t)
// RUN: %build-silgen-test-overlays
+// RUN: %build-silgen-test-overlays-ios
// RUN: %target-swift-emit-silgen(mock-sdk: -sdk %S/Inputs -I %t) -parse-as-library %s | %FileCheck %s
// RUN: %target-swift-emit-ir(mock-sdk: -sdk %S/Inputs -I %t) -parse-as-library %s | %FileCheck %s -check-prefix=IR
+// RUN: %target-swift-emit-silgen(mock-sdk: -Xcc -DSILGEN_TEST_UIAPPLICATIONMAIN_NULLABILITY -sdk %S/Inputs -I %t) -parse-as-library %s | %FileCheck %s
+// RUN: %target-swift-emit-ir(mock-sdk: -Xcc -DSILGEN_TEST_UIAPPLICATIONMAIN_NULLABILITY -sdk %S/Inputs -I %t) -parse-as-library %s | %FileCheck %s -check-prefix=IR
+
// RUN: %target-swift-emit-silgen(mock-sdk: -sdk %S/Inputs -I %t) -parse-as-library %s -D REFERENCE | %FileCheck %s
// RUN: %target-swift-emit-ir(mock-sdk: -sdk %S/Inputs -I %t) -parse-as-library %s -D REFERENCE | %FileCheck %s -check-prefix=IR
diff --git a/test/SILGen/dynamic.swift b/test/SILGen/dynamic.swift
index 0c8b3ae..b25842c 100644
--- a/test/SILGen/dynamic.swift
+++ b/test/SILGen/dynamic.swift
@@ -545,7 +545,6 @@
// No vtable entry for override of @objc extension property
// CHECK-LABEL: sil_vtable [serialized] SubExt {
-// CHECK-NEXT: #BaseExt.init!initializer.1: (BaseExt.Type) -> () -> BaseExt : @$S7dynamic6SubExtCACycfc [override] // dynamic.SubExt.init() -> dynamic.SubExt
// CHECK-NEXT: #SubExt.deinit!deallocator: @$S7dynamic6SubExtCfD // dynamic.SubExt.__deallocating_deinit
// CHECK-NEXT: }
diff --git a/test/SILGen/lit.local.cfg b/test/SILGen/lit.local.cfg
index f946218..a8e15f8 100644
--- a/test/SILGen/lit.local.cfg
+++ b/test/SILGen/lit.local.cfg
@@ -5,3 +5,6 @@
'%target-swift-frontend(mock-sdk: -sdk %S/Inputs -I %t) -emit-module -enable-objc-interop -o %t %S/Inputs/ObjectiveC.swift && '
'%target-swift-frontend(mock-sdk: -sdk %S/Inputs -I %t) -emit-module -enable-objc-interop -o %t %S/Inputs/Dispatch.swift && '
'%target-swift-frontend(mock-sdk: -sdk %S/Inputs -I %t) -emit-module -enable-objc-interop -o %t %S/Inputs/Foundation.swift'))
+
+config.substitutions.insert(0, ('%build-silgen-test-overlays-ios',
+ '%target-swift-frontend(mock-sdk: -sdk %S/Inputs -I %t) -emit-module -enable-objc-interop -o %t %S/Inputs/UIKit.swift'))
diff --git a/test/SILGen/objc_attr_NSManaged.swift b/test/SILGen/objc_attr_NSManaged.swift
index e1c7556..dbb4f7c 100644
--- a/test/SILGen/objc_attr_NSManaged.swift
+++ b/test/SILGen/objc_attr_NSManaged.swift
@@ -119,16 +119,12 @@
// CHECK-LABEL: sil_vtable SwiftGizmo {
// CHECK-NEXT: #SwiftGizmo.modifyX!1: {{.*}} : @$S19objc_attr_NSManaged10SwiftGizmoC7modifyXyyF
// CHECK-NEXT: #SwiftGizmo.testFunc!1: {{.*}} : @$S19objc_attr_NSManaged10SwiftGizmoC8testFuncyyF
-// CHECK-NEXT: #SwiftGizmo.init!initializer.1: {{.*}} : @$S19objc_attr_NSManaged10SwiftGizmoCACSgycfc
-// CHECK-NEXT: #SwiftGizmo.init!initializer.1: {{.*}} : @$S19objc_attr_NSManaged10SwiftGizmoC7bellsOnACSgSi_tcfc
// CHECK-NEXT: #SwiftGizmo.deinit!deallocator: @$S19objc_attr_NSManaged10SwiftGizmoCfD
// CHECK-NEXT: }
// CHECK-LABEL: sil_vtable FinalGizmo {
// CHECK-NEXT: #SwiftGizmo.modifyX!1: {{.*}} : @$S19objc_attr_NSManaged10SwiftGizmoC7modifyX{{[_0-9a-zA-Z]*}}F
// CHECK-NEXT: #SwiftGizmo.testFunc!1: {{.*}} : @$S19objc_attr_NSManaged10SwiftGizmoC8testFunc{{[_0-9a-zA-Z]*}}F
-// CHECK-NEXT: #SwiftGizmo.init!initializer.1: {{.*}} : @$S19objc_attr_NSManaged10FinalGizmoC{{[_0-9a-zA-Z]*}}fc
-// CHECK-NEXT: #SwiftGizmo.init!initializer.1: {{.*}} : @$S19objc_attr_NSManaged10FinalGizmoC{{[_0-9a-zA-Z]*}}fc
// CHECK-NEXT: #FinalGizmo.deinit!deallocator: @$S19objc_attr_NSManaged10FinalGizmoCfD
// CHECK-NEXT: }
diff --git a/test/SILGen/objc_implicitly_unwrapped_optional.swift b/test/SILGen/objc_implicitly_unwrapped_optional.swift
deleted file mode 100644
index 3e2eba1..0000000
--- a/test/SILGen/objc_implicitly_unwrapped_optional.swift
+++ /dev/null
@@ -1,19 +0,0 @@
-// RUN: %target-swift-emit-sil(mock-sdk: %clang-importer-sdk) -enable-sil-ownership -assert-config Release %s | %FileCheck %s
-
-// REQUIRES: objc_interop
-
-import Foundation
-
-class C : Hive {}
-
-// CHECK-LABEL: sil private @$S34objc_implicitly_unwrapped_optional1DC5coderACSo7NSCoderC_tcfcAA1CCAdHSgAFSg_tcfcTV
-// CHECK: bb0(%0 : $Optional<NSCoder>, %1 : $D):
-// CHECK: [[THUNK:%.*]] = function_ref @$S34objc_implicitly_unwrapped_optional1DC5coderACSo7NSCoderC_tcfc
-// CHECK: [[REF:%.*]] = apply [[THUNK]]
-// CHECK: [[RESULT:%.*]] = enum $Optional<D>, #Optional.some!enumelt.1, [[REF]] : $D
-// CHECK: return [[RESULT]] : $Optional<D>
-class D : C {
- override init(coder aCoder: NSCoder) {
- super.init(coder: aCoder)
- }
-}
diff --git a/test/SILGen/vtables_objc.swift b/test/SILGen/vtables_objc.swift
index ecc1f20..726b4d3 100644
--- a/test/SILGen/vtables_objc.swift
+++ b/test/SILGen/vtables_objc.swift
@@ -59,16 +59,12 @@
// CHECK: sil_vtable Hoozit {
// CHECK-NEXT: #Hoozit.anse!1: {{.*}} : @$S12vtables_objc6HoozitC4anse{{[_0-9a-zA-Z]*}}F
// CHECK-NEXT: #Hoozit.incorrige!1: {{.*}} : @$S12vtables_objc6HoozitC9incorrige{{[_0-9a-zA-Z]*}}F
-// CHECK-NEXT: #Hoozit.init!initializer.1: (Hoozit.Type) -> () -> Hoozit? : @$S12vtables_objc6HoozitCACSgycfc
-// CHECK-NEXT: #Hoozit.init!initializer.1: (Hoozit.Type) -> (Int) -> Hoozit? : @$S12vtables_objc6HoozitC7bellsOnACSgSi_tcfc
// CHECK-NEXT: #Hoozit.deinit!deallocator: @$S12vtables_objc6HoozitCfD
// CHECK-NEXT: }
// CHECK: sil_vtable Wotsit {
// CHECK-NEXT: #Hoozit.anse!1: {{.*}} : @$S12vtables_objc6HoozitC4anse{{[_0-9a-zA-Z]*}}F
// CHECK-NEXT: #Hoozit.incorrige!1: {{.*}} : @$S12vtables_objc6WotsitC9incorrige{{[_0-9a-zA-Z]*}}F
-// CHECK-NEXT: #Hoozit.init!initializer.1: (Hoozit.Type) -> () -> Hoozit? : @$S12vtables_objc6WotsitCACSgycfc
-// CHECK-NEXT: #Hoozit.init!initializer.1: (Hoozit.Type) -> (Int) -> Hoozit? : @$S12vtables_objc6WotsitC7bellsOnACSgSi_tcfc
// CHECK-NEXT: #Wotsit.deinit!deallocator: @$S12vtables_objc6WotsitCfD
// CHECK-NEXT: }
diff --git a/test/Sema/implicit_initializer_multi.swift b/test/Sema/implicit_initializer_multi.swift
index 6786111..b60ca5b 100644
--- a/test/Sema/implicit_initializer_multi.swift
+++ b/test/Sema/implicit_initializer_multi.swift
@@ -1,4 +1,5 @@
// RUN: %target-swift-frontend -emit-silgen -primary-file %s %S/Inputs/implicit_initializer_multi_other.swift -verify
+// REQUIRES: objc_interop
func test() {
_ = DefaultInitializable()
diff --git a/test/attr/attr_dynamic.swift b/test/attr/attr_dynamic.swift
index a04a66e..963e784 100644
--- a/test/attr/attr_dynamic.swift
+++ b/test/attr/attr_dynamic.swift
@@ -12,20 +12,24 @@
class Foo {
@objc dynamic init() {}
@objc dynamic init(x: NotObjCAble) {} // expected-error{{method cannot be marked @objc because the type of the parameter cannot be represented in Objective-C}} expected-note{{Swift structs cannot be represented in Objective-C}}
-
+ // expected-error@-1{{'dynamic' initializer 'init(x:)' must also be '@objc}}
+
@objc dynamic var x: Int
-
+
@objc dynamic var nonObjcVar: NotObjCAble // expected-error{{property cannot be marked @objc because its type cannot be represented in Objective-C}} expected-note{{Swift structs cannot be represented in Objective-C}}
+ // expected-error@-1{{'dynamic' var 'nonObjcVar' must also be '@objc'}}
@objc dynamic func foo(x: Int) {}
@objc dynamic func bar(x: Int) {}
@objc dynamic func nonObjcFunc(x: NotObjCAble) {} // expected-error{{method cannot be marked @objc because the type of the parameter cannot be represented in Objective-C}} expected-note{{Swift structs cannot be represented in Objective-C}}
-
+ // expected-error@-1{{'dynamic' instance method 'nonObjcFunc(x:)' must also be '@objc'}}
+
@objc dynamic subscript(x: Int) -> ObjCClass { get {} }
@objc dynamic subscript(x: Int) -> NotObjCAble { get {} } // expected-error{{subscript cannot be marked @objc because its type cannot be represented in Objective-C}} expected-note{{Swift structs cannot be represented in Objective-C}}
-
+ // expected-error@-1{{'dynamic' subscript 'subscript' must also be '@objc'}}
+
dynamic deinit {} // expected-error{{'dynamic' modifier cannot be applied to this declaration}} {{3-11=}}
func notDynamic() {}
@@ -53,3 +57,9 @@
// CHECK: {{^}} override func notDynamic()
override func notDynamic() {}
}
+
+// SR-5317
+@objcMembers
+class ObjCMemberCheck {
+ dynamic var s = NotObjCAble(c: Foo()) // expected-error{{'dynamic' var 's' must also be '@objc'}}
+}
diff --git a/test/attr/attr_dynamic_infer.swift b/test/attr/attr_dynamic_infer.swift
index 3264184..23cce63 100644
--- a/test/attr/attr_dynamic_infer.swift
+++ b/test/attr/attr_dynamic_infer.swift
@@ -1,4 +1,5 @@
// RUN: %target-swift-ide-test -print-ast-typechecked -source-filename=%s -print-implicit-attrs -disable-objc-attr-requires-foundation-module | %FileCheck %s
+// REQUIRES: objc_interop
@objc class Super {
@objc dynamic func baseFoo() {}
@@ -36,17 +37,17 @@
// CHECK: @objc override dynamic var prop: Super
override var prop: Super {
- // CHECK: @objc override dynamic get
+ // CHECK: @objc dynamic get
get { return Super() }
- // CHECK: @objc override dynamic set
+ // CHECK: @objc dynamic set
set { }
}
// CHECK: @objc override dynamic subscript(sup: Super) -> Super
override subscript(sup: Super) -> Super {
- // CHECK: @objc override dynamic get
+ // CHECK: @objc dynamic get
get { return sup }
- // CHECK: @objc override dynamic set
+ // CHECK: @objc dynamic set
set { }
}
@@ -64,17 +65,17 @@
// CHECK: @objc final var prop: Super
@objc final var prop: Super {
- // CHECK: @objc final get
+ // CHECK: final get
get { return Super() }
- // CHECK: @objc final set
+ // CHECK: final set
set { }
}
// CHECK: @objc final subscript(sup: Super) -> Super
@objc final subscript(sup: Super) -> Super {
- // CHECK: @objc final get
+ // CHECK: final get
get { return sup }
- // CHECK: @objc final set
+ // CHECK: final set
set { }
}
diff --git a/test/attr/attr_ibaction.swift b/test/attr/attr_ibaction.swift
index 206f2df..b0d1651 100644
--- a/test/attr/attr_ibaction.swift
+++ b/test/attr/attr_ibaction.swift
@@ -75,21 +75,13 @@
// Protocol types
@IBAction func action7(_: P1) {} // expected-error{{argument to @IBAction method cannot have non-object type 'P1'}}
- // expected-error@-1{{method cannot be marked @IBAction because the type of the parameter cannot be represented in Objective-C}}
- // expected-note@-2{{protocol-constrained type containing protocol 'P1' cannot be represented in Objective-C}}
@IBAction func action8(_: CP1) {} // expected-error{{argument to @IBAction method cannot have non-object type 'CP1'}}
- // expected-error@-1{{method cannot be marked @IBAction because the type of the parameter cannot be represented in Objective-C}}
- // expected-note@-2{{protocol-constrained type containing protocol 'CP1' cannot be represented in Objective-C}}
@IBAction func action9(_: OP1) {}
@IBAction func action10(_: P1?) {} // expected-error{{argument to @IBAction method cannot have non-object type}}
- // expected-error@-1{{method cannot be marked @IBAction because the type of the parameter cannot be represented in Objective-C}}
@IBAction func action11(_: CP1?) {} // expected-error{{argument to @IBAction method cannot have non-object type}}
- // expected-error@-1{{method cannot be marked @IBAction because the type of the parameter cannot be represented in Objective-C}}
@IBAction func action12(_: OP1?) {}
@IBAction func action13(_: P1!) {} // expected-error{{argument to @IBAction method cannot have non-object type}}
- // expected-error@-1{{method cannot be marked @IBAction because the type of the parameter cannot be represented in Objective-C}}
@IBAction func action14(_: CP1!) {} // expected-error{{argument to @IBAction method cannot have non-object type}}
- // expected-error@-1{{method cannot be marked @IBAction because the type of the parameter cannot be represented in Objective-C}}
@IBAction func action15(_: OP1!) {}
// Class metatype
@@ -104,27 +96,17 @@
// Protocol types
@IBAction func action21(_: P1.Type) {} // expected-error{{argument to @IBAction method cannot have non-object type}}
- // expected-error@-1{{method cannot be marked @IBAction because the type of the parameter cannot be represented in Objective-C}}
@IBAction func action22(_: CP1.Type) {} // expected-error{{argument to @IBAction method cannot have non-object type}}
- // expected-error@-1{{method cannot be marked @IBAction because the type of the parameter cannot be represented in Objective-C}}
@IBAction func action23(_: OP1.Type) {} // expected-error{{argument to @IBAction method cannot have non-object type}}
@IBAction func action24(_: P1.Type?) {} // expected-error{{argument to @IBAction method cannot have non-object type}}
- // expected-error@-1{{method cannot be marked @IBAction because the type of the parameter cannot be represented in Objective-C}}
@IBAction func action25(_: CP1.Type?) {} // expected-error{{argument to @IBAction method cannot have non-object type}}
- // expected-error@-1{{method cannot be marked @IBAction because the type of the parameter cannot be represented in Objective-C}}
@IBAction func action26(_: OP1.Type?) {} // expected-error{{argument to @IBAction method cannot have non-object type}}
@IBAction func action27(_: P1.Type!) {} // expected-error{{argument to @IBAction method cannot have non-object type}}
- //expected-error@-1{{method cannot be marked @IBAction because the type of the parameter cannot be represented in Objective-C}}
@IBAction func action28(_: CP1.Type!) {} // expected-error{{argument to @IBAction method cannot have non-object type}}
- //expected-error@-1{{method cannot be marked @IBAction because the type of the parameter cannot be represented in Objective-C}}
@IBAction func action29(_: OP1.Type!) {} // expected-error{{argument to @IBAction method cannot have non-object type}}
// Other bad cases
@IBAction func action30(_: S) {} // expected-error{{argument to @IBAction method cannot have non-object type}}
- // expected-error@-1{{method cannot be marked @IBAction because the type of the parameter cannot be represented in Objective-C}}
- // expected-note@-2{{Swift structs cannot be represented in Objective-C}}
@IBAction func action31(_: E) {} // expected-error{{argument to @IBAction method cannot have non-object type}}
- // expected-error@-1{{method cannot be marked @IBAction because the type of the parameter cannot be represented in Objective-C}}
- // expected-note@-2{{non-'@objc' enums cannot be represented in Objective-C}}
init() { }
}
diff --git a/test/attr/attr_objc.swift b/test/attr/attr_objc.swift
index 25c6ef2..5949bb0 100644
--- a/test/attr/attr_objc.swift
+++ b/test/attr/attr_objc.swift
@@ -1676,7 +1676,6 @@
@IBAction func badAction(_ sender: PlainStruct?) { }
// expected-error@-1{{argument to @IBAction method cannot have non-object type 'PlainStruct?'}}
- // expected-error@-2{{method cannot be marked @IBAction because the type of the parameter cannot be represented in Objective-C}}
}
//===---
@@ -1716,6 +1715,7 @@
var badManaged: PlainStruct
// expected-error@-1 {{property cannot be marked @NSManaged because its type cannot be represented in Objective-C}}
// expected-note@-2 {{Swift structs cannot be represented in Objective-C}}
+ // expected-error@-3{{'dynamic' var 'badManaged' must also be '@objc'}}
// CHECK-LABEL: {{^}} @NSManaged var badManaged: PlainStruct
}
diff --git a/test/decl/class/circular_inheritance.swift b/test/decl/class/circular_inheritance.swift
index 8c6c9d3..8eca1c4 100644
--- a/test/decl/class/circular_inheritance.swift
+++ b/test/decl/class/circular_inheritance.swift
@@ -48,14 +48,10 @@
// CHECK: ===CYCLE DETECTED===
// CHECK-NEXT: `--{{.*}}SuperclassTypeRequest({{.*Left}}
-// CHECK-NEXT: `--{{.*}}InheritedTypeRequest(circular_inheritance.(file).Left@
-// CHECK-NEXT: `--{{.*}}AccessLevelRequest
-// CHECK-NEXT: `--{{.*}}AccessLevelRequest
-// CHECK-NEXT: `--{{.*}}SuperclassTypeRequest
-// CHECK-NEXT: `--{{.*}}InheritedTypeRequest(circular_inheritance.(file).Right@
-// CHECK-NEXT: `--{{.*}}AccessLevelRequest{{.*}}
-// CHECK-NEXT: `--{{.*}}AccessLevelRequest{{.*}}
-// CHECK-NEXT: `--{{.*}}SuperclassTypeRequest{{.*(cyclic dependency)}}
+// CHECK: `--{{.*}}InheritedTypeRequest(circular_inheritance.(file).Left@
+// CHECK: `--{{.*}}SuperclassTypeRequest
+// CHECK: `--{{.*}}InheritedTypeRequest(circular_inheritance.(file).Right@
+// CHECK: `--{{.*}}SuperclassTypeRequest{{.*(cyclic dependency)}}
// CHECK-DOT: digraph Dependencies
// CHECK-DOT: label="InheritedTypeRequest
diff --git a/test/decl/objc_override_multi.swift b/test/decl/objc_override_multi.swift
index b0eb7e1..deab0cd 100644
--- a/test/decl/objc_override_multi.swift
+++ b/test/decl/objc_override_multi.swift
@@ -4,5 +4,11 @@
class SubSub1 : Sub1 {
@objc func a() { } // expected-error{{method 'a()' with Objective-C selector 'a' conflicts with method 'f()' from superclass 'Super1' with the same Objective-C selector}}
+
+ func test() {
+ // Needed to force enough checking of Super1.f() to record its
+ // Objective-C selector.
+ f()
+ }
}
diff --git a/test/decl/var/NSManaged_properties.swift b/test/decl/var/NSManaged_properties.swift
index 82961ba..553a027 100644
--- a/test/decl/var/NSManaged_properties.swift
+++ b/test/decl/var/NSManaged_properties.swift
@@ -38,6 +38,7 @@
// expected-error@+1{{property cannot be marked @NSManaged because its type cannot be represented in Objective-C}}
@NSManaged var nonobjc_var: SwiftProto?
+ // expected-error@-1{{'dynamic' var 'nonobjc_var' must also be '@objc'}}
// expected-error@+4 {{@NSManaged only allowed on an instance property or method}}
// expected-error@+3 {{@NSManaged property cannot have an initial value}}
diff --git a/validation-test/Sema/OverridesAndOverloads.swift b/validation-test/Sema/OverridesAndOverloads.swift
index bb32680..d615864 100644
--- a/validation-test/Sema/OverridesAndOverloads.swift
+++ b/validation-test/Sema/OverridesAndOverloads.swift
@@ -328,8 +328,7 @@
}
Base().foo(C1()); expectEqual("foo(C1)", which)
- Base().foo(Token1()); expectEqual("foo(T)", which)
- Base().foo(Token1() as Any); expectEqual("foo(Any)", which)
+ Base().foo(Token1()); expectEqual("foo(Any)", which)
Base().bar(C1()); expectEqual("bar(C1)", which)
Base().bar(Token1()); expectEqual("bar(T)", which)
diff --git a/validation-test/Sema/type_checker_perf/slow/rdar33688063.swift b/validation-test/Sema/type_checker_perf/slow/rdar33688063.swift
index f4003c6..2c13ac1 100644
--- a/validation-test/Sema/type_checker_perf/slow/rdar33688063.swift
+++ b/validation-test/Sema/type_checker_perf/slow/rdar33688063.swift
@@ -1,5 +1,5 @@
// RUN: %target-typecheck-verify-swift -solver-expression-time-threshold=1 -swift-version 4
// REQUIRES: tools-release,no_asserts
-let _ = 1 | UInt32(0) << 0 | UInt32(1) << 1 | UInt32(2) << 2
+let _ = 1 | UInt32(0) << 0 | UInt32(1) << 1 | UInt32(2) << 2 | UInt32(3) << 3 | UInt32(4) << 4
// expected-error@-1 {{reasonable time}}
diff --git a/validation-test/compiler_crashers_2_fixed/0166-sr8240-2.swift b/validation-test/compiler_crashers_2_fixed/0166-sr8240-2.swift
index 0723703..fe2ed7e 100644
--- a/validation-test/compiler_crashers_2_fixed/0166-sr8240-2.swift
+++ b/validation-test/compiler_crashers_2_fixed/0166-sr8240-2.swift
@@ -9,7 +9,7 @@
}
extension Box where Representation == Repr, T == Representation.RawEnum {
init(rawEnumValue: Representation.RawEnum) {
- let _: Int.Type = T.self // expected-error {{cannot convert value of type '().Type' to specified type 'Int.Type'}}
+ let _: ().Type = T.self
fatalError()
}
}