Skip to content

Commit 5c412b4

Browse files
committed
Sema: Don't allow opaque return types to reference DynamicSelfType
This cannot be represented in the ABI because we expect that the opaque return type can be instantiated from the generic arguments of its declaring context. Reconstructing type metadata for the DynamicSelfType would require opaque return type instantiation to also take the self *value*. Fixes rdar://72407668 / #56367
1 parent dceed56 commit 5c412b4

File tree

3 files changed

+49
-4
lines changed

3 files changed

+49
-4
lines changed

include/swift/AST/DiagnosticsSema.def

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4215,6 +4215,9 @@ NOTE(opaque_type_underlying_type_candidate_here,none,
42154215
ERROR(opaque_type_self_referential_underlying_type,none,
42164216
"function opaque return type was inferred as %0, which defines the "
42174217
"opaque type in terms of itself", (Type))
4218+
ERROR(opaque_type_cannot_contain_dynamic_self,none,
4219+
"function with opaque return type cannot return "
4220+
"the covariant 'Self' type of a class", ())
42184221
ERROR(opaque_type_var_no_init,none,
42194222
"property declares an opaque return type, but has no initializer "
42204223
"expression from which to infer an underlying type", ())

lib/Sema/MiscDiagnostics.cpp

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2846,20 +2846,26 @@ class OpaqueUnderlyingTypeChecker : public ASTWalker {
28462846

28472847
std::pair<bool, Expr *> walkToExprPre(Expr *E) override {
28482848
if (auto underlyingToOpaque = dyn_cast<UnderlyingToOpaqueExpr>(E)) {
2849-
auto key =
2850-
underlyingToOpaque->substitutions.getCanonical().getOpaqueValue();
2849+
auto subMap = underlyingToOpaque->substitutions;
28512850

2851+
auto key = subMap.getCanonical().getOpaqueValue();
28522852
auto isUnique = UniqueSignatures.insert(key).second;
28532853

28542854
auto candidate =
2855-
std::make_tuple(underlyingToOpaque->getSubExpr(),
2856-
underlyingToOpaque->substitutions, isUnique);
2855+
std::make_tuple(underlyingToOpaque->getSubExpr(), subMap, isUnique);
28572856

28582857
if (isSelfReferencing(candidate)) {
28592858
HasInvalidReturn = true;
28602859
return {false, nullptr};
28612860
}
28622861

2862+
if (subMap.hasDynamicSelf()) {
2863+
Ctx.Diags.diagnose(E->getLoc(),
2864+
diag::opaque_type_cannot_contain_dynamic_self);
2865+
HasInvalidReturn = true;
2866+
return {false, nullptr};
2867+
}
2868+
28632869
Candidates.push_back({CurrentAvailability, candidate});
28642870
return {false, E};
28652871
}
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
// RUN: %target-typecheck-verify-swift -disable-availability-checking
2+
3+
protocol P {
4+
init()
5+
}
6+
7+
extension P {
8+
static func opaqueProtocolExtensionFunc() -> some P { return Self() }
9+
}
10+
11+
class C: P {
12+
required init() {}
13+
14+
static func opaqueFunc1() -> some P {
15+
return Self()
16+
// expected-error@-1 {{function with opaque return type cannot return the covariant 'Self' type of a class}}
17+
}
18+
19+
static func opaqueFunc2() -> some P {
20+
return Self.opaqueProtocolExtensionFunc()
21+
// expected-error@-1 {{function with opaque return type cannot return the covariant 'Self' type of a class}}
22+
}
23+
24+
var opaqueProperty: some P {
25+
return Self()
26+
// expected-error@-1 {{function with opaque return type cannot return the covariant 'Self' type of a class}}
27+
}
28+
29+
subscript() -> some P {
30+
return Self()
31+
// expected-error@-1 {{function with opaque return type cannot return the covariant 'Self' type of a class}}
32+
}
33+
34+
var opaqueStoredProperty: some P = Self()
35+
// expected-error@-1 {{covariant 'Self' type cannot be referenced from a stored property initializer}}
36+
}

0 commit comments

Comments
 (0)