From b0a565e458146171d41a25f9647b4b908da35ad0 Mon Sep 17 00:00:00 2001 From: Doug Gregor Date: Mon, 3 Nov 2025 22:25:54 -0800 Subject: [PATCH 1/2] [Custom availability] Fix conformance availability diagnostic Emit a proper diagnostic for a conformance that is not available due to custom availability that doesn't have version information, eliminating an assertion. --- include/swift/AST/DiagnosticsSema.def | 4 +++ lib/Frontend/Frontend.cpp | 15 ++++++++++ lib/Sema/TypeCheckAvailability.cpp | 17 +++++++---- .../availability_custom_domains.swift | 28 +++++++++++++++++++ 4 files changed, 59 insertions(+), 5 deletions(-) diff --git a/include/swift/AST/DiagnosticsSema.def b/include/swift/AST/DiagnosticsSema.def index ba121d384b9ad..f28e4fb06ff65 100644 --- a/include/swift/AST/DiagnosticsSema.def +++ b/include/swift/AST/DiagnosticsSema.def @@ -7282,6 +7282,10 @@ ERROR(conformance_availability_only_version_newer, none, "conformance of %0 to %1 is only available in %2 %3 or newer", (Type, Type, AvailabilityDomain, AvailabilityRange)) +ERROR(conformance_availability_not_available, none, + "conformance of %0 to %1 is only available in %2", + (Type, Type, AvailabilityDomain)) + //------------------------------------------------------------------------------ // MARK: if #available(...) //------------------------------------------------------------------------------ diff --git a/lib/Frontend/Frontend.cpp b/lib/Frontend/Frontend.cpp index 7e196020dfe4c..6510af9e95bc3 100644 --- a/lib/Frontend/Frontend.cpp +++ b/lib/Frontend/Frontend.cpp @@ -1465,6 +1465,21 @@ static void configureAvailabilityDomains(const ASTContext &ctx, for (auto dynamic : opts.AvailabilityDomains.DynamicDomains) createAndInsertDomain(dynamic, CustomAvailabilityDomain::Kind::Dynamic); + // If we didn't see the UnicodeNormalization availability domain, set it + // appropriately. + if (domainMap.count(ctx.getIdentifier("UnicodeNormalization")) == 0) { + if (ctx.LangOpts.hasFeature(Feature::Embedded)) { + // Embedded Swift disables this domain by default. + createAndInsertDomain("UnicodeNormalization", + CustomAvailabilityDomain::Kind::Enabled); + } else { + // Non-Embedded Swift always enables the Unicode tables. + createAndInsertDomain("UnicodeNormalization", + CustomAvailabilityDomain::Kind::AlwaysEnabled); + } + } + + mainModule->setAvailabilityDomains(std::move(domainMap)); } diff --git a/lib/Sema/TypeCheckAvailability.cpp b/lib/Sema/TypeCheckAvailability.cpp index bb799e6c65390..6497ff3609656 100644 --- a/lib/Sema/TypeCheckAvailability.cpp +++ b/lib/Sema/TypeCheckAvailability.cpp @@ -1041,15 +1041,22 @@ static bool diagnosePotentialUnavailability( { auto type = rootConf->getType(); auto proto = rootConf->getProtocol()->getDeclaredInterfaceType(); - auto err = ctx.Diags.diagnose( - loc, diag::conformance_availability_only_version_newer, type, proto, - domain, availability); + auto err = availability.hasMinimumVersion() + ? ctx.Diags.diagnose( + loc, diag::conformance_availability_only_version_newer, type, proto, + domain, availability) + : ctx.Diags.diagnose( + loc, diag::conformance_availability_not_available, type, proto, + domain); auto behaviorLimit = behaviorLimitForExplicitUnavailability(rootConf, dc); - if (behaviorLimit >= DiagnosticBehavior::Warning) + if (!availability.hasMinimumVersion()) { + // Don't downgrade + } else if (behaviorLimit >= DiagnosticBehavior::Warning) { err.limitBehavior(behaviorLimit); - else + } else { err.warnUntilSwiftVersion(6); + } // Direct a fixit to the error if an existing guard is nearly-correct if (fixAvailabilityByNarrowingNearbyVersionCheck(loc, dc, domain, diff --git a/test/Availability/availability_custom_domains.swift b/test/Availability/availability_custom_domains.swift index a30f5e38aadf3..55086c0e07434 100644 --- a/test/Availability/availability_custom_domains.swift +++ b/test/Availability/availability_custom_domains.swift @@ -568,3 +568,31 @@ class DerivedUnavailable2: BaseAvailableInEnabledDomain { } // expected-error {{ @available(DisabledDomain, unavailable) class DerivedUnavailable3: BaseAvailableInEnabledDomain { } + +// Protocol conformance availability. +protocol P { } + +struct MyType1 { } + +@available(EnabledDomain) +extension MyType1: P { } + +struct MyType2 { } + +@available(AlwaysEnabledDomain) +extension MyType2: P { } + +struct MyType3 { } + +@available(DisabledDomain) +extension MyType3: P { } + +func acceptP(_: T.Type) { } + +func testP() { // expected-note 2{{add '@available' attribute to enclosing global function}} + acceptP(MyType1.self) // expected-error{{conformance of 'MyType1' to 'P' is only available in EnabledDomain}} + // expected-note@-1{{add 'if #available' version check}} + acceptP(MyType2.self) // okay + acceptP(MyType3.self) // expected-error{{conformance of 'MyType3' to 'P' is only available in DisabledDomain}} + // expected-note@-1{{add 'if #available' version check}} +} From ba3d8e0c2b0b8397444cf374a64eb872f57b140b Mon Sep 17 00:00:00 2001 From: Doug Gregor Date: Tue, 4 Nov 2025 10:07:40 -0800 Subject: [PATCH 2/2] Remove unused variable --- lib/SILGen/SILGenDestructor.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/lib/SILGen/SILGenDestructor.cpp b/lib/SILGen/SILGenDestructor.cpp index d80309d21a61d..4e78114122f85 100644 --- a/lib/SILGen/SILGenDestructor.cpp +++ b/lib/SILGen/SILGenDestructor.cpp @@ -58,8 +58,6 @@ void SILGenFunction::emitDistributedRemoteActorDeinit( auto cleanupLoc = CleanupLocation(loc); - auto &C = cd->getASTContext(); - { FullExpr CleanupScope(Cleanups, cleanupLoc); ManagedValue borrowedSelf = emitManagedBeginBorrow(loc, selfValue);