Skip to content

Commit 6ac91cd

Browse files
authored
Merge pull request #71821 from slavapestov/inheritance-clause-fixes
Refactor protocol inheritance clauses and existential layout for non-copyable generics
2 parents 476298c + 6939740 commit 6ac91cd

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

54 files changed

+705
-693
lines changed

include/swift/AST/Decl.h

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -4389,10 +4389,6 @@ class NominalTypeDecl : public GenericTypeDecl, public IterableDeclContext {
43894389
/// Type if it `isEscapable` instead of using this.
43904390
CanBeInvertible::Result canBeEscapable() const;
43914391

4392-
/// Determine whether this type has `: <target>` stated explicitly in
4393-
/// its inheritance clause.
4394-
bool hasMarking(InvertibleProtocolKind target) const;
4395-
43964392
/// Determine whether this type has ~<target>` stated on
43974393
/// itself, one of its inherited types or `Self` requirements.
43984394
InverseMarking::Mark hasInverseMarking(InvertibleProtocolKind target) const;
@@ -5188,6 +5184,10 @@ class ProtocolDecl final : public NominalTypeDecl {
51885184
/// Retrieve the set of protocols inherited from this protocol.
51895185
ArrayRef<ProtocolDecl *> getInheritedProtocols() const;
51905186

5187+
/// Retrieve the transitive closure of the inherited protocols, not including
5188+
/// this protocol itself.
5189+
ArrayRef<ProtocolDecl *> getAllInheritedProtocols() const;
5190+
51915191
/// Determine whether this protocol has a superclass.
51925192
bool hasSuperclass() const { return (bool)getSuperclassDecl(); }
51935193

@@ -5255,10 +5255,6 @@ class ProtocolDecl final : public NominalTypeDecl {
52555255
/// Determine whether this protocol has ~<target>` stated on
52565256
/// itself, one of its inherited types or `Self` requirements.
52575257
InverseMarking::Mark hasInverseMarking(InvertibleProtocolKind target) const;
5258-
5259-
/// Determine whether this protocol requires conformance to `IP`, without
5260-
/// querying a generic signature.
5261-
bool requiresInvertible(InvertibleProtocolKind ip) const;
52625258

52635259
SourceLoc getStartLoc() const { return ProtocolLoc; }
52645260
SourceRange getSourceRange() const {

include/swift/AST/GenericSignature.h

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -225,9 +225,6 @@ class GenericSignature {
225225
/// requirement signature against the protocol generic signature
226226
/// <Self where Self : P>.
227227
void verify(ArrayRef<Requirement> reqts) const;
228-
229-
/// Returns a new signature with the given parameters erased
230-
GenericSignature typeErased(ArrayRef<Type> typeErasedParams) const;
231228
};
232229

233230
/// A reference to a canonical generic signature.

include/swift/AST/NameLookup.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -603,7 +603,7 @@ struct InheritedNominalEntry : Located<NominalTypeDecl *> {
603603
void getDirectlyInheritedNominalTypeDecls(
604604
llvm::PointerUnion<const TypeDecl *, const ExtensionDecl *> decl,
605605
unsigned i, llvm::SmallVectorImpl<InheritedNominalEntry> &result,
606-
bool &anyObject);
606+
InvertibleProtocolSet &inverses, bool &anyObject);
607607

608608
/// Retrieve the set of nominal type declarations that are directly
609609
/// "inherited" by the given declaration, looking through typealiases
@@ -612,7 +612,7 @@ void getDirectlyInheritedNominalTypeDecls(
612612
/// If we come across the AnyObject type, set \c anyObject true.
613613
SmallVector<InheritedNominalEntry, 4> getDirectlyInheritedNominalTypeDecls(
614614
llvm::PointerUnion<const TypeDecl *, const ExtensionDecl *> decl,
615-
bool &anyObject);
615+
InvertibleProtocolSet &inverses, bool &anyObject);
616616

617617
/// Retrieve the set of nominal type declarations that appear as the
618618
/// constraint type of any "Self" constraints in the where clause of the

include/swift/AST/NameLookupRequests.h

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,8 @@ void simple_display(
5858

5959
/// Describes a set of type declarations that are "direct" referenced by
6060
/// a particular type in the AST.
61-
using DirectlyReferencedTypeDecls = llvm::TinyPtrVector<TypeDecl *>;
61+
using DirectlyReferencedTypeDecls = std::pair<llvm::TinyPtrVector<TypeDecl *>,
62+
InvertibleProtocolSet>;
6263

6364
/// Request the set of declarations directly referenced by the an "inherited"
6465
/// type of a type or extension declaration.
@@ -198,6 +199,25 @@ class InheritedProtocolsRequest
198199
ArrayRef<ProtocolDecl *> result) const;
199200
};
200201

202+
class AllInheritedProtocolsRequest
203+
: public SimpleRequest<
204+
AllInheritedProtocolsRequest, ArrayRef<ProtocolDecl *>(ProtocolDecl *),
205+
RequestFlags::Cached> {
206+
public:
207+
using SimpleRequest::SimpleRequest;
208+
209+
private:
210+
friend SimpleRequest;
211+
212+
// Evaluation.
213+
ArrayRef<ProtocolDecl *>
214+
evaluate(Evaluator &evaluator, ProtocolDecl *PD) const;
215+
216+
public:
217+
// Caching
218+
bool isCached() const { return true; }
219+
};
220+
201221
class ProtocolRequirementsRequest
202222
: public SimpleRequest<ProtocolRequirementsRequest,
203223
ArrayRef<ValueDecl *>(ProtocolDecl *),
@@ -270,6 +290,7 @@ class ExtendedNominalRequest
270290

271291
struct SelfBounds {
272292
llvm::TinyPtrVector<NominalTypeDecl *> decls;
293+
InvertibleProtocolSet inverses;
273294
bool anyObject = false;
274295
};
275296

include/swift/AST/NameLookupTypeIDZone.def

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,9 @@ SWIFT_REQUEST(NameLookup, InheritedDeclsReferencedRequest,
4747
SWIFT_REQUEST(NameLookup, InheritedProtocolsRequest,
4848
ArrayRef<ProtocolDecl *>(ProtocolDecl *), SeparatelyCached,
4949
NoLocationInfo)
50+
SWIFT_REQUEST(NameLookup, AllInheritedProtocolsRequest,
51+
ArrayRef<ProtocolDecl *>(ProtocolDecl *), Cached,
52+
NoLocationInfo)
5053
SWIFT_REQUEST(NameLookup, ProtocolRequirementsRequest,
5154
ArrayRef<ValueDecl *>(ProtocolDecl *), SeparatelyCached,
5255
NoLocationInfo)

include/swift/AST/Requirement.h

Lines changed: 0 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -251,31 +251,11 @@ struct InverseRequirement {
251251

252252
InvertibleProtocolKind getKind() const;
253253

254-
/// Adds the type parameters of this generic context to the result if
255-
/// it has default requirements.
256-
static void enumerateDefaultedParams(GenericContext *decl,
257-
SmallVectorImpl<Type> &result);
258-
259254
/// Appends additional requirements corresponding to defaults for the given
260255
/// generic parameters.
261256
static void expandDefaults(ASTContext &ctx,
262257
ArrayRef<Type> gps,
263258
SmallVectorImpl<StructuralRequirement> &result);
264-
265-
/// Adds the inferred default protocols for an assumed generic parameter with
266-
/// respect to that parameter's inverses and existing required protocols.
267-
/// For example, if an inverse ~P exists, then P will not be added to the
268-
/// protocols list.
269-
///
270-
/// Similarly, if the protocols list has a protocol Q that already implies
271-
/// Copyable, then we will not add `Copyable` to the protocols list.
272-
///
273-
/// \param inverses the inverses '& ~P' that are applied to the generic param.
274-
/// \param protocols the existing required protocols, to which defaults will
275-
/// be appended.
276-
static void expandDefaults(ASTContext &ctx,
277-
InvertibleProtocolSet inverses,
278-
SmallVectorImpl<ProtocolDecl*> &protocols);
279259
};
280260

281261
} // end namespace swift

include/swift/AST/Types.h

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -5926,16 +5926,6 @@ class ProtocolType : public NominalType {
59265926
/// in the protocol list, then sorting them in some stable order.
59275927
static void canonicalizeProtocols(SmallVectorImpl<ProtocolDecl *> &protocols);
59285928

5929-
/// Visit all of the protocols in the given list of protocols, along with their
5930-
///
5931-
/// \param fn Visitor function called for each protocol (just once). If it
5932-
/// returns \c true, the visit operation will abort and return \c true.
5933-
///
5934-
/// \returns \c true if any invocation of \c fn returns \c true, and \c false
5935-
/// otherwise.
5936-
static bool visitAllProtocols(ArrayRef<ProtocolDecl *> protocols,
5937-
llvm::function_ref<bool(ProtocolDecl *)> fn);
5938-
59395929
private:
59405930
friend class NominalTypeDecl;
59415931
ProtocolType(ProtocolDecl *TheDecl, Type Parent, const ASTContext &Ctx,

include/swift/SIL/SILFunction.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,9 @@ class SILSpecializeAttr final {
9999
Partial
100100
};
101101

102+
static GenericSignature buildTypeErasedSignature(
103+
GenericSignature sig, ArrayRef<Type> typeErasedParams);
104+
102105
static SILSpecializeAttr *create(SILModule &M,
103106
GenericSignature specializedSignature,
104107
ArrayRef<Type> typeErasedParams,

lib/APIDigester/ModuleAnalyzerNodes.cpp

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1959,16 +1959,14 @@ void swift::ide::api::
19591959
SwiftDeclCollector::addConformancesToTypeDecl(SDKNodeDeclType *Root,
19601960
NominalTypeDecl *NTD) {
19611961
if (auto *PD = dyn_cast<ProtocolDecl>(NTD)) {
1962-
PD->walkInheritedProtocols([&](ProtocolDecl *inherited) {
1963-
if (PD != inherited && !Ctx.shouldIgnore(inherited)) {
1962+
for (auto *inherited : PD->getAllInheritedProtocols()) {
1963+
if (!Ctx.shouldIgnore(inherited)) {
19641964
ProtocolConformanceRef Conf(inherited);
19651965
auto ConfNode = SDKNodeInitInfo(Ctx, Conf)
19661966
.createSDKNode(SDKNodeKind::Conformance);
19671967
Root->addConformance(ConfNode);
19681968
}
1969-
1970-
return TypeWalker::Action::Continue;
1971-
});
1969+
}
19721970
} else {
19731971
// Avoid adding the same conformance twice.
19741972
SmallPtrSet<ProtocolConformance*, 4> Seen;

lib/AST/ASTContext.cpp

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -3914,15 +3914,6 @@ ProtocolCompositionType::build(const ASTContext &C, ArrayRef<Type> Members,
39143914
bool HasExplicitAnyObject) {
39153915
assert(Members.size() != 1 || HasExplicitAnyObject || !Inverses.empty());
39163916

3917-
#ifndef NDEBUG
3918-
for (auto member : Members) {
3919-
if (auto *proto = member->getAs<ProtocolType>()) {
3920-
assert(!proto->getDecl()->getInvertibleProtocolKind() &&
3921-
"Should have been folded away");
3922-
}
3923-
}
3924-
#endif
3925-
39263917
// Check to see if we've already seen this protocol composition before.
39273918
void *InsertPos = nullptr;
39283919
llvm::FoldingSetNodeID ID;

lib/AST/AccessRequests.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -248,7 +248,7 @@ DefaultAndMaxAccessLevelRequest::evaluate(Evaluator &evaluator,
248248

249249
// Try to scope the extension's access to the least public type mentioned
250250
// in its where clause.
251-
for (auto *typeDecl : typeDecls) {
251+
for (auto *typeDecl : typeDecls.first) {
252252
if (isa<TypeAliasDecl>(typeDecl) || isa<NominalTypeDecl>(typeDecl)) {
253253
auto scope = typeDecl->getFormalAccessScope(ED->getDeclContext());
254254
maxScope = maxScope->intersectWith(scope);

lib/AST/ConformanceLookupTable.cpp

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -209,9 +209,10 @@ void ConformanceLookupTable::forEachInStage(ConformanceStage stage,
209209
}
210210
} else if (next->getParentSourceFile() ||
211211
next->getParentModule()->isBuiltinModule()) {
212+
InvertibleProtocolSet inverses;
212213
bool anyObject = false;
213214
for (const auto &found :
214-
getDirectlyInheritedNominalTypeDecls(next, anyObject)) {
215+
getDirectlyInheritedNominalTypeDecls(next, inverses, anyObject)) {
215216
if (auto proto = dyn_cast<ProtocolDecl>(found.Item))
216217
protocols.push_back(
217218
{proto, found.Loc, found.uncheckedLoc, found.preconcurrencyLoc});
@@ -497,9 +498,10 @@ void ConformanceLookupTable::addInheritedProtocols(
497498
llvm::PointerUnion<const TypeDecl *, const ExtensionDecl *> decl,
498499
ConformanceSource source) {
499500
// Find all of the protocols in the inheritance list.
501+
InvertibleProtocolSet inverses;
500502
bool anyObject = false;
501503
for (const auto &found :
502-
getDirectlyInheritedNominalTypeDecls(decl, anyObject)) {
504+
getDirectlyInheritedNominalTypeDecls(decl, inverses, anyObject)) {
503505
if (auto proto = dyn_cast<ProtocolDecl>(found.Item)) {
504506
addProtocol(proto, found.Loc,
505507
source.withUncheckedLoc(found.uncheckedLoc)
@@ -525,6 +527,8 @@ void ConformanceLookupTable::addMacroGeneratedProtocols(
525527

526528
void ConformanceLookupTable::expandImpliedConformances(NominalTypeDecl *nominal,
527529
DeclContext *dc) {
530+
ASTContext &ctx = nominal->getASTContext();
531+
528532
// Note: recursive type-checking implies that AllConformances
529533
// may be reallocated during this traversal, so pay the lookup cost
530534
// during each iteration.
@@ -544,16 +548,23 @@ void ConformanceLookupTable::expandImpliedConformances(NominalTypeDecl *nominal,
544548
isa<EnumDecl>(nominal) && nominal->isObjC() &&
545549
cast<EnumDecl>(nominal)->hasCases() &&
546550
cast<EnumDecl>(nominal)->hasOnlyCasesWithoutAssociatedValues()) {
547-
ASTContext &ctx = nominal->getASTContext();
548551
if (auto bridgedNSError
549552
= ctx.getProtocol(KnownProtocolKind::BridgedNSError)) {
550553
addProtocol(bridgedNSError, SourceLoc(),
551554
ConformanceSource::forImplied(conformanceEntry));
552555
}
553556
}
554557

555-
addInheritedProtocols(conformingProtocol,
556-
ConformanceSource::forImplied(conformanceEntry));
558+
auto source = ConformanceSource::forImplied(conformanceEntry);
559+
for (auto *inherited : conformingProtocol->getInheritedProtocols()) {
560+
// Conforming a ~Copyable nominal to a protocol that inherits Copyable
561+
// should not imply a Copyable conformance on the nominal.
562+
if (ctx.LangOpts.hasFeature(Feature::NoncopyableGenerics))
563+
if (inherited->getInvertibleProtocolKind())
564+
continue;
565+
566+
addProtocol(inherited, SourceLoc(), source);
567+
}
557568
}
558569
}
559570

0 commit comments

Comments
 (0)