Skip to content

Commit 3c6b0bd

Browse files
authored
Merge pull request #74680 from hamishknight/confirmance
[Sema] Pass down ProtocolConformance to DerivedConformance
2 parents 5056e79 + 7429222 commit 3c6b0bd

File tree

6 files changed

+29
-65
lines changed

6 files changed

+29
-65
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: 5 additions & 22 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
@@ -985,21 +971,18 @@ void DerivedConformance::tryDiagnoseFailedHashableDerivation(
985971
}
986972

987973
ValueDecl *DerivedConformance::deriveHashable(ValueDecl *requirement) {
988-
ASTContext &C = ConformanceDecl->getASTContext();
989-
990974
// var hashValue: Int
991-
if (requirement->getBaseName() == C.Id_hashValue) {
975+
if (requirement->getBaseName() == Context.Id_hashValue) {
992976
// We always allow hashValue to be synthesized; invalid cases are diagnosed
993977
// during hash(into:) synthesis.
994978
return deriveHashable_hashValue(*this);
995979
}
996980

997981
// Hashable.hash(into:)
998-
if (requirement->getBaseName() == C.Id_hash) {
982+
if (requirement->getBaseName() == Context.Id_hash) {
999983
// Start by resolving hashValue conformance.
1000-
auto hashValueReq = getHashValueRequirement(C);
1001-
auto conformance = getHashableConformance(ConformanceDecl);
1002-
auto hashValueDecl = conformance->getWitnessDecl(hashValueReq);
984+
auto hashValueReq = getHashValueRequirement(Context);
985+
auto hashValueDecl = Conformance->getWitnessDecl(hashValueReq);
1003986
if (!hashValueDecl) {
1004987
// We won't derive hash(into:) if hashValue cannot be resolved.
1005988
// The hashValue failure will produce a diagnostic elsewhere.
@@ -1011,7 +994,7 @@ ValueDecl *DerivedConformance::deriveHashable(ValueDecl *requirement) {
1011994

1012995
// Refuse to synthesize Hashable if type isn't a struct or enum, or if it
1013996
// has non-Hashable stored properties/associated values.
1014-
auto hashableProto = C.getProtocol(KnownProtocolKind::Hashable);
997+
auto hashableProto = Context.getProtocol(KnownProtocolKind::Hashable);
1015998
if (!canDeriveConformance(getConformanceContext(), Nominal,
1016999
hashableProto)) {
10171000
ConformanceDecl->diagnose(diag::type_does_not_conform,

lib/Sema/DerivedConformances.cpp

Lines changed: 12 additions & 9 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(
@@ -280,7 +283,7 @@ void DerivedConformance::diagnoseIfSynthesisUnsupportedForDecl(
280283
ValueDecl *DerivedConformance::getDerivableRequirement(NominalTypeDecl *nominal,
281284
ValueDecl *requirement) {
282285
// Note: whenever you update this function, also update
283-
// TypeChecker::deriveProtocolRequirement.
286+
// deriveProtocolRequirement.
284287
ASTContext &ctx = nominal->getASTContext();
285288
const auto name = requirement->getName();
286289

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: 6 additions & 10 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,7 @@ static ValueDecl *deriveProtocolRequirement(DeclContext *DC,
45114511
if (!derivableKind)
45124512
return nullptr;
45134513

4514-
const auto Decl = DC->getInnermostDeclarationDeclContext();
4515-
if (Decl->isInvalid())
4516-
return nullptr;
4517-
4518-
DerivedConformance derived(TypeDecl->getASTContext(), Decl, TypeDecl,
4519-
protocol);
4514+
DerivedConformance derived(Conformance, TypeDecl, protocol);
45204515

45214516
switch (*derivableKind) {
45224517
case KnownDerivableProtocolKind::RawRepresentable:
@@ -4597,7 +4592,8 @@ ResolveWitnessResult ConformanceChecker::resolveWitnessViaDerivation(
45974592
}
45984593

45994594
// Attempt to derive the witness.
4600-
auto derived = deriveProtocolRequirement(DC, derivingTypeDecl, requirement);
4595+
auto derived =
4596+
deriveProtocolRequirement(Conformance, derivingTypeDecl, requirement);
46014597

46024598
if (!derived) {
46034599
return ResolveWitnessResult::ExplicitFailed;

lib/Sema/TypeChecker.h

Lines changed: 0 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -826,21 +826,6 @@ void checkConformancesInContext(IterableDeclContext *idc);
826826
/// Check that the type of the given property conforms to NSCopying.
827827
ProtocolConformanceRef checkConformanceToNSCopying(VarDecl *var);
828828

829-
/// Derive an implicit declaration to satisfy a requirement of a derived
830-
/// protocol conformance.
831-
///
832-
/// \param DC The declaration context where the conformance was
833-
/// defined, either the type itself or an extension
834-
/// \param TypeDecl The type for which the requirement is being derived.
835-
/// \param Requirement The protocol requirement.
836-
///
837-
/// \returns nullptr if the derivation failed, or the derived declaration
838-
/// if it succeeded. If successful, the derived declaration is added
839-
/// to TypeDecl's body.
840-
ValueDecl *deriveProtocolRequirement(DeclContext *DC,
841-
NominalTypeDecl *TypeDecl,
842-
ValueDecl *Requirement);
843-
844829
/// \name Name lookup
845830
///
846831
/// Routines that perform name lookup.

0 commit comments

Comments
 (0)