@@ -55,16 +55,17 @@ concreteSyntaxDeclForAvailableAttribute(const Decl *AbstractSyntaxDecl);
5555// / Emit a diagnostic for references to declarations that have been
5656// / marked as unavailable, either through "unavailable" or "obsoleted:".
5757static bool diagnoseExplicitUnavailability (
58- SourceLoc loc, const RootProtocolConformance *rootConf,
59- const ExtensionDecl *ext, const ExportContext &where,
58+ SourceLoc loc, const AvailabilityConstraint &constraint,
59+ const RootProtocolConformance *rootConf, const ExtensionDecl *ext,
60+ const ExportContext &where,
6061 bool warnIfConformanceUnavailablePreSwift6 = false ,
6162 bool preconcurrency = false );
6263
6364// / Emit a diagnostic for references to declarations that have been
6465// / marked as unavailable, either through "unavailable" or "obsoleted:".
6566static bool diagnoseExplicitUnavailability (
66- const ValueDecl *D, SourceRange R, const ExportContext &Where ,
67- DeclAvailabilityFlags Flags,
67+ const ValueDecl *D, SourceRange R, const AvailabilityConstraint &constraint ,
68+ const ExportContext &Where, DeclAvailabilityFlags Flags,
6869 llvm::function_ref<void (InFlightDiagnostic &, StringRef)>
6970 attachRenameFixIts);
7071
@@ -2951,9 +2952,16 @@ void swift::diagnoseOverrideOfUnavailableDecl(ValueDecl *override,
29512952 return ;
29522953 }
29532954
2955+ // FIXME: [availability] Take an unsatisfied constraint as input instead of
2956+ // recomputing it.
29542957 ExportContext where = ExportContext::forDeclSignature (override , nullptr );
2958+ auto constraint =
2959+ getUnsatisfiedAvailabilityConstraint (base, where.getAvailability ());
2960+ if (!constraint)
2961+ return ;
2962+
29552963 diagnoseExplicitUnavailability (
2956- base, override ->getLoc (), where,
2964+ base, override ->getLoc (), *constraint, where,
29572965 /* Flags*/ std::nullopt ,
29582966 [&override , &ctx](InFlightDiagnostic &diag, StringRef rename) {
29592967 ParsedDeclName parsedName = parseDeclName (rename);
@@ -2983,125 +2991,63 @@ void swift::diagnoseOverrideOfUnavailableDecl(ValueDecl *override,
29832991
29842992// / Emit a diagnostic for references to declarations that have been
29852993// / marked as unavailable, either through "unavailable" or "obsoleted:".
2986- static bool diagnoseExplicitUnavailability (const ValueDecl *D, SourceRange R,
2987- const ExportContext &Where,
2988- const Expr *call,
2989- DeclAvailabilityFlags Flags) {
2994+ static bool diagnoseExplicitUnavailability (
2995+ const ValueDecl *D, SourceRange R, const AvailabilityConstraint &constraint,
2996+ const ExportContext &Where, const Expr *call, DeclAvailabilityFlags Flags) {
29902997 return diagnoseExplicitUnavailability (
2991- D, R, Where, Flags, [=](InFlightDiagnostic &diag, StringRef rename) {
2998+ D, R, constraint, Where, Flags,
2999+ [=](InFlightDiagnostic &diag, StringRef rename) {
29923000 fixItAvailableAttrRename (diag, R, D, rename, call);
29933001 });
29943002}
29953003
2996- // / Represents common information needed to emit diagnostics about explicitly
2997- // / unavailable declarations.
2998- class UnavailabilityDiagnosticInfo {
2999- public:
3000- enum class Status {
3001- // / The declaration is marked `unavailable`, potentially on a specific
3002- // / platform.
3003- AlwaysUnavailable,
3004-
3005- // / The declaration is not available until, for example, a later Swift
3006- // / language mode.
3007- IntroducedInVersion,
3008-
3009- // / The declaration was obsoleted in a previous version.
3010- Obsoleted,
3011- };
3012-
3013- private:
3014- Status DiagnosticStatus;
3015- SemanticAvailableAttr Attr;
3016-
3017- public:
3018- UnavailabilityDiagnosticInfo (Status status, const SemanticAvailableAttr &attr)
3019- : DiagnosticStatus(status), Attr(attr) {};
3020-
3021- Status getStatus () const { return DiagnosticStatus; }
3022- SemanticAvailableAttr getAttr () const { return Attr; }
3023- AvailabilityDomain getDomain () const { return Attr.getDomain (); }
3024- StringRef getDomainName () const {
3025- return getDomain ().getNameForDiagnostics ();
3026- }
3004+ bool shouldHideDomainNameForConstraintDiagnostic (
3005+ const AvailabilityConstraint &constraint) {
3006+ switch (constraint.getDomain ().getKind ()) {
3007+ case AvailabilityDomain::Kind::Universal:
3008+ case AvailabilityDomain::Kind::Embedded:
3009+ return true ;
3010+ case AvailabilityDomain::Kind::Platform:
3011+ return false ;
30273012
3028- bool shouldHideDomainNameInUnversionedDiagnostics () const {
3029- switch (getDomain ().getKind ()) {
3030- case AvailabilityDomain::Kind::Universal:
3031- case AvailabilityDomain::Kind::Embedded:
3032- return true ;
3033- case AvailabilityDomain::Kind::Platform:
3013+ case AvailabilityDomain::Kind::PackageDescription:
3014+ case AvailabilityDomain::Kind::SwiftLanguage:
3015+ switch (constraint.getKind ()) {
3016+ case AvailabilityConstraint::Kind::AlwaysUnavailable:
3017+ case AvailabilityConstraint::Kind::IntroducedInNewerVersion:
30343018 return false ;
3035-
3036- case AvailabilityDomain::Kind::PackageDescription:
3037- case AvailabilityDomain::Kind::SwiftLanguage:
3038- switch (DiagnosticStatus) {
3039- case Status::AlwaysUnavailable:
3040- return false ;
3041- case Status::IntroducedInVersion:
3042- case Status::Obsoleted:
3043- return true ;
3044- }
3045- }
3046- }
3047- };
3048-
3049- static std::optional<UnavailabilityDiagnosticInfo>
3050- getExplicitUnavailabilityDiagnosticInfo (const Decl *decl,
3051- const ExportContext &where) {
3052- auto attr = where.shouldDiagnoseDeclAsUnavailable (decl);
3053- if (!attr)
3054- return std::nullopt ;
3055-
3056- ASTContext &ctx = decl->getASTContext ();
3057-
3058- switch (attr->getVersionAvailability (ctx)) {
3059- case AvailableVersionComparison::Available:
3060- case AvailableVersionComparison::PotentiallyUnavailable:
3061- llvm_unreachable (" These aren't considered unavailable" );
3062-
3063- case AvailableVersionComparison::Unavailable:
3064- if ((attr->isSwiftLanguageModeSpecific () ||
3065- attr->isPackageDescriptionVersionSpecific ()) &&
3066- attr->getIntroduced ()) {
3067- return UnavailabilityDiagnosticInfo (
3068- UnavailabilityDiagnosticInfo::Status::IntroducedInVersion, *attr);
3069- } else {
3070- return UnavailabilityDiagnosticInfo (
3071- UnavailabilityDiagnosticInfo::Status::AlwaysUnavailable, *attr);
3019+ case AvailabilityConstraint::Kind::RequiresVersion:
3020+ case AvailabilityConstraint::Kind::Obsoleted:
3021+ return true ;
30723022 }
3073- break ;
3074-
3075- case AvailableVersionComparison::Obsoleted:
3076- return UnavailabilityDiagnosticInfo (
3077- UnavailabilityDiagnosticInfo::Status::Obsoleted, *attr);
30783023 }
30793024}
30803025
3081- bool diagnoseExplicitUnavailability (
3082- SourceLoc loc, const RootProtocolConformance *rootConf,
3083- const ExtensionDecl *ext, const ExportContext &where,
3084- bool warnIfConformanceUnavailablePreSwift6,
3085- bool preconcurrency) {
3086- // Invertible protocols are never unavailable.
3087- if (rootConf->getProtocol ()->getInvertibleProtocolKind ())
3026+ bool diagnoseExplicitUnavailability (SourceLoc loc,
3027+ const AvailabilityConstraint &constraint,
3028+ const RootProtocolConformance *rootConf,
3029+ const ExtensionDecl *ext,
3030+ const ExportContext &where,
3031+ bool warnIfConformanceUnavailablePreSwift6,
3032+ bool preconcurrency) {
3033+ if (constraint.isConditionallySatisfiable ())
30883034 return false ;
30893035
3090- auto diagnosticInfo = getExplicitUnavailabilityDiagnosticInfo (ext, where);
3091- if (!diagnosticInfo )
3036+ // Invertible protocols are never unavailable.
3037+ if (rootConf-> getProtocol ()-> getInvertibleProtocolKind () )
30923038 return false ;
30933039
30943040 ASTContext &ctx = ext->getASTContext ();
30953041 auto &diags = ctx.Diags ;
30963042
30973043 auto type = rootConf->getType ();
30983044 auto proto = rootConf->getProtocol ()->getDeclaredInterfaceType ();
3099- StringRef versionedPlatform = diagnosticInfo-> getDomainName ();
3100- StringRef platform =
3101- diagnosticInfo-> shouldHideDomainNameInUnversionedDiagnostics ( )
3102- ? " "
3103- : versionedPlatform;
3104- auto attr = diagnosticInfo-> getAttr ();
3045+ auto domain = constraint. getDomain ();
3046+ StringRef versionedPlatform = domain. getNameForDiagnostics ();
3047+ StringRef platform = shouldHideDomainNameForConstraintDiagnostic (constraint )
3048+ ? " "
3049+ : versionedPlatform;
3050+ auto attr = constraint. getAttr ();
31053051
31063052 // Downgrade unavailable Sendable conformance diagnostics where
31073053 // appropriate.
@@ -3115,23 +3061,25 @@ bool diagnoseExplicitUnavailability(
31153061 .limitBehaviorWithPreconcurrency (behavior, preconcurrency)
31163062 .warnUntilSwiftVersionIf (warnIfConformanceUnavailablePreSwift6, 6 );
31173063
3118- switch (diagnosticInfo-> getStatus ()) {
3119- case UnavailabilityDiagnosticInfo::Status ::AlwaysUnavailable:
3064+ switch (constraint. getKind ()) {
3065+ case AvailabilityConstraint::Kind ::AlwaysUnavailable:
31203066 diags
31213067 .diagnose (ext, diag::conformance_availability_marked_unavailable, type,
31223068 proto)
31233069 .highlight (attr.getParsedAttr ()->getRange ());
31243070 break ;
3125- case UnavailabilityDiagnosticInfo::Status::IntroducedInVersion :
3071+ case AvailabilityConstraint::Kind::RequiresVersion :
31263072 diags.diagnose (ext, diag::conformance_availability_introduced_in_version,
31273073 type, proto, versionedPlatform, *attr.getIntroduced ());
31283074 break ;
3129- case UnavailabilityDiagnosticInfo::Status ::Obsoleted:
3075+ case AvailabilityConstraint::Kind ::Obsoleted:
31303076 diags
31313077 .diagnose (ext, diag::conformance_availability_obsoleted, type, proto,
31323078 versionedPlatform, *attr.getObsoleted ())
31333079 .highlight (attr.getParsedAttr ()->getRange ());
31343080 break ;
3081+ case AvailabilityConstraint::Kind::IntroducedInNewerVersion:
3082+ llvm_unreachable (" unexpected constraint" );
31353083 }
31363084 return true ;
31373085}
@@ -3510,15 +3458,14 @@ static void checkFunctionConversionAvailability(Type srcType, Type destType,
35103458}
35113459
35123460bool diagnoseExplicitUnavailability (
3513- const ValueDecl *D, SourceRange R, const ExportContext &Where ,
3514- DeclAvailabilityFlags Flags,
3461+ const ValueDecl *D, SourceRange R, const AvailabilityConstraint &constraint ,
3462+ const ExportContext &Where, DeclAvailabilityFlags Flags,
35153463 llvm::function_ref<void (InFlightDiagnostic &, StringRef)>
35163464 attachRenameFixIts) {
3517- auto diagnosticInfo = getExplicitUnavailabilityDiagnosticInfo (D, Where);
3518- if (!diagnosticInfo)
3465+ if (constraint.isConditionallySatisfiable ())
35193466 return false ;
35203467
3521- auto Attr = diagnosticInfo-> getAttr ();
3468+ auto Attr = constraint. getAttr ();
35223469 if (Attr.getDomain ().isSwiftLanguage () && !Attr.isVersionSpecific ()) {
35233470 if (shouldAllowReferenceToUnavailableInSwiftDeclaration (D, Where))
35243471 return false ;
@@ -3527,11 +3474,11 @@ bool diagnoseExplicitUnavailability(
35273474 SourceLoc Loc = R.Start ;
35283475 ASTContext &ctx = D->getASTContext ();
35293476 auto &diags = ctx.Diags ;
3530- StringRef versionedPlatform = diagnosticInfo-> getDomainName ();
3531- StringRef platform =
3532- diagnosticInfo-> shouldHideDomainNameInUnversionedDiagnostics ( )
3533- ? " "
3534- : versionedPlatform;
3477+ auto domain = constraint. getDomain ();
3478+ StringRef versionedPlatform = domain. getNameForDiagnostics ();
3479+ StringRef platform = shouldHideDomainNameForConstraintDiagnostic (constraint )
3480+ ? " "
3481+ : versionedPlatform;
35353482
35363483 // TODO: Consider removing this.
35373484 // ObjC keypaths components weren't checked previously, so errors are demoted
@@ -3579,23 +3526,26 @@ bool diagnoseExplicitUnavailability(
35793526 }
35803527
35813528 auto sourceRange = Attr.getParsedAttr ()->getRange ();
3582- switch (diagnosticInfo-> getStatus ()) {
3583- case UnavailabilityDiagnosticInfo::Status ::AlwaysUnavailable:
3529+ switch (constraint. getKind ()) {
3530+ case AvailabilityConstraint::Kind ::AlwaysUnavailable:
35843531 diags.diagnose (D, diag::availability_marked_unavailable, D)
35853532 .highlight (sourceRange);
35863533 break ;
3587- case UnavailabilityDiagnosticInfo::Status::IntroducedInVersion :
3534+ case AvailabilityConstraint::Kind::RequiresVersion :
35883535 diags
35893536 .diagnose (D, diag::availability_introduced_in_version, D,
35903537 versionedPlatform, *Attr.getIntroduced ())
35913538 .highlight (sourceRange);
35923539 break ;
3593- case UnavailabilityDiagnosticInfo::Status ::Obsoleted:
3540+ case AvailabilityConstraint::Kind ::Obsoleted:
35943541 diags
35953542 .diagnose (D, diag::availability_obsoleted, D, versionedPlatform,
35963543 *Attr.getObsoleted ())
35973544 .highlight (sourceRange);
35983545 break ;
3546+ case AvailabilityConstraint::Kind::IntroducedInNewerVersion:
3547+ llvm_unreachable (" unexpected constraint" );
3548+ break ;
35993549 }
36003550 return true ;
36013551}
@@ -4217,9 +4167,8 @@ bool swift::diagnoseDeclAvailability(const ValueDecl *D, SourceRange R,
42174167 auto constraint =
42184168 getUnsatisfiedAvailabilityConstraint (D, Where.getAvailability ());
42194169
4220- if (constraint && !constraint->isConditionallySatisfiable ()) {
4221- // FIXME: diagnoseExplicitUnavailability should take an unmet requirement
4222- if (diagnoseExplicitUnavailability (D, R, Where, call, Flags))
4170+ if (constraint) {
4171+ if (diagnoseExplicitUnavailability (D, R, *constraint, Where, call, Flags))
42234172 return true ;
42244173 }
42254174
@@ -4739,11 +4688,9 @@ swift::diagnoseConformanceAvailability(SourceLoc loc,
47394688 auto constraint =
47404689 getUnsatisfiedAvailabilityConstraint (ext, where.getAvailability ());
47414690 if (constraint) {
4742- // FIXME: diagnoseExplicitUnavailability() should take unmet requirement
4743- if (diagnoseExplicitUnavailability (
4744- loc, rootConf, ext, where,
4745- warnIfConformanceUnavailablePreSwift6,
4746- preconcurrency)) {
4691+ if (diagnoseExplicitUnavailability (loc, *constraint, rootConf, ext, where,
4692+ warnIfConformanceUnavailablePreSwift6,
4693+ preconcurrency)) {
47474694 maybeEmitAssociatedTypeNote ();
47484695 return true ;
47494696 }
0 commit comments