Files
swift-mirror/test/Sema/availability_stored_unavailable.swift
Allan Shortlidge 9812c90023 Sema: Ban unavailable stored properties.
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
2023-04-04 08:52:39 -07:00

79 lines
2.5 KiB
Swift

// RUN: %target-typecheck-verify-swift -parse-as-library
// REQUIRES: OS=macosx
@available(macOS, unavailable)
struct UnavailableMacOSStruct {}
@available(*, unavailable)
public struct UniversallyUnavailableStruct {}
// Ok, initialization of globals is lazy and boxed.
@available(macOS, unavailable)
var unavailableMacOSGlobal: UnavailableMacOSStruct = .init()
@available(*, unavailable)
var universallyUnavailableGlobal: UniversallyUnavailableStruct = .init()
struct GoodAvailableStruct {
// Ok, computed property.
@available(macOS, unavailable)
var unavailableMacOS: UnavailableMacOSStruct {
get { UnavailableMacOSStruct() }
}
// Ok, initialization of static vars is lazy and boxed.
@available(macOS, unavailable)
static var staticUnavailableMacOS: UnavailableMacOSStruct = .init()
}
@available(macOS, unavailable)
struct GoodUnavailableMacOSStruct {
var unavailableMacOS: UnavailableMacOSStruct = .init()
lazy var lazyUnavailableMacOS: UnavailableMacOSStruct = .init()
// Ok, the container is unavailable.
@available(macOS, unavailable)
var unavailableMacOSExplicit: UnavailableMacOSStruct = .init()
}
@available(macOS, unavailable)
struct GoodNestedUnavailableMacOSStruct {
struct Inner {
var unavailableMacOS: UnavailableMacOSStruct = .init()
lazy var lazyUnavailableMacOS: UnavailableMacOSStruct = .init()
// Ok, the container is unavailable.
@available(macOS, unavailable)
var unavailableMacOSExplicit: UnavailableMacOSStruct = .init()
}
}
@available(*, unavailable)
struct GoodUniversallyUnavailableStruct {
var universallyUnavailable: UniversallyUnavailableStruct = .init()
lazy var lazyUniversallyUnavailable: UniversallyUnavailableStruct = .init()
@available(*, unavailable)
var universallyUnavailableExplicit: UniversallyUnavailableStruct = .init()
}
struct BadStruct {
// expected-error@+1 {{stored properties cannot be marked unavailable with '@available'}}
@available(macOS, unavailable)
var unavailableMacOS: UnavailableMacOSStruct = .init()
// expected-error@+1 {{stored properties cannot be marked unavailable with '@available'}}
@available(macOS, unavailable)
lazy var lazyUnavailableMacOS: UnavailableMacOSStruct = .init()
// expected-error@+1 {{stored properties cannot be marked unavailable with '@available'}}
@available(*, unavailable)
var universallyUnavailable: UniversallyUnavailableStruct = .init()
}
enum GoodAvailableEnum {
@available(macOS, unavailable)
case unavailableMacOS(UnavailableMacOSStruct)
}