mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
Destructors are always called if declared, so allowing deinit to be declared as
unavailable (or potentially unavailable) creates a type checking loophole that
allows unavailable code to execute at runtime:
```
class C {
@available(*, unavailable)
deinit {
print("Oops")
}
}
_ = C() // prints "Oops"
```
Resolves rdar://106409012 and https://github.com/apple/swift/issues/63854.
53 lines
1.3 KiB
Swift
53 lines
1.3 KiB
Swift
// RUN: %target-typecheck-verify-swift -target %target-cpu-apple-macosx10.50
|
|
|
|
// REQUIRES: OS=macosx
|
|
|
|
@available(*, unavailable)
|
|
class Unavailable {
|
|
deinit {}
|
|
}
|
|
|
|
@available(*, unavailable)
|
|
class UnavailableWithUnavailableDeinit {
|
|
@available(*, unavailable)
|
|
deinit {}
|
|
}
|
|
|
|
@available(*, unavailable)
|
|
enum UnavailableEnum {
|
|
class NestedWithUnavailableDeinit {
|
|
@available(*, unavailable)
|
|
deinit {}
|
|
}
|
|
}
|
|
|
|
class DeinitUnavailable {
|
|
@available(*, unavailable) // expected-error {{deinitializer cannot be marked unavailable with '@available'}}
|
|
deinit {}
|
|
}
|
|
|
|
class DeinitUnavailableMacOS {
|
|
@available(macOS, unavailable) // expected-error {{deinitializer cannot be marked unavailable with '@available'}}
|
|
deinit {}
|
|
}
|
|
|
|
class AvailableAtDeploymentTargetDeinit {
|
|
@available(macOS 10.50, *)
|
|
deinit {}
|
|
}
|
|
|
|
class PotentiallyUnavailableDeinit {
|
|
@available(macOS 10.51, *) // expected-error {{deinitializer cannot be marked potentially unavailable with '@available'}}
|
|
deinit {}
|
|
}
|
|
|
|
@available(macOS 10.51, *)
|
|
func funcAvailable10_51() {}
|
|
|
|
class AlwaysAvailable { // expected-note {{add @available attribute to enclosing class}}
|
|
deinit {
|
|
funcAvailable10_51() // expected-error {{'funcAvailable10_51()' is only available in macOS 10.51 or newer}}
|
|
// expected-note@-1 {{add 'if #available' version check}}
|
|
}
|
|
}
|