Skip to content

Commit ac465ea

Browse files
authored
Merge pull request swiftlang#70548 from kavon/ncgenerics-stdlib-building-v3
[NCGenerics] Even more fixes for building the stdlib (Part 3)
2 parents 3bdc2d2 + 5e050e6 commit ac465ea

37 files changed

+494
-100
lines changed

include/swift/AST/Decl.h

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5171,6 +5171,10 @@ class ProtocolDecl final : public NominalTypeDecl {
51715171
/// Determine whether this protocol inherits from the given ("super")
51725172
/// protocol.
51735173
bool inheritsFrom(const ProtocolDecl *Super) const;
5174+
5175+
/// Determine whether this protocol requires conformance to `IP`, without
5176+
/// querying a generic signature.
5177+
bool requiresInvertible(InvertibleProtocolKind ip) const;
51745178

51755179
SourceLoc getStartLoc() const { return ProtocolLoc; }
51765180
SourceRange getSourceRange() const {
@@ -5216,9 +5220,9 @@ class ProtocolDecl final : public NominalTypeDecl {
52165220
/// semantics but has no corresponding witness table.
52175221
bool isMarkerProtocol() const;
52185222

5219-
/// Determine whether this is an invertible protocol,
5220-
/// i.e., for a protocol P, the inverse constraint ~P exists.
5221-
bool isInvertibleProtocol() const;
5223+
/// Determine if this is an invertible protocol and return its kind,
5224+
/// i.e., for a protocol P, returns the kind if inverse constraint ~P exists.
5225+
llvm::Optional<InvertibleProtocolKind> getInvertibleProtocolKind() const;
52225226

52235227
private:
52245228
void computeKnownProtocolKind() const;

include/swift/AST/DiagnosticsSema.def

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7586,6 +7586,10 @@ WARNING(redundant_inverse_constraint,none,
75867586
ERROR(inverse_on_class, none,
75877587
"classes cannot be '~%0'",
75887588
(StringRef))
7589+
ERROR(inverse_with_class_constraint, none,
7590+
"composition involving %select{class requirement %2|'AnyObject'}0 "
7591+
"cannot contain '~%1'",
7592+
(bool, StringRef, Type))
75897593
ERROR(inverse_extension, none,
75907594
"cannot apply inverse %0 to extension",
75917595
(Type))

include/swift/AST/Expr.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3393,6 +3393,10 @@ class ErasureExpr final : public ImplicitConversionExpr,
33933393
Bits.ErasureExpr.NumArgumentConversions = argConversions.size();
33943394
std::uninitialized_copy(argConversions.begin(), argConversions.end(),
33953395
getTrailingObjects<ConversionPair>());
3396+
3397+
assert(llvm::all_of(conformances, [](ProtocolConformanceRef ref) {
3398+
return !ref.isInvalid();
3399+
}));
33963400
}
33973401

33983402
public:

include/swift/AST/Module.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -853,6 +853,13 @@ class ModuleDecl
853853
ProtocolConformanceRef conformsToProtocol(Type sourceTy,
854854
ProtocolDecl *targetProtocol);
855855

856+
/// Collect the conformances of \c fromType each of the protocols of an
857+
/// existential type's layout.
858+
ArrayRef<ProtocolConformanceRef>
859+
collectExistentialConformances(CanType fromType, CanType existential,
860+
bool skipConditionalRequirements = true,
861+
bool allowMissing = false);
862+
856863
/// Find a member named \p name in \p container that was declared in this
857864
/// module.
858865
///

include/swift/AST/ProtocolConformanceRef.h

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -128,7 +128,7 @@ class ProtocolConformanceRef {
128128
/// Determine whether this conformance (or a conformance it depends on)
129129
/// involves a "missing" conformance anywhere. Such conformances
130130
/// cannot be depended on to always exist.
131-
bool hasMissingConformance(ModuleDecl *module) const;
131+
bool hasMissingConformance() const;
132132

133133
/// Enumerate the missing conformances in this conformance.
134134
///
@@ -140,7 +140,6 @@ class ProtocolConformanceRef {
140140
/// \returns \c true if any invocation of \c fn returned true,
141141
/// \c false otherwise.
142142
bool forEachMissingConformance(
143-
ModuleDecl *module,
144143
llvm::function_ref<bool(BuiltinProtocolConformance *missing)> fn) const;
145144

146145
using OpaqueValue = void*;

include/swift/AST/TypeCheckRequests.h

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -323,6 +323,34 @@ class ExistentialConformsToSelfRequest :
323323
void cacheResult(bool value) const;
324324
};
325325

326+
class CollectExistentialConformancesRequest
327+
: public SimpleRequest<CollectExistentialConformancesRequest,
328+
ArrayRef<ProtocolConformanceRef>(ModuleDecl*,
329+
CanType,
330+
CanType,
331+
bool,
332+
bool),
333+
RequestFlags::Uncached> { // TODO: maybe cache this?
334+
public:
335+
using SimpleRequest::SimpleRequest;
336+
337+
private:
338+
friend SimpleRequest;
339+
340+
// Evaluation.
341+
ArrayRef<ProtocolConformanceRef>
342+
evaluate(Evaluator &evaluator,
343+
ModuleDecl *module,
344+
CanType fromType,
345+
CanType existential,
346+
bool skipConditionalRequirements,
347+
bool allowMissing) const;
348+
349+
public:
350+
// Caching.
351+
bool isCached() const { return true; }
352+
};
353+
326354
/// Determine whether an existential type conforming to this protocol
327355
/// requires the \c any syntax.
328356
class HasSelfOrAssociatedTypeRequirementsRequest :

include/swift/AST/TypeCheckerTypeIDZone.def

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,13 @@ SWIFT_REQUEST(TypeChecker, EnumRawTypeRequest,
100100
Type(EnumDecl *), Cached, NoLocationInfo)
101101
SWIFT_REQUEST(TypeChecker, ExistentialConformsToSelfRequest,
102102
bool(ProtocolDecl *), SeparatelyCached, NoLocationInfo)
103+
SWIFT_REQUEST(TypeChecker, CollectExistentialConformancesRequest,
104+
ArrayRef<ProtocolConformanceRef>(ModuleDecl*,
105+
CanType,
106+
CanType,
107+
bool,
108+
bool),
109+
Uncached, NoLocationInfo)
103110
SWIFT_REQUEST(TypeChecker, HasSelfOrAssociatedTypeRequirementsRequest,
104111
bool(ProtocolDecl *), SeparatelyCached, NoLocationInfo)
105112
SWIFT_REQUEST(TypeChecker, ExtendedTypeRequest, Type(ExtensionDecl *), Cached,

include/swift/AST/Types.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5873,6 +5873,7 @@ class ProtocolCompositionType final : public TypeBase,
58735873
private llvm::TrailingObjects<ProtocolCompositionType, Type> {
58745874
friend TrailingObjects;
58755875

5876+
// The inverse constraints `& ~IP` that are part of this composition.
58765877
InvertibleProtocolSet Inverses;
58775878

58785879
public:

lib/AST/ASTPrinter.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1470,6 +1470,10 @@ static void reconstituteInverses(GenericSignature genericSig,
14701470
for (auto tp : typeParams) {
14711471
assert(tp);
14721472

1473+
// Any generic parameter with a superclass bound could not have an inverse.
1474+
if (genericSig->getSuperclassBound(tp))
1475+
continue;
1476+
14731477
auto defaults = InverseRequirement::expandDefault(tp);
14741478
for (auto ip : defaults) {
14751479
auto *proto = ctx.getProtocol(getKnownProtocolKind(ip));

lib/AST/Decl.cpp

Lines changed: 35 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -6414,14 +6414,12 @@ bool ProtocolDecl::isMarkerProtocol() const {
64146414
return getAttrs().hasAttribute<MarkerAttr>();
64156415
}
64166416

6417-
bool ProtocolDecl::isInvertibleProtocol() const {
6418-
if (auto kp = getKnownProtocolKind()) {
6419-
if (getInvertibleProtocolKind(*kp)) {
6420-
assert(isMarkerProtocol());
6421-
return true;
6422-
}
6423-
}
6424-
return false;
6417+
llvm::Optional<InvertibleProtocolKind>
6418+
ProtocolDecl::getInvertibleProtocolKind() const {
6419+
if (auto kp = getKnownProtocolKind())
6420+
return ::getInvertibleProtocolKind(*kp);
6421+
6422+
return llvm::None;
64256423
}
64266424

64276425
ArrayRef<ProtocolDecl *> ProtocolDecl::getInheritedProtocols() const {
@@ -6560,9 +6558,14 @@ bool ProtocolDecl::walkInheritedProtocols(
65606558
}
65616559

65626560
bool ProtocolDecl::inheritsFrom(const ProtocolDecl *super) const {
6561+
assert(super);
6562+
65636563
if (this == super)
65646564
return false;
65656565

6566+
if (auto ip = super->getInvertibleProtocolKind())
6567+
return requiresInvertible(*ip);
6568+
65666569
return walkInheritedProtocols([super](ProtocolDecl *inherited) {
65676570
if (inherited == super)
65686571
return TypeWalker::Action::Stop;
@@ -6571,6 +6574,30 @@ bool ProtocolDecl::inheritsFrom(const ProtocolDecl *super) const {
65716574
});
65726575
}
65736576

6577+
bool ProtocolDecl::requiresInvertible(InvertibleProtocolKind ip) const {
6578+
// HACK: until we enable Feature::NoncopyableGenerics in the stdlib,
6579+
// hardcode the fact that an invertible protocol does not require any other!
6580+
if (getInvertibleProtocolKind())
6581+
return false;
6582+
6583+
auto kp = ::getKnownProtocolKind(ip);
6584+
return walkInheritedProtocols([kp, ip](ProtocolDecl *proto) {
6585+
if (proto->isSpecificProtocol(kp))
6586+
return TypeWalker::Action::Stop; // it is required.
6587+
6588+
switch (proto->getMarking(ip).getInverse().getKind()) {
6589+
case InverseMarking::Kind::None:
6590+
return TypeWalker::Action::Stop; // it is required.
6591+
6592+
case InverseMarking::Kind::LegacyExplicit:
6593+
case InverseMarking::Kind::Explicit:
6594+
case InverseMarking::Kind::Inferred:
6595+
// the implicit requirement was suppressed on this protocol, keep looking.
6596+
return TypeWalker::Action::Continue;
6597+
}
6598+
});
6599+
}
6600+
65746601
bool ProtocolDecl::requiresClass() const {
65756602
return evaluateOrDefault(getASTContext().evaluator,
65766603
ProtocolRequiresClassRequest{const_cast<ProtocolDecl *>(this)}, false);

0 commit comments

Comments
 (0)