@@ -2841,36 +2841,72 @@ bool swift::diagnoseExplicitUnavailability(const ValueDecl *D, SourceRange R,
2841
2841
});
2842
2842
}
2843
2843
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);
2852
2897
if (!attr)
2853
- return false ;
2898
+ return std::nullopt ;
2854
2899
2855
2900
// Calling unavailable code from within code with the same
2856
2901
// unavailability is OK -- the eventual caller can't call the
2857
2902
// enclosing code in the same situations it wouldn't be able to
2858
2903
// 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;
2871
2906
2872
- StringRef platform;
2873
- auto behavior = DiagnosticBehavior::Unspecified;
2907
+ ASTContext &ctx = decl->getASTContext ();
2908
+ StringRef platform = " " ;
2909
+ StringRef versionedPlatform = " " ;
2874
2910
switch (attr->getPlatformAgnosticAvailability ()) {
2875
2911
case PlatformAgnosticAvailabilityKind::Deprecated:
2876
2912
llvm_unreachable (" shouldn't see deprecations in explicit unavailability" );
@@ -2881,73 +2917,96 @@ bool swift::diagnoseExplicitUnavailability(SourceLoc loc,
2881
2917
case PlatformAgnosticAvailabilityKind::None:
2882
2918
case PlatformAgnosticAvailabilityKind::Unavailable:
2883
2919
if (attr->Platform != PlatformKind::none) {
2884
- // This was platform-specific; indicate the platform.
2885
2920
platform = attr->prettyPlatformString ();
2886
- break ;
2921
+ versionedPlatform = platform ;
2887
2922
}
2888
-
2889
- // Downgrade unavailable Sendable conformance diagnostics where
2890
- // appropriate.
2891
- behavior = behaviorLimitForExplicitUnavailability (
2892
- rootConf, where.getDeclContext ());
2893
- LLVM_FALLTHROUGH;
2894
-
2923
+ break ;
2895
2924
case PlatformAgnosticAvailabilityKind::SwiftVersionSpecific:
2925
+ versionedPlatform = " Swift" ;
2926
+ break ;
2896
2927
case PlatformAgnosticAvailabilityKind::PackageDescriptionVersionSpecific:
2897
- // We don't want to give further detail about these.
2898
- platform = " " ;
2928
+ versionedPlatform = " PackageDescription" ;
2899
2929
break ;
2900
-
2901
2930
case PlatformAgnosticAvailabilityKind::UnavailableInSwift:
2902
- // This API is explicitly unavailable in Swift.
2903
2931
platform = " Swift" ;
2904
2932
break ;
2905
2933
}
2906
2934
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
-
2914
2935
switch (attr->getVersionAvailability (ctx)) {
2915
2936
case AvailableVersionComparison::Available:
2916
2937
case AvailableVersionComparison::PotentiallyUnavailable:
2917
2938
llvm_unreachable (" These aren't considered unavailable" );
2918
2939
2919
2940
case AvailableVersionComparison::Unavailable:
2920
2941
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
+ }
2933
2952
break ;
2934
2953
2935
2954
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
+ }
2947
2960
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 ());
2951
3010
break ;
2952
3011
}
2953
3012
return true ;
@@ -3282,52 +3341,21 @@ bool swift::diagnoseExplicitUnavailability(
3282
3341
const ExportContext &Where,
3283
3342
DeclAvailabilityFlags Flags,
3284
3343
llvm::function_ref<void (InFlightDiagnostic &)> attachRenameFixIts) {
3285
- auto *Attr = AvailableAttr::isUnavailable (D );
3286
- if (!Attr )
3344
+ auto diagnosticInfo = getExplicitUnavailabilityDiagnosticInfo (D, Where );
3345
+ if (!diagnosticInfo )
3287
3346
return false ;
3288
3347
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
+ }
3295
3354
3296
3355
SourceLoc Loc = R.Start ;
3297
-
3298
3356
ASTContext &ctx = D->getASTContext ();
3299
3357
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 ();
3331
3359
3332
3360
// TODO: Consider removing this.
3333
3361
// ObjC keypaths components weren't checked previously, so errors are demoted
@@ -3372,41 +3400,22 @@ bool swift::diagnoseExplicitUnavailability(
3372
3400
.limitBehavior (limit);
3373
3401
}
3374
3402
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)
3388
3406
.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 )
3391
3412
.highlight (Attr->getRange ());
3392
3413
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 ());
3410
3419
break ;
3411
3420
}
3412
3421
return true ;
0 commit comments