Skip to content

Commit f0ff68e

Browse files
committed
[Diagnostics] Special case requirement failures related to return statement/expression
Make sure that "affected" declaration is recognized as the one to which result type is attached to if the requirement failure is originated in contextual type of `return` statement/expression. Resolves: SR-13992 Resolves: rdar://72819046 Resolves: rdar://57789606
1 parent 4917d43 commit f0ff68e

File tree

2 files changed

+51
-2
lines changed

2 files changed

+51
-2
lines changed

lib/Sema/CSDiagnostics.cpp

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -249,8 +249,28 @@ ValueDecl *RequirementFailure::getDeclRef() const {
249249
return getAffectedDeclFromType(func->getResultInterfaceType());
250250
}
251251

252-
if (isFromContextualType())
253-
return getAffectedDeclFromType(getContextualType(getRawAnchor()));
252+
if (isFromContextualType()) {
253+
auto anchor = getRawAnchor();
254+
auto contextualPurpose = getContextualTypePurpose(anchor);
255+
auto contextualTy = getContextualType(anchor);
256+
257+
// If the issue is a mismatch between `return` statement/expression
258+
// and its contextual requirements, it means that affected declaration
259+
// is a declarer of a contextual "result" type e.g. member of a
260+
// type, local function etc.
261+
if (contextualPurpose == CTP_ReturnStmt ||
262+
contextualPurpose == CTP_ReturnSingleExpr) {
263+
// In case of opaque result type, let's point to the declaration
264+
// associated with the type itself (since it has one) instead of
265+
// declarer.
266+
if (auto *opaque = contextualTy->getAs<OpaqueTypeArchetypeType>())
267+
return opaque->getDecl();
268+
269+
return cast<ValueDecl>(getDC()->getAsDecl());
270+
}
271+
272+
return getAffectedDeclFromType(contextualTy);
273+
}
254274

255275
if (auto overload = getCalleeOverloadChoiceIfAvailable(getLocator())) {
256276
// If there is a declaration associated with this

test/Constraints/sr13992.swift

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
// RUN: %target-typecheck-verify-swift
2+
3+
// SR-13992
4+
5+
protocol V {}
6+
7+
protocol P1 {}
8+
protocol P2 {
9+
func bar() -> V
10+
}
11+
protocol P3 {}
12+
13+
struct S<T> {
14+
var foo: T
15+
}
16+
17+
extension S : P1 {}
18+
extension S : P2 where T: P3 { // expected-note {{requirement from conditional conformance of 'S<V>' to 'P2'}}
19+
func bar() -> V { fatalError() }
20+
}
21+
22+
struct Q {
23+
var foo: V
24+
25+
func test() -> P1 & P2 {
26+
S(foo: foo) // expected-error {{protocol 'V' as a type cannot conform to 'P3'}}
27+
// expected-note@-1 {{only concrete types such as structs, enums and classes can conform to protocols}}
28+
}
29+
}

0 commit comments

Comments
 (0)