Skip to content

Commit 5e95ae6

Browse files
committed
[Sema] Pass down ProtocolConformance to DerivedConformance
Previously `getHashableConformance` was attempting to find the conformance itself, which could fail (rdar://129620291). Instead, pass down the known protocol conformance that we're deriving a witness for. No test case unfortunately as I haven't been able to come up with a reproducer. rdar://129620291
1 parent 9b31348 commit 5e95ae6

File tree

5 files changed

+25
-39
lines changed

5 files changed

+25
-39
lines changed

lib/Sema/AssociatedTypeInference.cpp

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2489,20 +2489,16 @@ AssociatedTypeInference::computeDefaultTypeWitness(
24892489
}
24902490

24912491
static std::pair<Type, TypeDecl *>
2492-
deriveTypeWitness(DeclContext *DC,
2493-
NominalTypeDecl *TypeDecl,
2494-
AssociatedTypeDecl *AssocType) {
2492+
deriveTypeWitness(const NormalProtocolConformance *Conformance,
2493+
NominalTypeDecl *TypeDecl, AssociatedTypeDecl *AssocType) {
24952494
auto *protocol = cast<ProtocolDecl>(AssocType->getDeclContext());
24962495

24972496
auto knownKind = protocol->getKnownProtocolKind();
24982497

24992498
if (!knownKind)
25002499
return std::make_pair(nullptr, nullptr);
25012500

2502-
auto Decl = DC->getInnermostDeclarationDeclContext();
2503-
2504-
DerivedConformance derived(TypeDecl->getASTContext(), Decl, TypeDecl,
2505-
protocol);
2501+
DerivedConformance derived(Conformance, TypeDecl, protocol);
25062502
switch (*knownKind) {
25072503
case KnownProtocolKind::RawRepresentable:
25082504
return std::make_pair(derived.deriveRawRepresentable(AssocType), nullptr);
@@ -2536,7 +2532,7 @@ AssociatedTypeInference::computeDerivedTypeWitness(
25362532
return std::make_pair(Type(), nullptr);
25372533

25382534
// Try to derive the type witness.
2539-
auto result = deriveTypeWitness(dc, derivingTypeDecl, assocType);
2535+
auto result = deriveTypeWitness(conformance, derivingTypeDecl, assocType);
25402536
if (!result.first)
25412537
return std::make_pair(Type(), nullptr);
25422538

lib/Sema/DerivedConformanceEquatableHashable.cpp

Lines changed: 1 addition & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -953,20 +953,6 @@ getHashValueRequirement(ASTContext &C) {
953953
return nullptr;
954954
}
955955

956-
static ProtocolConformance *
957-
getHashableConformance(const Decl *parentDecl) {
958-
ASTContext &C = parentDecl->getASTContext();
959-
const auto IDC = cast<IterableDeclContext>(parentDecl);
960-
auto hashableProto = C.getProtocol(KnownProtocolKind::Hashable);
961-
for (auto conformance: IDC->getLocalConformances(
962-
ConformanceLookupKind::NonStructural)) {
963-
if (conformance->getProtocol() == hashableProto) {
964-
return conformance;
965-
}
966-
}
967-
return nullptr;
968-
}
969-
970956
bool DerivedConformance::canDeriveHashable(NominalTypeDecl *type) {
971957
// FIXME: This is not actually correct. We cannot promise to always
972958
// provide a witness here in all cases. Unfortunately, figuring out
@@ -996,8 +982,7 @@ ValueDecl *DerivedConformance::deriveHashable(ValueDecl *requirement) {
996982
if (requirement->getBaseName() == Context.Id_hash) {
997983
// Start by resolving hashValue conformance.
998984
auto hashValueReq = getHashValueRequirement(Context);
999-
auto conformance = getHashableConformance(ConformanceDecl);
1000-
auto hashValueDecl = conformance->getWitnessDecl(hashValueReq);
985+
auto hashValueDecl = Conformance->getWitnessDecl(hashValueReq);
1001986
if (!hashValueDecl) {
1002987
// We won't derive hash(into:) if hashValue cannot be resolved.
1003988
// The hashValue failure will produce a diagnostic elsewhere.

lib/Sema/DerivedConformances.cpp

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -29,20 +29,23 @@ using namespace swift;
2929

3030
enum NonconformingMemberKind { AssociatedValue, StoredProperty };
3131

32-
DerivedConformance::DerivedConformance(ASTContext &ctx, Decl *conformanceDecl,
33-
NominalTypeDecl *nominal,
34-
ProtocolDecl *protocol)
35-
: Context(ctx), ConformanceDecl(conformanceDecl), Nominal(nominal),
36-
Protocol(protocol) {
37-
assert(getConformanceContext()->getSelfNominalTypeDecl() == nominal);
32+
DerivedConformance::DerivedConformance(
33+
const NormalProtocolConformance *conformance, NominalTypeDecl *nominal,
34+
ProtocolDecl *protocol)
35+
: Context(nominal->getASTContext()), Conformance(conformance),
36+
Nominal(nominal), Protocol(protocol) {
37+
auto *DC = Conformance->getDeclContext();
38+
ConformanceDecl = DC->getInnermostDeclarationDeclContext();
39+
assert(ConformanceDecl);
40+
assert(DC->getSelfNominalTypeDecl() == nominal);
3841
}
3942

4043
DeclContext *DerivedConformance::getConformanceContext() const {
41-
return cast<DeclContext>(ConformanceDecl);
44+
return Conformance->getDeclContext();
4245
}
4346

4447
ModuleDecl *DerivedConformance::getParentModule() const {
45-
return cast<DeclContext>(ConformanceDecl)->getParentModule();
48+
return getConformanceContext()->getParentModule();
4649
}
4750

4851
void DerivedConformance::addMembersToConformanceContext(

lib/Sema/DerivedConformances.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,11 +55,12 @@ class DerivedConformance {
5555

5656
public:
5757
ASTContext &Context;
58+
const NormalProtocolConformance *Conformance;
5859
Decl *ConformanceDecl;
5960
NominalTypeDecl *Nominal;
6061
ProtocolDecl *Protocol;
6162

62-
DerivedConformance(ASTContext &ctx, Decl *conformanceDecl,
63+
DerivedConformance(const NormalProtocolConformance *conformance,
6364
NominalTypeDecl *nominal, ProtocolDecl *protocol);
6465

6566
/// Retrieve the context in which the conformance is declared (either the

lib/Sema/TypeCheckProtocol.cpp

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4500,9 +4500,9 @@ ConformanceChecker::resolveWitnessViaLookup(ValueDecl *requirement) {
45004500
return ResolveWitnessResult::ExplicitFailed;
45014501
}
45024502

4503-
static ValueDecl *deriveProtocolRequirement(DeclContext *DC,
4504-
NominalTypeDecl *TypeDecl,
4505-
ValueDecl *Requirement) {
4503+
static ValueDecl *
4504+
deriveProtocolRequirement(const NormalProtocolConformance *Conformance,
4505+
NominalTypeDecl *TypeDecl, ValueDecl *Requirement) {
45064506
// Note: whenever you update this function, also update
45074507
// DerivedConformance::getDerivableRequirement.
45084508
const auto protocol = cast<ProtocolDecl>(Requirement->getDeclContext());
@@ -4511,12 +4511,12 @@ static ValueDecl *deriveProtocolRequirement(DeclContext *DC,
45114511
if (!derivableKind)
45124512
return nullptr;
45134513

4514+
auto *DC = Conformance->getDeclContext();
45144515
const auto Decl = DC->getInnermostDeclarationDeclContext();
45154516
if (Decl->isInvalid())
45164517
return nullptr;
45174518

4518-
DerivedConformance derived(TypeDecl->getASTContext(), Decl, TypeDecl,
4519-
protocol);
4519+
DerivedConformance derived(Conformance, TypeDecl, protocol);
45204520

45214521
switch (*derivableKind) {
45224522
case KnownDerivableProtocolKind::RawRepresentable:
@@ -4597,7 +4597,8 @@ ResolveWitnessResult ConformanceChecker::resolveWitnessViaDerivation(
45974597
}
45984598

45994599
// Attempt to derive the witness.
4600-
auto derived = deriveProtocolRequirement(DC, derivingTypeDecl, requirement);
4600+
auto derived =
4601+
deriveProtocolRequirement(Conformance, derivingTypeDecl, requirement);
46014602

46024603
if (!derived) {
46034604
return ResolveWitnessResult::ExplicitFailed;

0 commit comments

Comments
 (0)