SE-0290: Unavailability Condition

Doesn't the * mean "All versions of all other platforms and any future versions of this platform"?

So #available(iOS 13, *) would mean "iOS 13 (or later versions) + any tvOS + any macOS + any watchOS"

1 Like

Do removals have any compiler assistance with #available? I canā€™t think of an example of this to be able to test it out.

In terms of ergonomics, the main downside of the ProcessInfo API is that itā€™s relatively verbose and needs a separate check for platform. However, I think this could be overcome with a more Swifty API, eg

ProcessInfo.platform.unavailable(.ios, .version(13, 0))

1 Like

If you're going to make available into a method then it can be negated and there's no need for an unavailable method.

Ok, I think that most of the confusion when reading these unavailability conditions stems from the asterisk.

Let's consider this example:

   if #available(iOS 14, *) {
       print("I'm running iOS 14 or later, or any version of any other platform.")
   } else /*    #unavailable(iOS 14, *) or !#available(iOS 14, *)    */ {
       print("I'm running a version of iOS that is earlier than 14")
   }

I think the problem with #unavailable(iOS 14, *) is that the asterisk isn't actually saying anything about other platforms, so when you read it and try to apply the same mental logic as you do to an availability condition it's just weird. I think we should consider leaving the asterisk off for the unavailability conditions completely. Also for this reason, I think having #unavailable instead of !#available makes more sense, because they would have different asterisk requirements.

So instead the example might look like this:

 if #unavailable(iOS 14) {
    print("I'm running a version of iOS that is earlier than 14")
 } else {
   print("I'm running iOS 14 or later, or any version of any other platform.")
 }
6 Likes

I think that's the perfect solution.

2 Likes

In this case, if * means All versions of all other platforms and any future versions of this platform, then we don't need to remove it because it already dictates that the condition should return false. If you can compile for a platform, there will always be a version available.

I agree that it makes things weird though. I would be fine with removing it if that's the consensus but I personally think it's not an issue because it's just a matter of describing what * means.

I'm fine either way, I guess all I'm saying is that only one side of available/unavailable condition needs the asterisk. So for whatever reason that makes it weird if they both have the asterisk (in my mind at least).

Iā€™d like to revisit this. Without additional magic semantics, if #unavailable(iOS 14), #unavailable(macOS 11) will always be false. In order to compose #unavailable, you would need if #unavailable(iOS 14) || #unavailable(macOS 11). Note that && is not, er, available with #available because it is a ā€œclauseā€ rather than an expression.

This isnā€™t necessarily a show-stopper; as far as I can see the fact that , can be used as a general conjunction is just a weird wart in the language anyway. But in the case of #unavailable it isnā€™t ā€œuseless in a wayā€, itā€™s just useless. :slight_smile:

It's a good revisit. The original intention in that post was for * to always return true, but with the idea that it should instead return false it will make sense to disallow multiple unavailability checks.

Before we close the review, I think the conclusion is that we need to amend the proposal to contain that:

  • #unavailable(*) should return false, because a "future version/platform" will always be unavailable. It also better matches how the hypothetical !#available(*) would behave. Corrected: #unavailable(*) should return false, because if you're able to compile for a platform, then "all current and future versions" will always contain a version that is available. It also matches how the hypothetical !#available(*) would behave.
  • Given the above, multiple unavailabilities in the same statement should throw a warning, as two unavailabilities for different platforms will always cancel each other.
  • !#available can be diagnosed with a fix-it that converts it to #unavailable.

It's possible also to drop the asterisk as suggested, but I personally think the semantics of * already match the expected behavior.

1 Like

looks perfect

You mean true?

Argh, I confused myself which is a good indicator of how subjective * can be in this situation. The correct argument I meant to share is that it should return false because if you can compile for a platform, then it will always have a version available. Thus it would be impossible for "all current and future versions" to be unavailable.

Returned for revision

Based on this review thread's excellent discussion, the core team has decided to return this review for revision. The core team believes this is a merited addition to the language but that specific details of the proposal (as pointed out in the review thread) need to be addressed.

The core team feels that the spelling of #unavailable, as opposed to !#available, was the preferred path. As pointed out in the review discussion, #available is not a general expression. Further, the core team observed that people are likely to say "unavailable" instead of "not availableā€ in conversation ā€” further preferring the #unavailable spelling. The review thread also brought up a great insight to have a compiler fix-it for users reaching for !#available as the syntax ā€” that would be a great refinement (now or in the future) to the implementation.

The proposal needs revision to address the semantics of the #unavailable annotation for the platforms that are not specified. The wildcard * for #available has precise semantics, where * indicates the minimum deployment target for the unspecified platforms. The proposal needs to define the semantics for #unavailable for the platforms not specified and clearly explain how those semantics compose with the use of #available and other #unavailable annotations that may decorate a declaration.

Once the proposal is revised with those changes, the core team will run a second review of this proposal.

Thank you to everyone who participated in this review! The signal from the review was invaluable in gleaming these essential details to consider for this language enhancement.

13 Likes

The second review of this proposal is now running: