@@ -113,25 +113,59 @@ DeclAvailabilityConstraints::getPrimaryConstraint() const {
113113 return result;
114114}
115115
116+ static bool canIgnoreConstraintInUnavailableContexts (
117+ const Decl *decl, const AvailabilityConstraint &constraint) {
118+ auto domain = constraint.getDomain ();
119+
120+ switch (constraint.getReason ()) {
121+ case AvailabilityConstraint::Reason::UnconditionallyUnavailable:
122+ // Always reject uses of universally unavailable declarations, regardless
123+ // of context, since there are no possible compilation configurations in
124+ // which they are available. However, make an exception for types and
125+ // conformances, which can sometimes be awkward to avoid references to.
126+ if (!isa<TypeDecl>(decl) && !isa<ExtensionDecl>(decl)) {
127+ if (domain.isUniversal () || domain.isSwiftLanguage ())
128+ return false ;
129+ }
130+ return true ;
131+
132+ case AvailabilityConstraint::Reason::PotentiallyUnavailable:
133+ switch (domain.getKind ()) {
134+ case AvailabilityDomain::Kind::Universal:
135+ case AvailabilityDomain::Kind::SwiftLanguage:
136+ case AvailabilityDomain::Kind::PackageDescription:
137+ case AvailabilityDomain::Kind::Embedded:
138+ case AvailabilityDomain::Kind::Custom:
139+ return false ;
140+ case AvailabilityDomain::Kind::Platform:
141+ // Platform availability only applies to the target triple that the
142+ // binary is being compiled for. Since the same declaration can be
143+ // potentially unavailable from a given context when compiling for one
144+ // platform, but available from that context when compiling for a
145+ // different platform, it is overly strict to enforce potential platform
146+ // unavailability constraints in contexts that are unavailable to that
147+ // platform.
148+ return true ;
149+ }
150+ return constraint.getDomain ().isPlatform ();
151+
152+ case AvailabilityConstraint::Reason::Obsoleted:
153+ case AvailabilityConstraint::Reason::UnavailableForDeployment:
154+ return false ;
155+ }
156+ }
157+
116158static bool
117- isInsideCompatibleUnavailableDeclaration (const Decl *decl,
118- const SemanticAvailableAttr &attr ,
119- const AvailabilityContext &context) {
159+ shouldIgnoreConstraintInContext (const Decl *decl,
160+ const AvailabilityConstraint &constraint ,
161+ const AvailabilityContext &context) {
120162 if (!context.isUnavailable ())
121163 return false ;
122164
123- if (!attr. isUnconditionallyUnavailable ( ))
165+ if (!canIgnoreConstraintInUnavailableContexts (decl, constraint ))
124166 return false ;
125167
126- // Refuse calling universally unavailable functions from unavailable code,
127- // but allow the use of types.
128- auto domain = attr.getDomain ();
129- if (!isa<TypeDecl>(decl) && !isa<ExtensionDecl>(decl)) {
130- if (domain.isUniversal () || domain.isSwiftLanguage ())
131- return false ;
132- }
133-
134- return context.containsUnavailableDomain (domain);
168+ return context.containsUnavailableDomain (constraint.getDomain ());
135169}
136170
137171// / Returns the `AvailabilityConstraint` that describes how \p attr restricts
@@ -218,8 +252,7 @@ static void getAvailabilityConstraintsForDecl(
218252 // declaration is unconditionally unavailable in a domain for which
219253 // the context is already unavailable.
220254 llvm::erase_if (constraints, [&](const AvailabilityConstraint &constraint) {
221- return isInsideCompatibleUnavailableDeclaration (decl, constraint.getAttr (),
222- context);
255+ return shouldIgnoreConstraintInContext (decl, constraint, context);
223256 });
224257}
225258
0 commit comments