Skip to content

Commit 59d74fa

Browse files
committed
Sema: Diagnose opaque types that depend on availability of a custom domain.
Serialization and IRGen don't yet support opaque return types that would depend on querying availability of a custom domain so we need to reject this code to avoid mis-compiling it.
1 parent 4a76c04 commit 59d74fa

File tree

3 files changed

+45
-1
lines changed

3 files changed

+45
-1
lines changed

include/swift/AST/DiagnosticsSema.def

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5300,7 +5300,9 @@ GROUPED_ERROR(opaque_type_var_no_init,OpaqueTypeInference,none,
53005300
GROUPED_ERROR(opaque_type_var_no_underlying_type,OpaqueTypeInference,none,
53015301
"property declares an opaque return type, but cannot infer the "
53025302
"underlying type from its initializer expression", ())
5303-
5303+
GROUPED_ERROR(opaque_type_unsupported_availability,OpaqueTypeInference,none,
5304+
"opaque return type cannot depend on %0 availability",
5305+
(AvailabilityDomain))
53045306

53055307
//------------------------------------------------------------------------------
53065308
// MARK: Discard Statement

lib/Sema/MiscDiagnostics.cpp

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3530,6 +3530,32 @@ class OpaqueUnderlyingTypeChecker : public ASTWalker {
35303530
return;
35313531
}
35323532

3533+
// Diagnose unsupported availability domains.
3534+
// FIXME: [availability] Support custom domains.
3535+
bool anyUnsupportedDomain = false;
3536+
for (const auto &entry : Candidates) {
3537+
IfStmt *stmt = entry.first;
3538+
if (!stmt) continue;
3539+
3540+
for (const auto &elt : stmt->getCond()) {
3541+
if (elt.getKind() != StmtConditionElement::CK_Availability)
3542+
continue;
3543+
3544+
auto poundAvailable = elt.getAvailability();
3545+
if (auto query = poundAvailable->getAvailabilityQuery()) {
3546+
if (query->getDomain().isCustom()) {
3547+
Ctx.Diags.diagnose(poundAvailable->getStartLoc(),
3548+
diag::opaque_type_unsupported_availability,
3549+
query->getDomain());
3550+
anyUnsupportedDomain = true;
3551+
}
3552+
}
3553+
}
3554+
}
3555+
3556+
if (anyUnsupportedDomain)
3557+
return;
3558+
35333559
SmallVector<Candidate, 4> universallyUniqueCandidates;
35343560

35353561
for (const auto &entry : Candidates) {

test/Availability/availability_custom_domains.swift

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -193,3 +193,19 @@ struct EnabledDomainAvailable {
193193
unavailableInDisabledDomain() // expected-error {{'unavailableInDisabledDomain()' is unavailable}}
194194
}
195195
}
196+
197+
protocol P { }
198+
199+
@available(EnabledDomain)
200+
struct AvailableInEnabledDomain: P { }
201+
202+
@available(EnabledDomain, unavailable)
203+
struct UnavailableInEnabledDomain: P { }
204+
205+
func testOpaqueReturnType() -> some P {
206+
if #available(EnabledDomain) { // expected-error {{opaque return type cannot depend on EnabledDomain availability}}
207+
return AvailableInEnabledDomain()
208+
} else {
209+
return UnavailableInEnabledDomain()
210+
}
211+
}

0 commit comments

Comments
 (0)