Skip to content

[5.7] Sema: Allow explicitly available overrides to be as available as their context#60185

Merged
tshortli merged 1 commit intoswiftlang:release/5.7from
tshortli:incorrect-override-cannot-be-less-available-5.7
Jul 22, 2022
Merged

[5.7] Sema: Allow explicitly available overrides to be as available as their context#60185
tshortli merged 1 commit intoswiftlang:release/5.7from
tshortli:incorrect-override-cannot-be-less-available-5.7

Conversation

@tshortli
Copy link
Copy Markdown
Contributor

@tshortli tshortli commented Jul 21, 2022

Cherry-pick of #59857

Previously, the following test case produced an erroneous diagnostic:

class A {
  init() {}
}

@available(macOS 12, *)
class B: A {
  @available(macOS 12, *)
  override init() { // error: overriding 'init' must be as available as declaration it overrides
    super.init()
  }
}

The overridden init() constructor is as available as it can possibly be. Removing the explicit @available annotation suppressed the diagnostic.

To fix this, we check to see if the override is as available as its self type and accept it if it is.

You may be wondering how this works when the @available annotation is removed from override init() in the example. It turns out that AvailabilityInference::availableRange() returns a result that is based only on the explicit availability of the decl in question without taking the availability of the context into account (except when the context is an extension). So with the explicit annotation gone, both the base init() and the override are both considered to be "always" available. This is pretty unintuitive and arguably wrong. However, it seems like a lot of existing code depends on this behavior so I've left it for now.

Resolves rdar://96253347 and rdar://96235590.

…r context.

Previously, the following test case produced an erroneous diagnostic:

```
class A {
  init() {}
}

@available(macOS 12, *)
class B: A {
  @available(macOS 12, *)
  override init() { // error: overriding 'init' must be as available as declaration it overrides
    super.init()
  }
}
```

The overridden `init()` constructor is as available as it can possibly be. Removing the explicit `@available` annotation suppressed the diagnostic.

To fix this, we check to see if the override is as available as its self type and accept it if it is.

You may be wondering how this works when the `@available` annotation is removed from `override init()` in the example. It turns out that `AvailabilityInference::availableRange()` returns a result that is based only on the explicit availability of the decl in question without taking the availability of the context into account (except when the context is an extension). So with the explicit annotation gone, both the base `init()` and the override are both considered to be "always" available. This is pretty unintuitive and arguably wrong. However, it seems like a lot of existing code depends on this behavior so I've left it for now.

Resolves rdar://96253347
@tshortli tshortli added the r5.7 label Jul 21, 2022
@tshortli tshortli requested a review from a team as a code owner July 21, 2022 22:00
@tshortli
Copy link
Copy Markdown
Contributor Author

@swift-ci please test

@tkremenek
Copy link
Copy Markdown
Member

@swift-ci test macOS

@tshortli tshortli merged commit e2ebbae into swiftlang:release/5.7 Jul 22, 2022
@tshortli tshortli deleted the incorrect-override-cannot-be-less-available-5.7 branch July 22, 2022 04:12
@AnthonyLatsis AnthonyLatsis added 🍒 release cherry pick Flag: Release branch cherry picks swift 5.7 labels Jan 9, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

🍒 release cherry pick Flag: Release branch cherry picks swift 5.7

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants