Skip to content

Commit 33d7246

Browse files
authored
Merge pull request #7853 from DougGregor/normal-conformance-requirement-signature
2 parents 2561edd + ce718ee commit 33d7246

22 files changed

+208
-41
lines changed

include/swift/AST/ProtocolConformance.h

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -339,6 +339,10 @@ class NormalProtocolConformance : public ProtocolConformance,
339339
/// the requirements of those protocols.
340340
InheritedConformanceMap InheritedMapping;
341341

342+
/// Conformances that satisfy each of conformance requirements of the
343+
/// requirement signature of the protocol.
344+
ArrayRef<ProtocolConformanceRef> SignatureConformances;
345+
342346
LazyMemberLoader *Resolver = nullptr;
343347
uint64_t ResolverContextData;
344348

@@ -481,6 +485,17 @@ class NormalProtocolConformance : public ProtocolConformance,
481485
InheritedMapping[proto] = conformance;
482486
}
483487

488+
/// Retrieve the protocol conformances that satisfy the requirements of the
489+
/// protocol, which line up with the conformance constraints in the
490+
/// protocol's requirement signature.
491+
ArrayRef<ProtocolConformanceRef> getSignatureConformances() const {
492+
return SignatureConformances;
493+
}
494+
495+
/// Copy the given protocol conformances for the requirement signature into
496+
/// the normal conformance.
497+
void setSignatureConformances(ArrayRef<ProtocolConformanceRef> conformances);
498+
484499
/// Determine whether the witness for the given type requirement
485500
/// is the default definition.
486501
bool usesDefaultDefinition(AssociatedTypeDecl *requirement) const {

include/swift/AST/ProtocolConformanceRef.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,14 +20,15 @@
2020
#include "llvm/ADT/PointerUnion.h"
2121
#include "swift/AST/TypeAlignments.h"
2222
#include "swift/AST/Type.h"
23-
#include "swift/AST/ProtocolConformance.h"
2423

2524
namespace llvm {
2625
class raw_ostream;
2726
}
2827

2928
namespace swift {
3029

30+
class ProtocolConformance;
31+
3132
/// A ProtocolConformanceRef is a handle to a protocol conformance which
3233
/// may be either concrete or abstract.
3334
///

include/swift/Serialization/ModuleFormat.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ const uint16_t VERSION_MAJOR = 0;
5454
/// in source control, you should also update the comment to briefly
5555
/// describe what change you made. The content of this comment isn't important;
5656
/// it just ensures a conflict if two people change the module format.
57-
const uint16_t VERSION_MINOR = 322; // Last change: end_lifetime
57+
const uint16_t VERSION_MINOR = 323; // Last change: requirement conformances
5858

5959
using DeclID = PointerEmbeddedInt<unsigned, 31>;
6060
using DeclIDField = BCFixed<31>;

lib/AST/ASTContext.cpp

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
#include "swift/AST/LazyResolver.h"
2929
#include "swift/AST/ModuleLoader.h"
3030
#include "swift/AST/NameLookup.h"
31+
#include "swift/AST/ProtocolConformance.h"
3132
#include "swift/AST/RawComment.h"
3233
#include "swift/AST/SILLayout.h"
3334
#include "swift/AST/TypeCheckerDebugConsumer.h"
@@ -3606,6 +3607,36 @@ static NominalTypeDecl *findUnderlyingTypeInModule(ASTContext &ctx,
36063607
return nullptr;
36073608
}
36083609

3610+
bool ForeignRepresentationInfo::isRepresentableAsOptional() const {
3611+
switch (getKind()) {
3612+
case ForeignRepresentableKind::None:
3613+
llvm_unreachable("this type is not representable");
3614+
3615+
case ForeignRepresentableKind::Trivial:
3616+
return Storage.getPointer() != 0;
3617+
3618+
case ForeignRepresentableKind::Bridged: {
3619+
auto KPK_ObjectiveCBridgeable = KnownProtocolKind::ObjectiveCBridgeable;
3620+
ProtocolDecl *proto = getConformance()->getProtocol();
3621+
assert(proto->isSpecificProtocol(KPK_ObjectiveCBridgeable) &&
3622+
"unknown protocol; does it support optional?");
3623+
(void)proto;
3624+
(void)KPK_ObjectiveCBridgeable;
3625+
3626+
return true;
3627+
}
3628+
3629+
case ForeignRepresentableKind::BridgedError:
3630+
return true;
3631+
3632+
case ForeignRepresentableKind::Object:
3633+
case ForeignRepresentableKind::StaticBridged:
3634+
llvm_unreachable("unexpected kind in ForeignRepresentableCacheEntry");
3635+
}
3636+
3637+
llvm_unreachable("Unhandled ForeignRepresentableKind in switch.");
3638+
}
3639+
36093640
ForeignRepresentationInfo
36103641
ASTContext::getForeignRepresentationInfo(NominalTypeDecl *nominal,
36113642
ForeignLanguage language,

lib/AST/ASTDumper.cpp

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2615,10 +2615,18 @@ void ProtocolConformance::dump(llvm::raw_ostream &out, unsigned indent) const {
26152615
};
26162616

26172617
switch (getKind()) {
2618-
case ProtocolConformanceKind::Normal:
2618+
case ProtocolConformanceKind::Normal: {
2619+
auto normal = cast<NormalProtocolConformance>(this);
2620+
26192621
printCommon("normal");
26202622
// Maybe print information about the conforming context?
2623+
2624+
for (auto conformance : normal->getSignatureConformances()) {
2625+
out << '\n';
2626+
conformance.dump(out, indent + 2);
2627+
}
26212628
break;
2629+
}
26222630

26232631
case ProtocolConformanceKind::Inherited: {
26242632
auto conf = cast<InheritedProtocolConformance>(this);

lib/AST/ASTVerifier.cpp

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2025,6 +2025,40 @@ struct ASTNodeBase {};
20252025
continue;
20262026
}
20272027
}
2028+
2029+
// Make sure we have the right signature conformances.
2030+
if (!normal->isInvalid()){
2031+
auto conformances = normal->getSignatureConformances();
2032+
unsigned idx = 0;
2033+
for (auto req : proto->getRequirementSignature()->getRequirements()) {
2034+
if (req.getKind() != RequirementKind::Conformance)
2035+
continue;
2036+
2037+
if (idx >= conformances.size()) {
2038+
Out << "error: not enough conformances for requirement signature\n";
2039+
normal->dump(Out);
2040+
abort();
2041+
}
2042+
2043+
auto reqProto =
2044+
req.getSecondType()->castTo<ProtocolType>()->getDecl();
2045+
if (reqProto != conformances[idx].getRequirement()) {
2046+
Out << "error: wrong protocol in signature conformances: have "
2047+
<< conformances[idx].getRequirement()->getName().str()
2048+
<< ", expected " << reqProto->getName().str()<< "\n";
2049+
normal->dump(Out);
2050+
abort();
2051+
}
2052+
2053+
++idx;
2054+
}
2055+
2056+
if (idx != conformances.size()) {
2057+
Out << "error: too many conformances for requirement signature\n";
2058+
normal->dump(Out);
2059+
abort();
2060+
}
2061+
}
20282062
}
20292063

20302064
void verifyGenericEnvironment(Decl *D,

lib/AST/ForeignRepresentationInfo.h

Lines changed: 3 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -13,14 +13,15 @@
1313
#ifndef SWIFT_FOREIGNREPRESENTATIONINFO_H
1414
#define SWIFT_FOREIGNREPRESENTATIONINFO_H
1515

16-
#include "swift/AST/ProtocolConformance.h"
1716
#include "swift/AST/Type.h"
1817
#include "swift/Basic/LLVM.h"
1918
#include "llvm/ADT/PointerEmbeddedInt.h"
2019
#include "llvm/ADT/PointerIntPair.h"
2120

2221
namespace swift {
2322

23+
class ProtocolConformance;
24+
2425
class ForeignRepresentationInfo {
2526
using PayloadTy =
2627
llvm::PointerEmbeddedInt<uintptr_t, sizeof(uintptr_t) * CHAR_BIT - 3>;
@@ -112,35 +113,7 @@ class ForeignRepresentationInfo {
112113
}
113114

114115
/// Returns true if the optional version of this type is also representable.
115-
bool isRepresentableAsOptional() const {
116-
switch (getKind()) {
117-
case ForeignRepresentableKind::None:
118-
llvm_unreachable("this type is not representable");
119-
120-
case ForeignRepresentableKind::Trivial:
121-
return Storage.getPointer() != 0;
122-
123-
case ForeignRepresentableKind::Bridged: {
124-
auto KPK_ObjectiveCBridgeable = KnownProtocolKind::ObjectiveCBridgeable;
125-
ProtocolDecl *proto = getConformance()->getProtocol();
126-
assert(proto->isSpecificProtocol(KPK_ObjectiveCBridgeable) &&
127-
"unknown protocol; does it support optional?");
128-
(void)proto;
129-
(void)KPK_ObjectiveCBridgeable;
130-
131-
return true;
132-
}
133-
134-
case ForeignRepresentableKind::BridgedError:
135-
return true;
136-
137-
case ForeignRepresentableKind::Object:
138-
case ForeignRepresentableKind::StaticBridged:
139-
llvm_unreachable("unexpected kind in ForeignRepresentableCacheEntry");
140-
}
141-
142-
llvm_unreachable("Unhandled ForeignRepresentableKind in switch.");
143-
}
116+
bool isRepresentableAsOptional() const;
144117
};
145118

146119
} // end namespace swift

lib/AST/ProtocolConformance.cpp

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -252,6 +252,25 @@ AbstractStorageDecl *ProtocolConformance::getBehaviorDecl() const {
252252
return getRootNormalConformance()->getBehaviorDecl();
253253
}
254254

255+
void NormalProtocolConformance::setSignatureConformances(
256+
ArrayRef<ProtocolConformanceRef> conformances) {
257+
auto &ctx = getProtocol()->getASTContext();
258+
SignatureConformances = ctx.AllocateCopy(conformances);
259+
260+
#if !NDEBUG
261+
unsigned idx = 0;
262+
for (auto req : getProtocol()->getRequirementSignature()->getRequirements()) {
263+
if (req.getKind() == RequirementKind::Conformance) {
264+
assert(idx < conformances.size());
265+
assert(conformances[idx].getRequirement() ==
266+
req.getSecondType()->castTo<ProtocolType>()->getDecl());
267+
++idx;
268+
}
269+
}
270+
assert(idx == conformances.size() && "Too many conformances");
271+
#endif
272+
}
273+
255274
void NormalProtocolConformance::resolveLazyInfo() const {
256275
assert(Resolver);
257276
assert(isComplete());

lib/AST/Type.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
#include "swift/AST/GenericEnvironment.h"
2424
#include "swift/AST/LazyResolver.h"
2525
#include "swift/AST/Module.h"
26+
#include "swift/AST/ProtocolConformance.h"
2627
#include "swift/AST/SubstitutionMap.h"
2728
#include "swift/AST/TypeLoc.h"
2829
#include "llvm/ADT/APFloat.h"

lib/ClangImporter/ImportDecl.cpp

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6952,6 +6952,7 @@ void ClangImporter::Implementation::finishProtocolConformance(
69526952
};
69536953
return getDeclName(*left).compare(getDeclName(*right));
69546954
});
6955+
69556956
// Schedule any that aren't complete.
69566957
for (auto *inherited : inheritedProtos) {
69576958
ModuleDecl *M = conformance->getDeclContext()->getParentModule();
@@ -6964,6 +6965,24 @@ void ClangImporter::Implementation::finishProtocolConformance(
69646965
inheritedConformance->getConcrete());
69656966
}
69666967

6968+
// Collect conformances for the requirement signature.
6969+
SmallVector<ProtocolConformanceRef, 4> reqConformances;
6970+
for (auto req : proto->getRequirementSignature()->getRequirements()) {
6971+
if (req.getKind() != RequirementKind::Conformance)
6972+
continue;
6973+
6974+
assert(req.getFirstType()->isEqual(proto->getSelfInterfaceType()));
6975+
auto reqProto = req.getSecondType()->castTo<ProtocolType>()->getDecl();
6976+
6977+
ModuleDecl *M = conformance->getDeclContext()->getParentModule();
6978+
auto reqConformance = M->lookupConformance(conformance->getType(),
6979+
reqProto, /*resolver=*/nullptr);
6980+
assert(reqConformance && reqConformance->isConcrete() &&
6981+
"required conformance not found");
6982+
reqConformances.push_back(*reqConformance);
6983+
}
6984+
conformance->setSignatureConformances(reqConformances);
6985+
69676986
conformance->setState(ProtocolConformanceState::Complete);
69686987
}
69696988

lib/Sema/CSApply.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
#include "ConstraintSystem.h"
2020
#include "swift/AST/ASTVisitor.h"
2121
#include "swift/AST/ASTWalker.h"
22+
#include "swift/AST/ProtocolConformance.h"
2223
#include "swift/AST/SubstitutionMap.h"
2324
#include "swift/Basic/StringExtras.h"
2425
#include "llvm/ADT/APFloat.h"

lib/Sema/CSRanking.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
//
1616
//===----------------------------------------------------------------------===//
1717
#include "ConstraintSystem.h"
18+
#include "swift/AST/ProtocolConformance.h"
1819
#include "llvm/ADT/Statistic.h"
1920
#include "llvm/Support/Compiler.h"
2021

lib/Sema/CodeSynthesis.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
#include "swift/AST/Expr.h"
2424
#include "swift/AST/GenericEnvironment.h"
2525
#include "swift/AST/ParameterList.h"
26+
#include "swift/AST/ProtocolConformance.h"
2627
#include "swift/Basic/Defer.h"
2728
#include "llvm/ADT/SmallString.h"
2829
#include "llvm/ADT/StringExtras.h"

lib/Sema/ConstraintSystem.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,6 @@
2929
#include "swift/AST/ASTVisitor.h"
3030
#include "swift/AST/ASTWalker.h"
3131
#include "swift/AST/NameLookup.h"
32-
#include "swift/AST/ProtocolConformance.h"
3332
#include "swift/AST/Types.h"
3433
#include "swift/AST/TypeCheckerDebugConsumer.h"
3534
#include "llvm/ADT/ilist.h"

lib/Sema/TypeCheckConstraints.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1388,6 +1388,11 @@ bool GenericRequirementsCheckListener::shouldCheck(RequirementKind kind,
13881388
return true;
13891389
}
13901390

1391+
void GenericRequirementsCheckListener::satisfiedConformance(
1392+
Type depTy, Type replacementTy,
1393+
ProtocolConformanceRef conformance) {
1394+
}
1395+
13911396
bool TypeChecker::
13921397
solveForExpression(Expr *&expr, DeclContext *dc, Type convertType,
13931398
FreeTypeVariableBinding allowFreeTypeVariables,

lib/Sema/TypeCheckDecl.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
#include "swift/AST/GenericSignatureBuilder.h"
3131
#include "swift/AST/NameLookup.h"
3232
#include "swift/AST/PrettyStackTrace.h"
33+
#include "swift/AST/ProtocolConformance.h"
3334
#include "swift/AST/ReferencedNameTracker.h"
3435
#include "swift/AST/TypeWalker.h"
3536
#include "swift/Basic/Statistic.h"

lib/Sema/TypeCheckGeneric.cpp

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1124,10 +1124,13 @@ std::pair<bool, bool> TypeChecker::checkGenericArguments(
11241124
UnsatisfiedDependency *unsatisfiedDependency,
11251125
ConformanceCheckOptions conformanceOptions,
11261126
GenericRequirementsCheckListener *listener) {
1127+
bool valid = true;
1128+
11271129
for (const auto &rawReq : genericSig->getRequirements()) {
11281130
auto req = rawReq.subst(substitutions, conformances);
11291131
if (!req) {
11301132
// Another requirement will fail later; just continue.
1133+
valid = false;
11311134
continue;
11321135
}
11331136

@@ -1138,8 +1141,10 @@ std::pair<bool, bool> TypeChecker::checkGenericArguments(
11381141
if (kind != RequirementKind::Layout) {
11391142
rawSecondType = rawReq.getSecondType();
11401143
secondType = req->getSecondType().subst(substitutions, conformances);
1141-
if (!secondType)
1144+
if (!secondType) {
1145+
valid = false;
11421146
continue;
1147+
}
11431148
}
11441149

11451150
if (listener && !listener->shouldCheck(kind, firstType, secondType))
@@ -1165,6 +1170,12 @@ std::pair<bool, bool> TypeChecker::checkGenericArguments(
11651170
if (!result.second)
11661171
return std::make_pair(false, false);
11671172

1173+
// Report the conformance.
1174+
if (listener) {
1175+
listener->satisfiedConformance(rawReq.getFirstType(), firstType,
1176+
*result.second);
1177+
}
1178+
11681179
continue;
11691180
}
11701181

@@ -1207,5 +1218,5 @@ std::pair<bool, bool> TypeChecker::checkGenericArguments(
12071218
}
12081219
}
12091220

1210-
return std::make_pair(false, true);
1221+
return std::make_pair(false, valid);
12111222
}

0 commit comments

Comments
 (0)