@@ -2841,36 +2841,72 @@ bool swift::diagnoseExplicitUnavailability(const ValueDecl *D, SourceRange R,
28412841 });
28422842}
28432843
2844- // / Emit a diagnostic for references to declarations that have been
2845- // / marked as unavailable, either through "unavailable" or "obsoleted:".
2846- bool swift::diagnoseExplicitUnavailability (SourceLoc loc,
2847- const RootProtocolConformance *rootConf,
2848- const ExtensionDecl *ext,
2849- const ExportContext &where,
2850- bool warnIfConformanceUnavailablePreSwift6) {
2851- auto *attr = AvailableAttr::isUnavailable (ext);
2844+ // / Represents common information needed to emit diagnostics about explicitly
2845+ // / unavailable declarations.
2846+ class UnavailabilityDiagnosticInfo {
2847+ public:
2848+ enum class Status {
2849+ // / The declaration is marked `unavailable`, potentially on a specific
2850+ // / platform.
2851+ AlwaysUnavailable,
2852+
2853+ // / The declaration is not available until, for example, a later Swift
2854+ // / language mode.
2855+ IntroducedInVersion,
2856+
2857+ // / The declaration was obsoleted in a previous version.
2858+ Obsoleted,
2859+ };
2860+
2861+ private:
2862+ Status DiagnosticStatus;
2863+ const AvailableAttr *Attr;
2864+ StringRef Platform;
2865+ StringRef VersionedPlatform;
2866+
2867+ public:
2868+ UnavailabilityDiagnosticInfo (Status status, const AvailableAttr *attr,
2869+ StringRef platform, StringRef versionedPlatform)
2870+ : DiagnosticStatus(status), Attr(attr), Platform(platform),
2871+ VersionedPlatform (versionedPlatform) {
2872+ assert (attr);
2873+ assert (status == Status::AlwaysUnavailable || !VersionedPlatform.empty ());
2874+ };
2875+
2876+ Status getStatus () const { return DiagnosticStatus; }
2877+ const AvailableAttr *getAttr () const { return Attr; }
2878+
2879+ // / Returns the platform name (or "Swift" for a declaration that is
2880+ // / unavailable in Swift) to print in the main unavailability diangostic. May
2881+ // / be empty.
2882+ StringRef getPlatform () const { return Platform; }
2883+
2884+ // / Returns the platform name to print in diagnostic notes about the version
2885+ // / in which a declaration either will become available or previously became
2886+ // / obsoleted.
2887+ StringRef getVersionedPlatform () const {
2888+ assert (DiagnosticStatus != Status::AlwaysUnavailable);
2889+ return VersionedPlatform;
2890+ }
2891+ };
2892+
2893+ static std::optional<UnavailabilityDiagnosticInfo>
2894+ getExplicitUnavailabilityDiagnosticInfo (const Decl *decl,
2895+ const ExportContext &where) {
2896+ auto *attr = AvailableAttr::isUnavailable (decl);
28522897 if (!attr)
2853- return false ;
2898+ return std:: nullopt ;
28542899
28552900 // Calling unavailable code from within code with the same
28562901 // unavailability is OK -- the eventual caller can't call the
28572902 // enclosing code in the same situations it wouldn't be able to
28582903 // call this code.
2859- if (isInsideCompatibleUnavailableDeclaration (ext, where, attr))
2860- return false ;
2861-
2862- // Invertible protocols are never unavailable.
2863- if (rootConf->getProtocol ()->getInvertibleProtocolKind ())
2864- return false ;
2865-
2866- ASTContext &ctx = ext->getASTContext ();
2867- auto &diags = ctx.Diags ;
2868-
2869- auto type = rootConf->getType ();
2870- auto proto = rootConf->getProtocol ()->getDeclaredInterfaceType ();
2904+ if (isInsideCompatibleUnavailableDeclaration (decl, where, attr))
2905+ return std::nullopt ;
28712906
2872- StringRef platform;
2873- auto behavior = DiagnosticBehavior::Unspecified;
2907+ ASTContext &ctx = decl->getASTContext ();
2908+ StringRef platform = " " ;
2909+ StringRef versionedPlatform = " " ;
28742910 switch (attr->getPlatformAgnosticAvailability ()) {
28752911 case PlatformAgnosticAvailabilityKind::Deprecated:
28762912 llvm_unreachable (" shouldn't see deprecations in explicit unavailability" );
@@ -2881,73 +2917,96 @@ bool swift::diagnoseExplicitUnavailability(SourceLoc loc,
28812917 case PlatformAgnosticAvailabilityKind::None:
28822918 case PlatformAgnosticAvailabilityKind::Unavailable:
28832919 if (attr->Platform != PlatformKind::none) {
2884- // This was platform-specific; indicate the platform.
28852920 platform = attr->prettyPlatformString ();
2886- break ;
2921+ versionedPlatform = platform ;
28872922 }
2888-
2889- // Downgrade unavailable Sendable conformance diagnostics where
2890- // appropriate.
2891- behavior = behaviorLimitForExplicitUnavailability (
2892- rootConf, where.getDeclContext ());
2893- LLVM_FALLTHROUGH;
2894-
2923+ break ;
28952924 case PlatformAgnosticAvailabilityKind::SwiftVersionSpecific:
2925+ versionedPlatform = " Swift" ;
2926+ break ;
28962927 case PlatformAgnosticAvailabilityKind::PackageDescriptionVersionSpecific:
2897- // We don't want to give further detail about these.
2898- platform = " " ;
2928+ versionedPlatform = " PackageDescription" ;
28992929 break ;
2900-
29012930 case PlatformAgnosticAvailabilityKind::UnavailableInSwift:
2902- // This API is explicitly unavailable in Swift.
29032931 platform = " Swift" ;
29042932 break ;
29052933 }
29062934
2907- EncodedDiagnosticMessage EncodedMessage (attr->Message );
2908- diags.diagnose (loc, diag::conformance_availability_unavailable,
2909- type, proto,
2910- platform.empty (), platform, EncodedMessage.Message )
2911- .limitBehaviorUntilSwiftVersion (behavior, 6 )
2912- .warnUntilSwiftVersionIf (warnIfConformanceUnavailablePreSwift6, 6 );
2913-
29142935 switch (attr->getVersionAvailability (ctx)) {
29152936 case AvailableVersionComparison::Available:
29162937 case AvailableVersionComparison::PotentiallyUnavailable:
29172938 llvm_unreachable (" These aren't considered unavailable" );
29182939
29192940 case AvailableVersionComparison::Unavailable:
29202941 if ((attr->isLanguageVersionSpecific () ||
2921- attr->isPackageDescriptionVersionSpecific ())
2922- && attr->Introduced .has_value ())
2923- diags.diagnose (ext, diag::conformance_availability_introduced_in_version,
2924- type, proto,
2925- (attr->isLanguageVersionSpecific () ?
2926- " Swift" : " PackageDescription" ),
2927- *attr->Introduced )
2928- .highlight (attr->getRange ());
2929- else
2930- diags.diagnose (ext, diag::conformance_availability_marked_unavailable,
2931- type, proto)
2932- .highlight (attr->getRange ());
2942+ attr->isPackageDescriptionVersionSpecific ()) &&
2943+ attr->Introduced .has_value ()) {
2944+ return UnavailabilityDiagnosticInfo (
2945+ UnavailabilityDiagnosticInfo::Status::IntroducedInVersion, attr,
2946+ platform, versionedPlatform);
2947+ } else {
2948+ return UnavailabilityDiagnosticInfo (
2949+ UnavailabilityDiagnosticInfo::Status::AlwaysUnavailable, attr,
2950+ platform, versionedPlatform);
2951+ }
29332952 break ;
29342953
29352954 case AvailableVersionComparison::Obsoleted:
2936- // FIXME: Use of the platformString here is non-awesome for application
2937- // extensions.
2938-
2939- StringRef platformDisplayString;
2940- if (attr->isLanguageVersionSpecific ()) {
2941- platformDisplayString = " Swift" ;
2942- } else if (attr->isPackageDescriptionVersionSpecific ()) {
2943- platformDisplayString = " PackageDescription" ;
2944- } else {
2945- platformDisplayString = platform;
2946- }
2955+ return UnavailabilityDiagnosticInfo (
2956+ UnavailabilityDiagnosticInfo::Status::Obsoleted, attr, platform,
2957+ versionedPlatform);
2958+ }
2959+ }
29472960
2948- diags.diagnose (ext, diag::conformance_availability_obsoleted,
2949- type, proto, platformDisplayString, *attr->Obsoleted )
2950- .highlight (attr->getRange ());
2961+ bool swift::diagnoseExplicitUnavailability (
2962+ SourceLoc loc, const RootProtocolConformance *rootConf,
2963+ const ExtensionDecl *ext, const ExportContext &where,
2964+ bool warnIfConformanceUnavailablePreSwift6) {
2965+ // Invertible protocols are never unavailable.
2966+ if (rootConf->getProtocol ()->getInvertibleProtocolKind ())
2967+ return false ;
2968+
2969+ auto diagnosticInfo = getExplicitUnavailabilityDiagnosticInfo (ext, where);
2970+ if (!diagnosticInfo)
2971+ return false ;
2972+
2973+ ASTContext &ctx = ext->getASTContext ();
2974+ auto &diags = ctx.Diags ;
2975+
2976+ auto type = rootConf->getType ();
2977+ auto proto = rootConf->getProtocol ()->getDeclaredInterfaceType ();
2978+ StringRef platform = diagnosticInfo->getPlatform ();
2979+ const AvailableAttr *attr = diagnosticInfo->getAttr ();
2980+
2981+ // Downgrade unavailable Sendable conformance diagnostics where
2982+ // appropriate.
2983+ auto behavior =
2984+ behaviorLimitForExplicitUnavailability (rootConf, where.getDeclContext ());
2985+
2986+ EncodedDiagnosticMessage EncodedMessage (attr->Message );
2987+ diags
2988+ .diagnose (loc, diag::conformance_availability_unavailable, type, proto,
2989+ platform.empty (), platform, EncodedMessage.Message )
2990+ .limitBehaviorUntilSwiftVersion (behavior, 6 )
2991+ .warnUntilSwiftVersionIf (warnIfConformanceUnavailablePreSwift6, 6 );
2992+
2993+ switch (diagnosticInfo->getStatus ()) {
2994+ case UnavailabilityDiagnosticInfo::Status::AlwaysUnavailable:
2995+ diags
2996+ .diagnose (ext, diag::conformance_availability_marked_unavailable, type,
2997+ proto)
2998+ .highlight (attr->getRange ());
2999+ break ;
3000+ case UnavailabilityDiagnosticInfo::Status::IntroducedInVersion:
3001+ diags.diagnose (ext, diag::conformance_availability_introduced_in_version,
3002+ type, proto, diagnosticInfo->getVersionedPlatform (),
3003+ *attr->Introduced );
3004+ break ;
3005+ case UnavailabilityDiagnosticInfo::Status::Obsoleted:
3006+ diags
3007+ .diagnose (ext, diag::conformance_availability_obsoleted, type, proto,
3008+ diagnosticInfo->getVersionedPlatform (), *attr->Obsoleted )
3009+ .highlight (attr->getRange ());
29513010 break ;
29523011 }
29533012 return true ;
@@ -3282,52 +3341,21 @@ bool swift::diagnoseExplicitUnavailability(
32823341 const ExportContext &Where,
32833342 DeclAvailabilityFlags Flags,
32843343 llvm::function_ref<void (InFlightDiagnostic &)> attachRenameFixIts) {
3285- auto *Attr = AvailableAttr::isUnavailable (D );
3286- if (!Attr )
3344+ auto diagnosticInfo = getExplicitUnavailabilityDiagnosticInfo (D, Where );
3345+ if (!diagnosticInfo )
32873346 return false ;
32883347
3289- // Calling unavailable code from within code with the same
3290- // unavailability is OK -- the eventual caller can't call the
3291- // enclosing code in the same situations it wouldn't be able to
3292- // call this code.
3293- if ( isInsideCompatibleUnavailableDeclaration (D, Where, Attr))
3294- return false ;
3348+ auto *Attr = diagnosticInfo-> getAttr ();
3349+ if (Attr-> getPlatformAgnosticAvailability () ==
3350+ PlatformAgnosticAvailabilityKind::UnavailableInSwift) {
3351+ if ( shouldAllowReferenceToUnavailableInSwiftDeclaration (D, Where))
3352+ return false ;
3353+ }
32953354
32963355 SourceLoc Loc = R.Start ;
3297-
32983356 ASTContext &ctx = D->getASTContext ();
32993357 auto &diags = ctx.Diags ;
3300-
3301- StringRef platform;
3302- switch (Attr->getPlatformAgnosticAvailability ()) {
3303- case PlatformAgnosticAvailabilityKind::Deprecated:
3304- llvm_unreachable (" shouldn't see deprecations in explicit unavailability" );
3305-
3306- case PlatformAgnosticAvailabilityKind::NoAsync:
3307- llvm_unreachable (" shouldn't see noasync with explicit unavailability" );
3308-
3309- case PlatformAgnosticAvailabilityKind::None:
3310- case PlatformAgnosticAvailabilityKind::Unavailable:
3311- if (Attr->Platform != PlatformKind::none) {
3312- // This was platform-specific; indicate the platform.
3313- platform = Attr->prettyPlatformString ();
3314- break ;
3315- }
3316- LLVM_FALLTHROUGH;
3317-
3318- case PlatformAgnosticAvailabilityKind::SwiftVersionSpecific:
3319- case PlatformAgnosticAvailabilityKind::PackageDescriptionVersionSpecific:
3320- // We don't want to give further detail about these.
3321- platform = " " ;
3322- break ;
3323-
3324- case PlatformAgnosticAvailabilityKind::UnavailableInSwift:
3325- if (shouldAllowReferenceToUnavailableInSwiftDeclaration (D, Where))
3326- return true ;
3327-
3328- platform = " Swift" ;
3329- break ;
3330- }
3358+ StringRef platform = diagnosticInfo->getPlatform ();
33313359
33323360 // TODO: Consider removing this.
33333361 // ObjC keypaths components weren't checked previously, so errors are demoted
@@ -3372,41 +3400,22 @@ bool swift::diagnoseExplicitUnavailability(
33723400 .limitBehavior (limit);
33733401 }
33743402
3375- switch (Attr->getVersionAvailability (ctx)) {
3376- case AvailableVersionComparison::Available:
3377- case AvailableVersionComparison::PotentiallyUnavailable:
3378- llvm_unreachable (" These aren't considered unavailable" );
3379-
3380- case AvailableVersionComparison::Unavailable:
3381- if ((Attr->isLanguageVersionSpecific () ||
3382- Attr->isPackageDescriptionVersionSpecific ())
3383- && Attr->Introduced .has_value ())
3384- diags.diagnose (D, diag::availability_introduced_in_version, D,
3385- (Attr->isLanguageVersionSpecific () ?
3386- " Swift" : " PackageDescription" ),
3387- *Attr->Introduced )
3403+ switch (diagnosticInfo->getStatus ()) {
3404+ case UnavailabilityDiagnosticInfo::Status::AlwaysUnavailable:
3405+ diags.diagnose (D, diag::availability_marked_unavailable, D)
33883406 .highlight (Attr->getRange ());
3389- else
3390- diags.diagnose (D, diag::availability_marked_unavailable, D)
3407+ break ;
3408+ case UnavailabilityDiagnosticInfo::Status::IntroducedInVersion:
3409+ diags
3410+ .diagnose (D, diag::availability_introduced_in_version, D,
3411+ diagnosticInfo->getVersionedPlatform (), *Attr->Introduced )
33913412 .highlight (Attr->getRange ());
33923413 break ;
3393-
3394- case AvailableVersionComparison::Obsoleted:
3395- // FIXME: Use of the platformString here is non-awesome for application
3396- // extensions.
3397-
3398- StringRef platformDisplayString;
3399- if (Attr->isLanguageVersionSpecific ()) {
3400- platformDisplayString = " Swift" ;
3401- } else if (Attr->isPackageDescriptionVersionSpecific ()) {
3402- platformDisplayString = " PackageDescription" ;
3403- } else {
3404- platformDisplayString = platform;
3405- }
3406-
3407- diags.diagnose (D, diag::availability_obsoleted, D, platformDisplayString,
3408- *Attr->Obsoleted )
3409- .highlight (Attr->getRange ());
3414+ case UnavailabilityDiagnosticInfo::Status::Obsoleted:
3415+ diags
3416+ .diagnose (D, diag::availability_obsoleted, D,
3417+ diagnosticInfo->getVersionedPlatform (), *Attr->Obsoleted )
3418+ .highlight (Attr->getRange ());
34103419 break ;
34113420 }
34123421 return true ;
0 commit comments