Skip to content

Commit 0f411b1

Browse files
committed
[Diagnostics] Extract requirement declaration context retrieval into its own method
Change logic to traverse the chain of declaration contexts starting for "affected" declaration's parent and check if the requirement is satisfied by one of them, if so return it as requirement's declaration context. Extract this logic into a method on `RequirementFailure` to make it accessible for other types of requirement failure diagnostics.
1 parent 46981fe commit 0f411b1

File tree

2 files changed

+34
-18
lines changed

2 files changed

+34
-18
lines changed

lib/Sema/CSDiagnostics.cpp

Lines changed: 28 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -14,10 +14,11 @@
1414
//
1515
//===----------------------------------------------------------------------===//
1616

17-
#include "ConstraintSystem.h"
1817
#include "CSDiagnostics.h"
18+
#include "ConstraintSystem.h"
1919
#include "MiscDiagnostics.h"
2020
#include "swift/AST/Expr.h"
21+
#include "swift/AST/GenericSignature.h"
2122
#include "swift/AST/Types.h"
2223
#include "llvm/ADT/ArrayRef.h"
2324

@@ -67,7 +68,7 @@ Type RequirementFailure::getOwnerType() const {
6768
return getType(getAnchor())->getInOutObjectType()->getMetatypeInstanceType();
6869
}
6970

70-
const Requirement &RequirementFailure::getRequirement() {
71+
const Requirement &RequirementFailure::getRequirement() const {
7172
auto *genericCtx = AffectedDecl->getAsGenericContext();
7273
return genericCtx->getGenericRequirements()[getRequirementIndex()];
7374
}
@@ -100,6 +101,27 @@ ValueDecl *RequirementFailure::getDeclRef() const {
100101
return ownerType->getAnyGeneric();
101102
}
102103

104+
const DeclContext *RequirementFailure::getRequirementDC() const {
105+
const auto &req = getRequirement();
106+
auto *DC = AffectedDecl->getDeclContext();
107+
108+
do {
109+
auto *D = DC->getInnermostDeclarationDeclContext();
110+
if (!D)
111+
break;
112+
113+
if (auto *GC = D->getAsGenericContext()) {
114+
auto *sig = GC->getGenericSignature();
115+
if (sig && sig->isRequirementSatisfied(req))
116+
return DC;
117+
}
118+
119+
DC = DC->getParent();
120+
} while (DC);
121+
122+
return AffectedDecl->getAsGenericContext();
123+
}
124+
103125
bool MissingConformanceFailure::diagnose() {
104126
auto *anchor = getAnchor();
105127
auto ownerType = getOwnerType();
@@ -175,21 +197,10 @@ bool MissingConformanceFailure::diagnose() {
175197
} else {
176198
const auto &req = getRequirement();
177199
auto *genericCtx = AffectedDecl->getAsGenericContext();
200+
const auto *reqDC = getRequirementDC();
178201

179-
std::function<const DeclContext *(Type)> getAffectedCtx =
180-
[&](Type type) -> const DeclContext * {
181-
if (auto *DMT = type->getAs<DependentMemberType>())
182-
return getAffectedCtx(DMT->getBase());
183-
184-
if (auto *GPT = type->getAs<GenericTypeParamType>())
185-
return GPT->getDecl()->getDeclContext();
186-
187-
return genericCtx;
188-
};
189-
190-
const auto *affected = getAffectedCtx(req.getFirstType());
191-
if (affected != genericCtx) {
192-
auto *NTD = affected->getAsNominalTypeOrNominalTypeExtensionContext();
202+
if (reqDC != genericCtx) {
203+
auto *NTD = reqDC->getAsNominalTypeOrNominalTypeExtensionContext();
193204
emitDiagnostic(anchor->getLoc(), diag::type_does_not_conform_in_decl_ref,
194205
AffectedDecl->getDescriptiveKind(),
195206
AffectedDecl->getFullName(), NTD->getDeclaredType(), type,
@@ -200,7 +211,7 @@ bool MissingConformanceFailure::diagnose() {
200211
AffectedDecl->getFullName(), type, protocolType);
201212
}
202213

203-
emitDiagnostic(affected->getAsDeclOrDeclExtensionContext(),
214+
emitDiagnostic(reqDC->getAsDeclOrDeclExtensionContext(),
204215
diag::where_type_does_not_conform_type, req.getFirstType(),
205216
type);
206217
}

lib/Sema/CSDiagnostics.h

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -134,7 +134,12 @@ class RequirementFailure : public FailureDiagnostic {
134134
Type getOwnerType() const;
135135

136136
/// Generic requirement associated with the failure.
137-
const Requirement &getRequirement();
137+
const Requirement &getRequirement() const;
138+
139+
protected:
140+
/// Retrieve declaration contextual where current
141+
/// requirement has been introduced.
142+
const DeclContext *getRequirementDC() const;
138143

139144
private:
140145
/// Retrieve declaration associated with failing generic requirement.

0 commit comments

Comments
 (0)