Skip to content

Commit 42e0f21

Browse files
committed
[CSDiagnostics] Improve requirement failure source detection
If affected declaration is a static or instance memeber (excluding operators) and failed requirement is declared in other nominal type or extension, diagnose such problems as `in reference` instead of claiming that requirement belongs to the member itself.
1 parent 0d0c132 commit 42e0f21

File tree

4 files changed

+18
-12
lines changed

4 files changed

+18
-12
lines changed

lib/Sema/CSDiagnostics.cpp

Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -90,15 +90,6 @@ Type RequirementFailure::getOwnerType() const {
9090
}
9191

9292
const GenericContext *RequirementFailure::getGenericContext() const {
93-
// For conditional requirements, this is easy because all
94-
// required information is contained in the conformance
95-
// reference.
96-
if (isConditional()) {
97-
auto *conformance = getConformanceRef().getConcrete();
98-
auto *DC = conformance->getDeclContext();
99-
return DC->getAsDecl()->getAsGenericContext();
100-
}
101-
10293
if (auto *genericCtx = AffectedDecl->getAsGenericContext())
10394
return genericCtx;
10495
return AffectedDecl->getDeclContext()->getAsDecl()->getAsGenericContext();
@@ -199,6 +190,16 @@ const DeclContext *RequirementFailure::getRequirementDC() const {
199190
return AffectedDecl->getAsGenericContext();
200191
}
201192

193+
bool RequirementFailure::isStaticOrInstanceMember(const ValueDecl *decl) {
194+
if (decl->isInstanceMember())
195+
return true;
196+
197+
if (auto *AFD = dyn_cast<AbstractFunctionDecl>(decl))
198+
return AFD->isStatic() && !AFD->isOperator();
199+
200+
return decl->isStatic();
201+
}
202+
202203
bool RequirementFailure::diagnoseAsError() {
203204
if (!canDiagnoseFailure())
204205
return false;
@@ -210,7 +211,8 @@ bool RequirementFailure::diagnoseAsError() {
210211
auto lhs = resolveType(getLHS());
211212
auto rhs = resolveType(getRHS());
212213

213-
if (reqDC != genericCtx) {
214+
if (genericCtx != reqDC && (genericCtx->isChildContextOf(reqDC) ||
215+
isStaticOrInstanceMember(AffectedDecl))) {
214216
auto *NTD = reqDC->getSelfNominalTypeDecl();
215217
emitDiagnostic(anchor->getLoc(), getDiagnosticInRereference(),
216218
AffectedDecl->getDescriptiveKind(),

lib/Sema/CSDiagnostics.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -269,6 +269,10 @@ class RequirementFailure : public FailureDiagnostic {
269269
ValueDecl *getDeclRef() const;
270270

271271
void emitRequirementNote(const Decl *anchor, Type lhs, Type rhs) const;
272+
273+
/// Determine whether given declaration represents a static
274+
/// or instance property/method, excluding operators.
275+
static bool isStaticOrInstanceMember(const ValueDecl *decl);
272276
};
273277

274278
/// Diagnostics for failed conformance checks originating from

test/Generics/conditional_conformances.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -399,6 +399,6 @@ extension BinaryInteger {
399399
return self <= 1
400400
? 1
401401
: (2...self).reduce(1, *)
402-
// expected-error@-1 {{instance method 'reduce' requires that 'Self.Stride' conform to 'SignedInteger'}}
402+
// expected-error@-1 {{referencing instance method 'reduce' on 'ClosedRange' requires that 'Self.Stride' conform to 'SignedInteger'}}
403403
}
404404
}

test/NameBinding/name_lookup_min_max_conditional_conformance.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,6 @@ extension Conditional {
5353
// expected-warning@-1{{use of 'min' as reference to global function in module 'Swift' will change in future versions of Swift to reference instance method in generic struct 'Conditional' which comes via a conditional conformance}}
5454
// expected-note@-2{{use 'Swift.' to continue to reference the global function}}
5555
_ = foo(5, 6)
56-
// expected-error@-1{{instance method 'foo()' requires that 'T' conform to 'ContainsFoo'}}
56+
// expected-error@-1{{referencing instance method 'foo()' on 'Conditional' requires that 'T' conform to 'ContainsFoo'}}
5757
}
5858
}

0 commit comments

Comments
 (0)