Skip to content

Commit b1c2bc1

Browse files
authored
Merge pull request #85305 from DougGregor/custom-conformance-availability
[Custom availability] Fix conformance availability diagnostic
2 parents de38bb4 + ba3d8e0 commit b1c2bc1

File tree

4 files changed

+59
-5
lines changed

4 files changed

+59
-5
lines changed

include/swift/AST/DiagnosticsSema.def

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7265,6 +7265,10 @@ ERROR(conformance_availability_only_version_newer, none,
72657265
"conformance of %0 to %1 is only available in %2 %3 or newer",
72667266
(Type, Type, AvailabilityDomain, AvailabilityRange))
72677267

7268+
ERROR(conformance_availability_not_available, none,
7269+
"conformance of %0 to %1 is only available in %2",
7270+
(Type, Type, AvailabilityDomain))
7271+
72687272
//------------------------------------------------------------------------------
72697273
// MARK: if #available(...)
72707274
//------------------------------------------------------------------------------

lib/Frontend/Frontend.cpp

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1465,6 +1465,21 @@ static void configureAvailabilityDomains(const ASTContext &ctx,
14651465
for (auto dynamic : opts.AvailabilityDomains.DynamicDomains)
14661466
createAndInsertDomain(dynamic, CustomAvailabilityDomain::Kind::Dynamic);
14671467

1468+
// If we didn't see the UnicodeNormalization availability domain, set it
1469+
// appropriately.
1470+
if (domainMap.count(ctx.getIdentifier("UnicodeNormalization")) == 0) {
1471+
if (ctx.LangOpts.hasFeature(Feature::Embedded)) {
1472+
// Embedded Swift disables this domain by default.
1473+
createAndInsertDomain("UnicodeNormalization",
1474+
CustomAvailabilityDomain::Kind::Enabled);
1475+
} else {
1476+
// Non-Embedded Swift always enables the Unicode tables.
1477+
createAndInsertDomain("UnicodeNormalization",
1478+
CustomAvailabilityDomain::Kind::AlwaysEnabled);
1479+
}
1480+
}
1481+
1482+
14681483
mainModule->setAvailabilityDomains(std::move(domainMap));
14691484
}
14701485

lib/Sema/TypeCheckAvailability.cpp

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1041,15 +1041,22 @@ static bool diagnosePotentialUnavailability(
10411041
{
10421042
auto type = rootConf->getType();
10431043
auto proto = rootConf->getProtocol()->getDeclaredInterfaceType();
1044-
auto err = ctx.Diags.diagnose(
1045-
loc, diag::conformance_availability_only_version_newer, type, proto,
1046-
domain, availability);
1044+
auto err = availability.hasMinimumVersion()
1045+
? ctx.Diags.diagnose(
1046+
loc, diag::conformance_availability_only_version_newer, type, proto,
1047+
domain, availability)
1048+
: ctx.Diags.diagnose(
1049+
loc, diag::conformance_availability_not_available, type, proto,
1050+
domain);
10471051

10481052
auto behaviorLimit = behaviorLimitForExplicitUnavailability(rootConf, dc);
1049-
if (behaviorLimit >= DiagnosticBehavior::Warning)
1053+
if (!availability.hasMinimumVersion()) {
1054+
// Don't downgrade
1055+
} else if (behaviorLimit >= DiagnosticBehavior::Warning) {
10501056
err.limitBehavior(behaviorLimit);
1051-
else
1057+
} else {
10521058
err.warnUntilSwiftVersion(6);
1059+
}
10531060

10541061
// Direct a fixit to the error if an existing guard is nearly-correct
10551062
if (fixAvailabilityByNarrowingNearbyVersionCheck(loc, dc, domain,

test/Availability/availability_custom_domains.swift

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -568,3 +568,31 @@ class DerivedUnavailable2: BaseAvailableInEnabledDomain { } // expected-error {{
568568
@available(DisabledDomain, unavailable)
569569
class DerivedUnavailable3: BaseAvailableInEnabledDomain { }
570570

571+
572+
// Protocol conformance availability.
573+
protocol P { }
574+
575+
struct MyType1 { }
576+
577+
@available(EnabledDomain)
578+
extension MyType1: P { }
579+
580+
struct MyType2 { }
581+
582+
@available(AlwaysEnabledDomain)
583+
extension MyType2: P { }
584+
585+
struct MyType3 { }
586+
587+
@available(DisabledDomain)
588+
extension MyType3: P { }
589+
590+
func acceptP<T: P>(_: T.Type) { }
591+
592+
func testP() { // expected-note 2{{add '@available' attribute to enclosing global function}}
593+
acceptP(MyType1.self) // expected-error{{conformance of 'MyType1' to 'P' is only available in EnabledDomain}}
594+
// expected-note@-1{{add 'if #available' version check}}
595+
acceptP(MyType2.self) // okay
596+
acceptP(MyType3.self) // expected-error{{conformance of 'MyType3' to 'P' is only available in DisabledDomain}}
597+
// expected-note@-1{{add 'if #available' version check}}
598+
}

0 commit comments

Comments
 (0)