Skip to content

Sema: Allow protocols with 'Self' constraints again #19844

New issue

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

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

Already on GitHub? Sign in to your account

Merged
merged 6 commits into from
Oct 12, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion include/swift/AST/DeclContext.h
Original file line number Diff line number Diff line change
Expand Up @@ -501,7 +501,7 @@ class alignas(1 << DeclContextAlignInBits) DeclContext {
/// lookup.
///
/// \returns true if anything was found.
bool lookupQualified(ArrayRef<TypeDecl *> types, DeclName member,
bool lookupQualified(ArrayRef<NominalTypeDecl *> types, DeclName member,
NLOptions options,
SmallVectorImpl<ValueDecl *> &decls) const;

Expand Down
7 changes: 7 additions & 0 deletions include/swift/AST/NameLookup.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ namespace swift {
class Type;
class TypeDecl;
class ValueDecl;
struct SelfBounds;

/// LookupResultEntry - One result of unqualified lookup.
struct LookupResultEntry {
Expand Down Expand Up @@ -374,6 +375,12 @@ getDirectlyInheritedNominalTypeDecls(
llvm::PointerUnion<TypeDecl *, ExtensionDecl *> decl,
bool &anyObject);

/// Retrieve the set of nominal type declarations that appear as the
/// constraint type of any "Self" constraints in the where clause of the
/// given protocol or protocol extension.
SelfBounds getSelfBoundsFromWhereClause(
llvm::PointerUnion<TypeDecl *, ExtensionDecl *> decl);

} // end namespace swift

#endif
15 changes: 10 additions & 5 deletions include/swift/AST/NameLookupRequests.h
Original file line number Diff line number Diff line change
Expand Up @@ -182,26 +182,31 @@ class ExtendedNominalRequest :
void noteCycleStep(DiagnosticEngine &diags) const;
};

struct SelfBounds {
llvm::TinyPtrVector<NominalTypeDecl *> decls;
bool anyObject = false;
};

/// Request the nominal types that occur as the right-hand side of "Self: Foo"
/// constraints in the "where" clause of a protocol extension.
class SelfBoundsFromWhereClauseRequest :
public SimpleRequest<SelfBoundsFromWhereClauseRequest,
CacheKind::Uncached,
llvm::TinyPtrVector<NominalTypeDecl *>,
ExtensionDecl *> {
SelfBounds,
llvm::PointerUnion<TypeDecl *, ExtensionDecl *>> {
public:
using SimpleRequest::SimpleRequest;

private:
friend SimpleRequest;

// Evaluation.
llvm::TinyPtrVector<NominalTypeDecl *> evaluate(Evaluator &evaluator,
ExtensionDecl *ext) const;
SelfBounds evaluate(Evaluator &evaluator,
llvm::PointerUnion<TypeDecl *, ExtensionDecl *>) const;

public:
// Cycle handling
llvm::TinyPtrVector<NominalTypeDecl *> breakCycle() const { return { }; }
SelfBounds breakCycle() const { return { }; }
void diagnoseCycle(DiagnosticEngine &diags) const;
void noteCycleStep(DiagnosticEngine &diags) const;
};
Expand Down
10 changes: 6 additions & 4 deletions lib/AST/Decl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3642,7 +3642,7 @@ ProtocolDecl::getInheritedProtocols() const {
SmallPtrSet<const ProtocolDecl *, 4> known;
known.insert(this);
bool anyObject = false;
for (const auto &found :
for (const auto found :
getDirectlyInheritedNominalTypeDecls(
const_cast<ProtocolDecl *>(this), anyObject)) {
if (auto proto = dyn_cast<ProtocolDecl>(found.second)) {
Expand Down Expand Up @@ -3758,12 +3758,14 @@ bool ProtocolDecl::requiresClassSlow() {
getDirectlyInheritedNominalTypeDecls(this, anyObject);

// Quick check: do we inherit AnyObject?
if (anyObject)
return Bits.ProtocolDecl.RequiresClass = true;
if (anyObject) {
Bits.ProtocolDecl.RequiresClass = true;
return true;
}

// Look through all of the inherited nominals for a superclass or a
// class-bound protocol.
for (const auto &found : allInheritedNominals) {
for (const auto found : allInheritedNominals) {
// Superclass bound.
if (isa<ClassDecl>(found.second))
return Bits.ProtocolDecl.RequiresClass = true;
Expand Down
25 changes: 12 additions & 13 deletions lib/AST/GenericSignatureBuilder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7251,19 +7251,18 @@ void GenericSignatureBuilder::enumerateRequirements(
// Enumerate conformance requirements.
SmallVector<ProtocolDecl *, 4> protocols;
DenseMap<ProtocolDecl *, const RequirementSource *> protocolSources;
if (equivClass) {
for (const auto &conforms : equivClass->conformsTo) {
protocols.push_back(conforms.first);
assert(protocolSources.count(conforms.first) == 0 &&
"redundant protocol requirement?");

protocolSources.insert(
{conforms.first,
*getBestConstraintSource<ProtocolDecl *>(conforms.second,
[&](ProtocolDecl *proto) {
return proto == conforms.first;
})});
}

for (const auto &conforms : equivClass->conformsTo) {
protocols.push_back(conforms.first);
assert(protocolSources.count(conforms.first) == 0 &&
"redundant protocol requirement?");

protocolSources.insert(
{conforms.first,
*getBestConstraintSource<ProtocolDecl *>(conforms.second,
[&](ProtocolDecl *proto) {
return proto == conforms.first;
})});
}

// Sort the protocols in canonical order.
Expand Down
Loading