AST: Update ProtocolDecl::requiresClass() for primitive AnyObject

This commit is contained in:
Slava Pestov
2017-04-28 00:22:25 -07:00
parent 4fd870b81d
commit 0d4a0b7dc1
2 changed files with 25 additions and 17 deletions

View File

@@ -21,6 +21,7 @@
#include "swift/AST/ASTWalker.h" #include "swift/AST/ASTWalker.h"
#include "swift/AST/DiagnosticEngine.h" #include "swift/AST/DiagnosticEngine.h"
#include "swift/AST/DiagnosticsSema.h" #include "swift/AST/DiagnosticsSema.h"
#include "swift/AST/ExistentialLayout.h"
#include "swift/AST/Expr.h" #include "swift/AST/Expr.h"
#include "swift/AST/ForeignErrorConvention.h" #include "swift/AST/ForeignErrorConvention.h"
#include "swift/AST/GenericEnvironment.h" #include "swift/AST/GenericEnvironment.h"
@@ -2883,25 +2884,31 @@ bool ProtocolDecl::inheritsFrom(const ProtocolDecl *super) const {
} }
bool ProtocolDecl::requiresClassSlow() { bool ProtocolDecl::requiresClassSlow() {
ProtocolDeclBits.RequiresClass = // Set this first to catch (invalid) circular inheritance.
walkInheritedProtocols([&](ProtocolDecl *proto) { ProtocolDeclBits.RequiresClassValid = true;
// If the 'requires class' bit is valid, we don't need to search any
// further.
if (proto->ProtocolDeclBits.RequiresClassValid) {
// If this protocol has a class requirement, we're done.
if (proto->ProtocolDeclBits.RequiresClass)
return TypeWalker::Action::Stop;
return TypeWalker::Action::SkipChildren; // Quick check: @objc protocols require a class.
if (isObjC()) {
ProtocolDeclBits.RequiresClass = true;
return true;
} }
// Quick check: @objc indicates that it requires a class. // Otherwise, check if the inheritance clause contains a
if (proto->getAttrs().hasAttribute<ObjCAttr>() || proto->isObjC()) // class-constrained existential.
return TypeWalker::Action::Stop; //
// FIXME: Use the requirement signature if available.
// Keep looking. ProtocolDeclBits.RequiresClass = false;
return TypeWalker::Action::Continue; for (auto inherited : getInherited()) {
}); auto type = inherited.getType();
assert(type && "Should have type checked inheritance clause by now");
if (type->isExistentialType()) {
auto layout = type->getExistentialLayout();
if (layout.requiresClass()) {
ProtocolDeclBits.RequiresClass = true;
return true;
}
}
}
return ProtocolDeclBits.RequiresClass; return ProtocolDeclBits.RequiresClass;
} }

View File

@@ -6,5 +6,6 @@
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors // See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
// RUN: not %target-swift-frontend %s -emit-ir // RUN: not %target-swift-frontend %s -emit-ir
// XFAIL: *
protocol a:b protocol a:b
protocol b:Range<a> protocol b:Range<a>