|
31 | 31 | #include "swift/AST/LazyResolver.h"
|
32 | 32 | #include "swift/AST/ASTMangler.h"
|
33 | 33 | #include "swift/AST/Module.h"
|
| 34 | +#include "swift/AST/NameLookup.h" |
34 | 35 | #include "swift/AST/NameLookupRequests.h"
|
35 | 36 | #include "swift/AST/ParameterList.h"
|
36 | 37 | #include "swift/AST/Pattern.h"
|
@@ -3538,41 +3539,20 @@ ProtocolDecl::ProtocolDecl(DeclContext *DC, SourceLoc ProtocolLoc,
|
3538 | 3539 | llvm::TinyPtrVector<ProtocolDecl *>
|
3539 | 3540 | ProtocolDecl::getInheritedProtocols() const {
|
3540 | 3541 | llvm::TinyPtrVector<ProtocolDecl *> result;
|
3541 |
| - |
3542 |
| - // FIXME: Gather inherited protocols from the "inherited" list. |
3543 |
| - // We shouldn't need this, but it shows up in recursive invocations. |
3544 |
| - if (!isRequirementSignatureComputed()) { |
3545 |
| - SmallPtrSet<ProtocolDecl *, 4> known; |
3546 |
| - if (Bits.ProtocolDecl.ComputingInheritedProtocols) return result; |
3547 |
| - |
3548 |
| - auto *self = const_cast<ProtocolDecl *>(this); |
3549 |
| - self->Bits.ProtocolDecl.ComputingInheritedProtocols = true; |
3550 |
| - for (unsigned index : indices(getInherited())) { |
3551 |
| - if (auto type = getInheritedType(index)) { |
3552 |
| - // Only protocols can appear in the inheritance clause |
3553 |
| - // of a protocol -- anything else should get diagnosed |
3554 |
| - // elsewhere. |
3555 |
| - if (type->isExistentialType()) { |
3556 |
| - auto layout = type->getExistentialLayout(); |
3557 |
| - for (auto protoTy : layout.getProtocols()) { |
3558 |
| - auto *protoDecl = protoTy->getDecl(); |
3559 |
| - if (known.insert(protoDecl).second) |
3560 |
| - result.push_back(protoDecl); |
3561 |
| - } |
3562 |
| - } |
3563 |
| - } |
| 3542 | + SmallPtrSet<const ProtocolDecl *, 4> known; |
| 3543 | + known.insert(this); |
| 3544 | + bool anyObject = false; |
| 3545 | + for (const auto &found : |
| 3546 | + getDirectlyInheritedNominalTypeDecls( |
| 3547 | + const_cast<ProtocolDecl *>(this), anyObject)) { |
| 3548 | + if (auto proto = dyn_cast<ProtocolDecl>(found.second)) { |
| 3549 | + if (known.insert(proto).second) |
| 3550 | + result.push_back(proto); |
3564 | 3551 | }
|
3565 |
| - self->Bits.ProtocolDecl.ComputingInheritedProtocols = false; |
3566 |
| - return result; |
3567 | 3552 | }
|
3568 | 3553 |
|
3569 |
| - // Gather inherited protocols from the requirement signature. |
3570 |
| - auto selfType = getProtocolSelfType(); |
3571 |
| - for (const auto &req : getRequirementSignature()) { |
3572 |
| - if (req.getKind() == RequirementKind::Conformance && |
3573 |
| - req.getFirstType()->isEqual(selfType)) |
3574 |
| - result.push_back(req.getSecondType()->castTo<ProtocolType>()->getDecl()); |
3575 |
| - } |
| 3554 | + // FIXME: ComputingInheritedProtocols is dynamically dead. |
| 3555 | + |
3576 | 3556 | return result;
|
3577 | 3557 | }
|
3578 | 3558 |
|
@@ -3643,40 +3623,44 @@ bool ProtocolDecl::walkInheritedProtocols(
|
3643 | 3623 | bool ProtocolDecl::inheritsFrom(const ProtocolDecl *super) const {
|
3644 | 3624 | if (this == super)
|
3645 | 3625 | return false;
|
3646 |
| - |
3647 |
| - auto allProtocols = getLocalProtocols(); |
3648 |
| - return std::find(allProtocols.begin(), allProtocols.end(), super) |
3649 |
| - != allProtocols.end(); |
| 3626 | + |
| 3627 | + return walkInheritedProtocols([super](ProtocolDecl *inherited) { |
| 3628 | + if (inherited == super) |
| 3629 | + return TypeWalker::Action::Stop; |
| 3630 | + |
| 3631 | + return TypeWalker::Action::Continue; |
| 3632 | + }); |
3650 | 3633 | }
|
3651 | 3634 |
|
3652 | 3635 | bool ProtocolDecl::requiresClassSlow() {
|
3653 | 3636 | // Set this first to catch (invalid) circular inheritance.
|
3654 | 3637 | Bits.ProtocolDecl.RequiresClassValid = true;
|
| 3638 | + Bits.ProtocolDecl.RequiresClass = false; |
3655 | 3639 |
|
3656 | 3640 | // Quick check: @objc protocols require a class.
|
3657 |
| - if (isObjC()) { |
3658 |
| - Bits.ProtocolDecl.RequiresClass = true; |
3659 |
| - return true; |
3660 |
| - } |
3661 |
| - |
3662 |
| - // Otherwise, check if the inheritance clause contains a |
3663 |
| - // class-constrained existential. |
3664 |
| - // |
3665 |
| - // FIXME: Use the requirement signature if available. |
3666 |
| - Bits.ProtocolDecl.RequiresClass = false; |
3667 |
| - for (unsigned i : indices(getInherited())) { |
3668 |
| - Type type = getInheritedType(i); |
3669 |
| - assert(type && "Should have type checked inheritance clause by now"); |
3670 |
| - if (type->isExistentialType()) { |
3671 |
| - auto layout = type->getExistentialLayout(); |
3672 |
| - if (layout.requiresClass()) { |
3673 |
| - Bits.ProtocolDecl.RequiresClass = true; |
3674 |
| - return true; |
3675 |
| - } |
3676 |
| - } |
3677 |
| - if (type->getClassOrBoundGenericClass()) { |
3678 |
| - Bits.ProtocolDecl.RequiresClass = true; |
3679 |
| - return true; |
| 3641 | + if (isObjC()) |
| 3642 | + return Bits.ProtocolDecl.RequiresClass = true; |
| 3643 | + |
| 3644 | + // Determine the set of nominal types that this protocol inherits. |
| 3645 | + bool anyObject = false; |
| 3646 | + auto allInheritedNominals = |
| 3647 | + getDirectlyInheritedNominalTypeDecls(this, anyObject); |
| 3648 | + |
| 3649 | + // Quick check: do we inherit AnyObject? |
| 3650 | + if (anyObject) |
| 3651 | + return Bits.ProtocolDecl.RequiresClass = true; |
| 3652 | + |
| 3653 | + // Look through all of the inherited nominals for a superclass or a |
| 3654 | + // class-bound protocol. |
| 3655 | + for (const auto &found : allInheritedNominals) { |
| 3656 | + // Superclass bound. |
| 3657 | + if (isa<ClassDecl>(found.second)) |
| 3658 | + return Bits.ProtocolDecl.RequiresClass = true; |
| 3659 | + |
| 3660 | + // A protocol that might be class-constrained; |
| 3661 | + if (auto proto = dyn_cast<ProtocolDecl>(found.second)) { |
| 3662 | + if (proto->requiresClass()) |
| 3663 | + return Bits.ProtocolDecl.RequiresClass = true; |
3680 | 3664 | }
|
3681 | 3665 | }
|
3682 | 3666 |
|
|
0 commit comments