Skip to content

Commit 9605ec6

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 / swiftlang#56367
1 parent ae505e5 commit 9605ec6

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
@@ -4244,6 +4244,9 @@ NOTE(opaque_type_underlying_type_candidate_here,none,
42444244
ERROR(opaque_type_self_referential_underlying_type,none,
42454245
"function opaque return type was inferred as %0, which defines the "
42464246
"opaque type in terms of itself", (Type))
4247+
ERROR(opaque_type_cannot_contain_dynamic_self,none,
4248+
"function with opaque return type cannot return "
4249+
"the covariant 'Self' type of a class", ())
42474250
ERROR(opaque_type_var_no_init,none,
42484251
"property declares an opaque return type, but has no initializer "
42494252
"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
@@ -2815,20 +2815,26 @@ class OpaqueUnderlyingTypeChecker : public ASTWalker {
28152815

28162816
std::pair<bool, Expr *> walkToExprPre(Expr *E) override {
28172817
if (auto underlyingToOpaque = dyn_cast<UnderlyingToOpaqueExpr>(E)) {
2818-
auto key =
2819-
underlyingToOpaque->substitutions.getCanonical().getOpaqueValue();
2818+
auto subMap = underlyingToOpaque->substitutions;
28202819

2820+
auto key = subMap.getCanonical().getOpaqueValue();
28212821
auto isUnique = UniqueSignatures.insert(key).second;
28222822

28232823
auto candidate =
2824-
std::make_tuple(underlyingToOpaque->getSubExpr(),
2825-
underlyingToOpaque->substitutions, isUnique);
2824+
std::make_tuple(underlyingToOpaque->getSubExpr(), subMap, isUnique);
28262825

28272826
if (isSelfReferencing(candidate)) {
28282827
HasInvalidReturn = true;
28292828
return {false, nullptr};
28302829
}
28312830

2831+
if (subMap.hasDynamicSelf()) {
2832+
Ctx.Diags.diagnose(E->getLoc(),
2833+
diag::opaque_type_cannot_contain_dynamic_self);
2834+
HasInvalidReturn = true;
2835+
return {false, nullptr};
2836+
}
2837+
28322838
Candidates.push_back({CurrentAvailability, candidate});
28332839
return {false, E};
28342840
}
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)