The attribute makes the declaration unavailable from the perspective of clients
of the module's public interface and was creating a loophole that admitted
inappropriate unavailability.
Eventually, querying the `AvailabilityDomain` associated with an
`AvailabilitySpec` will require invoking a request that takes a `DeclContext`.
This means that any diagnostics related to the domain identified by an
`AvailabilitySpec` need to be emitted during type-checking rather than parsing.
This change migrates several `AvailabilitySpec` diagnostics from Parse to Sema
to unblock further work.
When diagnosing a declaration that is more available than its context, to
preserve source compatibility we need to downgrade the diagnostic to a warning
when the outermost declaration is an extension. This logic regressed with
https://github.com/swiftlang/swift/pull/77950 and my earlier attempt to fix
this (https://github.com/swiftlang/swift/pull/78832) misidentified what had
regressed.
Really resolves rdar://143423070.
When a method override is as available as the class it's a member of, then it
can't be any more available. It doesn't make sense to diagnose such a method as
less available than the method it overrides. This regressed recently for
methods belonging to classes that are nested inside extensions. The
availability of the derived class may be defined by its context, but the
compiler was only checking the availability attributes directly on the class.
Resolves rdar://143600638.
Availability checking for types was only suppressed when the immediate context
for the use of the type was explicitly marked unavailable. Availability is
lexical so the checking should be suppressed in the entire scope instead.
https://github.com/swiftlang/swift/pull/76621 caused a regression by skipping
the AST nodes nested under `defer` blocks. The node associated with a `defer`
block is implicit because it is a kind of closure context synthesized by the
compiler. However, the nodes it contains are not implicit and so they must be
visited by the `TypeRefinementContextBuilder`.
Resolves rdar://139012152
Marking an observer unavailable (or potentially unavailable) has no effect
since the compiler emits calls to them unconditionally.
Resolves rdar://80337141.
10.50 was once greater than any real macOS version, but now it compares
less than real released versions, which makes these tests depend on the
deployment target unnecessarily. Update these tests to use even larger
numbers to hopefully keep them independent a little longer.
Given the following test case, override availability checking produced an
erroneus diagnostic:
```
@available(macOS 10.15, *)
protocol P {
associatedtype A
var a: A { get set }
}
@available(macOS 13.0, *)
protocol Q: P {
// error: overriding _modify accessor for 'a' must be as available as
// declaration it overrides
var a: A { get set }
}
```
The synthesized `_modify` accessor in `Q` is explicitly marked available in
macOS 13, which is less available than the `_modify` accessor in `P`. The
availability of `Q` should limit the required availability of the override and
prevent the diagnostic, but the implementation had a bug where it checked the
availability of the context's type instead of the contextual self type's
declaration. In the example, the context's type is `Self` which does not have
annotated availability.
Resolves rdar://133573707.
These tests are using FileCheck to check the result of diagnostic
formatting in ways that don't match the new formatter. Force the old
formatter or, where possible, generalize so that they match both
formatters.
The type refinement context builder had a bunch of logic to try to
model type refinement contexts for the first variable declaration that
shows up within a pattern binding declaration. Instead, model this
more syntactically by creating a type refinement context for the
pattern binding declaration itself. This both addresses a regression
in the handling of `if #available` within a closure that's part of an
initializer, and fixes a bug in the same area where similar code has
explicit availability annotations.
Marking a stored property as unavailable with `@available` should be banned,
just like it already is banned for potential unavailability. Unavailable code
is not supposed be reachable at runtime, but unavailable properties with
storage create a back door into executing arbitrary unavailable code at
runtime:
```
@available(*, unavailable)
struct Unavailable {
init() {
print("Unavailable.init()")
}
}
struct S {
@available(*, unavailable)
var x = Unavailable()
}
_ = S() // prints "Unavailable.init()"
```
Resolves rdar://107449845
It turns out that we must allow declarations with `introduced:` availability
nested inside of other declarations that are `unavailable` in order to
influence weak linking. Stop diagnosing declarations as being more available
than their unavailable containers and revert some changes to availability
inference that were designed to avoid creating these nestings but caused
regressions for declarations marked `@_spi_available.`
Reverts parts of https://github.com/apple/swift/pull/64310,
https://github.com/apple/swift/pull/64015, and
https://github.com/apple/swift/pull/62900.
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
Previously, `TypeChecker::checkDeclarationAvailability()` would behave this way for most explicitly unavailable decls by _accident_. An explicitly unavailable decl has no introduction version, and the existing logic therefore would fail to find a lower bound on the availability of the decl. The edge case that exposed the fragility of this logic was an unavailable extension containing a member with it's own explicit availability. The unavailability of the extension ought to trump the availability of the member, but the existing logic couldn't detect that.
The compiler also ought to diagnose the conflicting availability annotations but I'd like to address that separately.
Resolves rdar://92551870
We would only check conditioanlavailability once we had committed
to a best witness. Instead, let's use this information to disambiguate
among multiple best witnesses, if we have them.
Access control and unconditional unavailability are still only
checked once the witness is chosen.
Fixes rdar://problem/77259046.
This cannot be supported for the same reasons struct and class stored
properties with potential unavailability cannot be supported.
It is possible that some users relied on this, because it worked in
some cases where the type metadata for the potentially unavailable
type was not actually needed for anything (eg, if the type was @frozen
and trivial, or a simple class reference). If this becomes an issue
we can downgrade this to a warning.
Note that just like the previous fix for stored properties, we do
still allow writing an '@available' attribute on the enum element if
the OS version is not any newer than the deployment target. This allows
annotating APIs with the OS version where they were introduced.
We were checking that the witness is at least as available as
the intersection of the protocol and the conforming type.
In the case where the conformance is defined in an extension,
this should actually be the intersection of the protocol and
the _availability of the extension_.
Fixes <rdar://problem/74114880>.
Access control, availability and exportability checking missed these
because of a baked-in assumption that getGenericParams() == nullptr
rules out the presence of a trailing where clause.
Concrete types can conform to unavailable protocols because
the witness table for the conformance is not required for use
with the concrete type itself.
However, protocols cannot have unavailable base protocols.
I believe this was an oversight of the original implementation
here.
This has the effect of rejecting unavailable overrides to available
methods in a similar way as overrides that are less available than the
introduction are rejected.
This affects module interfaces, interface generation in sourcekitd, and
diagnostics. Also fixes a fixit that was assuming the 'OSX' spelling when
computing the source range to replace.
Resolves rdar://problem/64667960
Most of the changes fall into a few categories:
* Replace explicit "x86_64" with %target-cpu in lit tests
* Cope with architecture differences in IR/asm/etc. macOS-specific tests
Instead, check them and their error handling right away.
In addition to fixing the crash in the radar, this also causes
us to emit unused variable warnings in functions containing
local functions.
Eventually, TC.definedFunctions should go away altogether.
Fixes <rdar://problem/53956342>.
This does several different things to improve how platforms are described in availability diagnostics:
• Mentions the platform in diagnostics for platform-specific @available(unavailable) attributes.
• Replaces “OS X” with “macOS”.
• Replaces “fooOS application extension” with “application extensions for fooOS”.
• Replaces “on fooOS” with “in fooOS”.
Fixes <rdar://problem/49963341>.
This makes diagnostics more verbose and accurate, because
it's possible to distinguish how many parameters there are
based on the message itself.
Also there are multiple diagnostic messages in a format of
`<descriptive-kind> <decl-name> ...` that get printed as
e.g. `subscript 'subscript'` if empty labels are omitted.
...and collapse StaticVar/ClassVar and StaticLet/ClassLet into
StaticProperty/ClassProperty.
"var" and "let" aren't great nouns to use in diagnostics to begin with,
especially alongside semantic terms like "instance method". Focus on
the type vs. non-type aspect instead with "property", which better
matches how people talk about member vars (and lets) anyway.
The code for performing the third pass using the GenericToArchetypeResolver
is still there, but it only runs for non-generic declarations.
The next step is to consolidate this path with the generic path.