Files
swift-mirror/test/Availability/availability_accessors.swift
Allan Shortlidge ee988c0da8 Sema: Infer key path immutability during expression availability checking.
Accessor availability diagnostics for key path expressions were first
introduced by https://github.com/swiftlang/swift/pull/83931. Those changes were
insufficient because sometimes key path expressions are generated in the AST
with more mutability than is needed by the context and so setter availability
could be diagnosed inappropriately. Key path expression binding was refined in
https://github.com/swiftlang/swift/pull/84491 to make this less likely to
occur. However, there are still some circumstances in which a mutable key path
is generated in the AST and then immediately coerced into an immutable key path
to satisfy the contextual type. This change infers the immutability of these key
path expressions by looking through surrounding conversion expressions.
2025-09-25 07:13:18 -07:00

646 lines
39 KiB
Swift

// RUN: %target-typecheck-verify-swift -parse-as-library -module-name MyModule
struct Nested {
var b: Int
@discardableResult
mutating func setToZero() -> Int {
let prev = b
b = 0
return prev
}
}
struct StructValue {
static var defaultValue: Self { .init(a: Nested(b: 1)) }
var a: Nested
subscript(_ i: Int) -> Nested {
get { a }
set { a = newValue }
}
@discardableResult
mutating func setToZero() -> Int {
let prev = a.b
a.setToZero()
return prev
}
}
class ClassValue {
var a: Nested
required init(a: Nested) {
self.a = a
}
subscript(_ i: Int) -> Nested {
get { a }
set { a = newValue }
}
@discardableResult func setToZero() -> Int {
let prev = a.b
a.setToZero()
return prev
}
}
struct BaseStruct<T> {
var available: T {
get { fatalError() }
set { }
}
var unavailableGetter: T {
@available(*, unavailable)
get { fatalError() } // expected-note 73 {{getter for 'unavailableGetter' has been explicitly marked unavailable here}}
set { }
}
var unavailableSetter: T {
get { fatalError() }
@available(*, unavailable)
set { fatalError() } // expected-note 33 {{setter for 'unavailableSetter' has been explicitly marked unavailable here}}
}
var unavailableGetterAndSetter: T {
@available(*, unavailable)
get { fatalError() } // expected-note 71 {{getter for 'unavailableGetterAndSetter' has been explicitly marked unavailable here}}
@available(*, unavailable)
set { fatalError() } // expected-note 33 {{setter for 'unavailableGetterAndSetter' has been explicitly marked unavailable here}}
}
var deprecatedGetter: T {
@available(*, deprecated, message: "reading not recommended")
get { fatalError() }
set { }
}
var deprecatedSetter: T {
get { fatalError() }
@available(*, deprecated, message: "writing not recommended")
set { }
}
}
struct SubscriptHelper {
subscript<T>(available t: T) -> () {
get { }
set { }
}
subscript<T>(unavailableGetter t: T) -> () {
@available(*, unavailable)
get { } // expected-note {{getter for 'subscript(unavailableGetter:)' has been explicitly marked unavailable here}}
set { }
}
subscript<T>(unavailableSetter t: T) -> () {
get { }
@available(*, unavailable)
set { } // expected-note {{setter for 'subscript(unavailableSetter:)' has been explicitly marked unavailable here}}
}
subscript<T>(unavailableGetterAndSetter t: T) -> () {
@available(*, unavailable)
get { } // expected-note {{getter for 'subscript(unavailableGetterAndSetter:)' has been explicitly marked unavailable here}}
@available(*, unavailable)
set { } // expected-note {{setter for 'subscript(unavailableGetterAndSetter:)' has been explicitly marked unavailable here}}
}
}
@discardableResult func takesInOut<T>(_ t: inout T) -> T {
return t
}
func testDiscardedRValueLoads_Struct() {
var x = BaseStruct<StructValue>() // expected-warning {{variable 'x' was never mutated; consider changing to 'let' constant}}
_ = x.available
_ = x.available.a
_ = x.available[0]
_ = x.available[0].b
_ = x.unavailableGetter // expected-error {{getter for 'unavailableGetter' is unavailable}}
_ = x.unavailableGetter.a // expected-error {{getter for 'unavailableGetter' is unavailable}}
_ = x.unavailableGetter[0] // expected-error {{getter for 'unavailableGetter' is unavailable}}
_ = x.unavailableGetter[0].b // expected-error {{getter for 'unavailableGetter' is unavailable}}
_ = x.unavailableSetter
_ = x.unavailableSetter.a
_ = x.unavailableSetter[0]
_ = x.unavailableSetter[0].b
_ = x.unavailableGetterAndSetter // expected-error {{getter for 'unavailableGetterAndSetter' is unavailable}}
_ = x.unavailableGetterAndSetter.a // expected-error {{getter for 'unavailableGetterAndSetter' is unavailable}}
_ = x.unavailableGetterAndSetter[0] // expected-error {{getter for 'unavailableGetterAndSetter' is unavailable}}
_ = x.unavailableGetterAndSetter[0].b // expected-error {{getter for 'unavailableGetterAndSetter' is unavailable}}
}
func testDiscardedRValueLoads_Class() {
var x = BaseStruct<ClassValue>() // expected-warning {{variable 'x' was never mutated; consider changing to 'let' constant}}
_ = x.available
_ = x.available.a
_ = x.available[0]
_ = x.available[0].b
_ = x.unavailableGetter // expected-error {{getter for 'unavailableGetter' is unavailable}}
_ = x.unavailableGetter.a // expected-error {{getter for 'unavailableGetter' is unavailable}}
_ = x.unavailableGetter[0] // expected-error {{getter for 'unavailableGetter' is unavailable}}
_ = x.unavailableGetter[0].b // expected-error {{getter for 'unavailableGetter' is unavailable}}
_ = x.unavailableSetter
_ = x.unavailableSetter.a
_ = x.unavailableSetter[0]
_ = x.unavailableSetter[0].b
_ = x.unavailableGetterAndSetter // expected-error {{getter for 'unavailableGetterAndSetter' is unavailable}}
_ = x.unavailableGetterAndSetter.a // expected-error {{getter for 'unavailableGetterAndSetter' is unavailable}}
_ = x.unavailableGetterAndSetter[0] // expected-error {{getter for 'unavailableGetterAndSetter' is unavailable}}
_ = x.unavailableGetterAndSetter[0].b // expected-error {{getter for 'unavailableGetterAndSetter' is unavailable}}
}
func testLValueAssignments_Struct(_ someValue: StructValue) {
var x = BaseStruct<StructValue>()
x.available = someValue
x.available.a = someValue.a
x.available[0] = someValue.a
x.available[0].b = 1
x.unavailableGetter = someValue
x.unavailableGetter.a = someValue.a // expected-error {{getter for 'unavailableGetter' is unavailable}}
x.unavailableGetter[0] = someValue.a // expected-error {{getter for 'unavailableGetter' is unavailable}}
x.unavailableGetter[0].b = 1 // expected-error {{getter for 'unavailableGetter' is unavailable}}
x.unavailableSetter = someValue // expected-error {{setter for 'unavailableSetter' is unavailable}}
x.unavailableSetter.a = someValue.a // expected-error {{setter for 'unavailableSetter' is unavailable}}
x.unavailableSetter[0] = someValue.a // expected-error {{setter for 'unavailableSetter' is unavailable}}
x.unavailableSetter[0].b = 1 // expected-error {{setter for 'unavailableSetter' is unavailable}}
x.unavailableGetterAndSetter = someValue // expected-error {{setter for 'unavailableGetterAndSetter' is unavailable}}
x.unavailableGetterAndSetter.a = someValue.a // expected-error {{getter for 'unavailableGetterAndSetter' is unavailable}} expected-error {{setter for 'unavailableGetterAndSetter' is unavailable}}
x.unavailableGetterAndSetter[0] = someValue.a // expected-error {{getter for 'unavailableGetterAndSetter' is unavailable}} expected-error {{setter for 'unavailableGetterAndSetter' is unavailable}}
x.unavailableGetterAndSetter[0].b = 1 // expected-error {{getter for 'unavailableGetterAndSetter' is unavailable}} expected-error {{setter for 'unavailableGetterAndSetter' is unavailable}}
}
func testLValueAssignments_Class(_ someValue: ClassValue) {
var x = BaseStruct<ClassValue>()
x.available = someValue
x.available.a = someValue.a
x.available[0] = someValue.a
x.available[0].b = 1
x.unavailableGetter = someValue
x.unavailableGetter.a = someValue.a // expected-error {{getter for 'unavailableGetter' is unavailable}}
x.unavailableGetter[0] = someValue.a // expected-error {{getter for 'unavailableGetter' is unavailable}}
x.unavailableGetter[0].b = 1 // expected-error {{getter for 'unavailableGetter' is unavailable}}
x.unavailableSetter = someValue // expected-error {{setter for 'unavailableSetter' is unavailable}}
x.unavailableSetter.a = someValue.a
x.unavailableSetter[0] = someValue.a
x.unavailableSetter[0].b = 1
x.unavailableGetterAndSetter = someValue // expected-error {{setter for 'unavailableGetterAndSetter' is unavailable}}
x.unavailableGetterAndSetter.a = someValue.a // expected-error {{getter for 'unavailableGetterAndSetter' is unavailable}}
x.unavailableGetterAndSetter[0] = someValue.a // expected-error {{getter for 'unavailableGetterAndSetter' is unavailable}}
x.unavailableGetterAndSetter[0].b = 1 // expected-error {{getter for 'unavailableGetterAndSetter' is unavailable}}
}
func testSubscripts(_ s: BaseStruct<StructValue>) {
var x = BaseStruct<SubscriptHelper>()
// Available subscript, available member, varying argument availability
x.available[available: s.available] = ()
x.available[available: s.unavailableGetter] = () // expected-error {{getter for 'unavailableGetter' is unavailable}}
x.available[available: s.unavailableSetter] = ()
x.available[available: s.unavailableGetterAndSetter] = () // expected-error {{getter for 'unavailableGetterAndSetter' is unavailable}}
_ = x.available[available: s.available]
_ = x.available[available: s.unavailableGetter] // expected-error {{getter for 'unavailableGetter' is unavailable}}
_ = x.available[available: s.unavailableSetter]
_ = x.available[available: s.unavailableGetterAndSetter] // expected-error {{getter for 'unavailableGetterAndSetter' is unavailable}}
// Varying subscript availability, available member, available argument
x.available[unavailableGetter: s.available] = ()
x.available[unavailableSetter: s.available] = () // expected-error {{setter for 'subscript(unavailableSetter:)' is unavailable}}
x.available[unavailableGetterAndSetter: s.available] = () // expected-error {{setter for 'subscript(unavailableGetterAndSetter:)' is unavailable}}
_ = x.available[unavailableGetter: s.available] // expected-error {{getter for 'subscript(unavailableGetter:)' is unavailable}}
_ = x.available[unavailableSetter: s.available]
_ = x.available[unavailableGetterAndSetter: s.available] // expected-error {{getter for 'subscript(unavailableGetterAndSetter:)' is unavailable}}
// Available subscript, varying member availability, available argument
x.unavailableGetter[available: s.available] = () // expected-error {{getter for 'unavailableGetter' is unavailable}}
x.unavailableSetter[available: s.available] = () // expected-error {{setter for 'unavailableSetter' is unavailable}}
x.unavailableGetterAndSetter[available: s.available] = () // expected-error {{getter for 'unavailableGetterAndSetter' is unavailable}} expected-error {{setter for 'unavailableGetterAndSetter' is unavailable}}
_ = x.unavailableGetter[available: s.available] // expected-error {{getter for 'unavailableGetter' is unavailable}}
_ = x.unavailableSetter[available: s.available]
_ = x.unavailableGetterAndSetter[available: s.available] // expected-error {{getter for 'unavailableGetterAndSetter' is unavailable}}
}
func testDiscardedKeyPathApplicationLoads_Struct() {
let a = [0]
var x = BaseStruct<StructValue>()
_ = x[keyPath: \.available]
_ = x[keyPath: \.available.a]
_ = x[keyPath: \.available[0]]
_ = x[keyPath: \.available[0].b]
_ = a[keyPath: \.[takesInOut(&x.available.a.b)]]
_ = a[keyPath: \.[takesInOut(&x.available[0].b)]]
_ = x[keyPath: \.unavailableGetter] // expected-error {{getter for 'unavailableGetter' is unavailable}}
_ = x[keyPath: \.unavailableGetter.a] // expected-error {{getter for 'unavailableGetter' is unavailable}}
_ = x[keyPath: \.unavailableGetter[0]] // expected-error {{getter for 'unavailableGetter' is unavailable}}
_ = x[keyPath: \.unavailableGetter[0].b] // expected-error {{getter for 'unavailableGetter' is unavailable}}
_ = a[keyPath: \.[takesInOut(&x.unavailableGetter.a.b)]] // expected-error {{getter for 'unavailableGetter' is unavailable}}
_ = a[keyPath: \.[takesInOut(&x.unavailableGetter[0].b)]] // expected-error {{getter for 'unavailableGetter' is unavailable}}
_ = x[keyPath: \.unavailableSetter]
_ = x[keyPath: \.unavailableSetter.a]
_ = x[keyPath: \.unavailableSetter[0]]
_ = x[keyPath: \.unavailableSetter[0].b]
_ = a[keyPath: \.[takesInOut(&x.unavailableSetter.a.b)]] // expected-error {{setter for 'unavailableSetter' is unavailable}}
_ = a[keyPath: \.[takesInOut(&x.unavailableSetter[0].b)]] // expected-error {{setter for 'unavailableSetter' is unavailable}}
_ = x[keyPath: \.unavailableGetterAndSetter] // expected-error {{getter for 'unavailableGetterAndSetter' is unavailable}}
_ = x[keyPath: \.unavailableGetterAndSetter.a] // expected-error {{getter for 'unavailableGetterAndSetter' is unavailable}}
_ = x[keyPath: \.unavailableGetterAndSetter[0]] // expected-error {{getter for 'unavailableGetterAndSetter' is unavailable}}
_ = x[keyPath: \.unavailableGetterAndSetter[0].b] // expected-error {{getter for 'unavailableGetterAndSetter' is unavailable}}
_ = a[keyPath: \.[takesInOut(&x.unavailableGetterAndSetter.a.b)]] // expected-error {{getter for 'unavailableGetterAndSetter' is unavailable}} // expected-error {{setter for 'unavailableGetterAndSetter' is unavailable}}
_ = a[keyPath: \.[takesInOut(&x.unavailableGetterAndSetter[0].b)]] // expected-error {{getter for 'unavailableGetterAndSetter' is unavailable}} expected-error {{setter for 'unavailableGetterAndSetter' is unavailable}}
}
func testDiscardedKeyPathApplicationLoads_Class() {
let a = [0]
var x = BaseStruct<ClassValue>() // expected-warning {{variable 'x' was never mutated; consider changing to 'let' constant}}
_ = x[keyPath: \.available]
_ = x[keyPath: \.available.a]
_ = x[keyPath: \.available[0]]
_ = x[keyPath: \.available[0].b]
_ = a[keyPath: \.[takesInOut(&x.available.a.b)]]
_ = a[keyPath: \.[takesInOut(&x.available[0].b)]]
_ = x[keyPath: \.unavailableGetter] // expected-error {{getter for 'unavailableGetter' is unavailable}}
_ = x[keyPath: \.unavailableGetter.a] // expected-error {{getter for 'unavailableGetter' is unavailable}}
_ = x[keyPath: \.unavailableGetter[0]] // expected-error {{getter for 'unavailableGetter' is unavailable}}
_ = x[keyPath: \.unavailableGetter[0].b] // expected-error {{getter for 'unavailableGetter' is unavailable}}
_ = a[keyPath: \.[takesInOut(&x.unavailableGetter.a.b)]] // expected-error {{getter for 'unavailableGetter' is unavailable}}
_ = a[keyPath: \.[takesInOut(&x.unavailableGetter[0].b)]] // expected-error {{getter for 'unavailableGetter' is unavailable}}
_ = x[keyPath: \.unavailableSetter]
_ = x[keyPath: \.unavailableSetter.a]
_ = x[keyPath: \.unavailableSetter[0]]
_ = x[keyPath: \.unavailableSetter[0].b]
_ = a[keyPath: \.[takesInOut(&x.unavailableSetter.a.b)]]
_ = a[keyPath: \.[takesInOut(&x.unavailableSetter[0].b)]]
_ = x[keyPath: \.unavailableGetterAndSetter] // expected-error {{getter for 'unavailableGetterAndSetter' is unavailable}}
_ = x[keyPath: \.unavailableGetterAndSetter.a] // expected-error {{getter for 'unavailableGetterAndSetter' is unavailable}}
_ = x[keyPath: \.unavailableGetterAndSetter[0]] // expected-error {{getter for 'unavailableGetterAndSetter' is unavailable}}
_ = x[keyPath: \.unavailableGetterAndSetter[0].b] // expected-error {{getter for 'unavailableGetterAndSetter' is unavailable}}
_ = a[keyPath: \.[takesInOut(&x.unavailableGetterAndSetter.a.b)]] // expected-error {{getter for 'unavailableGetterAndSetter' is unavailable}}
_ = a[keyPath: \.[takesInOut(&x.unavailableGetterAndSetter[0].b)]] // expected-error {{getter for 'unavailableGetterAndSetter' is unavailable}}
}
func testKeyPathApplicationAssignments_Struct(_ someValue: StructValue) {
var a = [0]
var x = BaseStruct<StructValue>()
x[keyPath: \.available] = someValue
x[keyPath: \.available.a] = someValue.a
x[keyPath: \.available[0]] = someValue.a
x[keyPath: \.available[0].b] = 1
x[keyPath: \.available] = someValue
a[keyPath: \.[takesInOut(&x.available.a.b)]] = 0
a[keyPath: \.[takesInOut(&x.available[0].b)]] = 0
x[keyPath: \.unavailableGetter] = someValue
x[keyPath: \.unavailableGetter.a] = someValue.a // FIXME: missing diagnostic for getter
x[keyPath: \.unavailableGetter[0]] = someValue.a // FIXME: missing diagnostic for getter
x[keyPath: \.unavailableGetter[0].b] = 1 // FIXME: missing diagnostic for getter
a[keyPath: \.[takesInOut(&x.unavailableGetter.a.b)]] = 0 // expected-error {{getter for 'unavailableGetter' is unavailable}}
a[keyPath: \.[takesInOut(&x.unavailableGetter[0].b)]] = 0 // expected-error {{getter for 'unavailableGetter' is unavailable}}
x[keyPath: \.unavailableSetter] = someValue // expected-error {{cannot assign through subscript: key path is read-only}}
x[keyPath: \.unavailableSetter.a] = someValue.a // expected-error {{cannot assign through subscript: key path is read-only}}
x[keyPath: \.unavailableSetter[0]] = someValue.a // expected-error {{cannot assign through subscript: key path is read-only}}
x[keyPath: \.unavailableSetter[0].b] = 1 // expected-error {{cannot assign through subscript: key path is read-only}}
a[keyPath: \.[takesInOut(&x.unavailableSetter.a.b)]] = 0 // expected-error {{setter for 'unavailableSetter' is unavailable}}
a[keyPath: \.[takesInOut(&x.unavailableSetter[0].b)]] = 0 // expected-error {{setter for 'unavailableSetter' is unavailable}}
x[keyPath: \.unavailableGetterAndSetter] = someValue // expected-error {{cannot assign through subscript: key path is read-only}}
x[keyPath: \.unavailableGetterAndSetter.a] = someValue.a // expected-error {{cannot assign through subscript: key path is read-only}}
x[keyPath: \.unavailableGetterAndSetter[0]] = someValue.a // expected-error {{cannot assign through subscript: key path is read-only}}
x[keyPath: \.unavailableGetterAndSetter[0].b] = 1 // expected-error {{cannot assign through subscript: key path is read-only}}
a[keyPath: \.[takesInOut(&x.unavailableGetterAndSetter.a.b)]] = 0 // expected-error {{getter for 'unavailableGetterAndSetter' is unavailable}} expected-error {{setter for 'unavailableGetterAndSetter' is unavailable}}
a[keyPath: \.[takesInOut(&x.unavailableGetterAndSetter[0].b)]] = 0 // expected-error {{getter for 'unavailableGetterAndSetter' is unavailable}} expected-error {{setter for 'unavailableGetterAndSetter' is unavailable}}
}
func testKeyPathApplicationAssignments_Class(_ someValue: ClassValue) {
var a = [0]
var x = BaseStruct<ClassValue>()
x[keyPath: \.available] = someValue
x[keyPath: \.available.a] = someValue.a
x[keyPath: \.available[0]] = someValue.a
x[keyPath: \.available[0].b] = 1
x[keyPath: \.available] = someValue
a[keyPath: \.[takesInOut(&x.available.a.b)]] = 0
a[keyPath: \.[takesInOut(&x.available[0].b)]] = 0
x[keyPath: \.unavailableGetter] = someValue
x[keyPath: \.unavailableGetter.a] = someValue.a // FIXME: missing diagnostic for getter
x[keyPath: \.unavailableGetter[0]] = someValue.a // FIXME: missing diagnostic for getter
x[keyPath: \.unavailableGetter[0].b] = 1 // FIXME: missing diagnostic for getter
a[keyPath: \.[takesInOut(&x.unavailableGetter.a.b)]] = 0 // expected-error {{getter for 'unavailableGetter' is unavailable}}
a[keyPath: \.[takesInOut(&x.unavailableGetter[0].b)]] = 0 // expected-error {{getter for 'unavailableGetter' is unavailable}}
x[keyPath: \.unavailableSetter] = someValue // expected-error {{cannot assign through subscript: key path is read-only}}
// FIXME: spurious unavailable setter error
x[keyPath: \.unavailableSetter.a] = someValue.a // expected-error {{setter for 'unavailableSetter' is unavailable}}
// FIXME: spurious unavailable setter error
x[keyPath: \.unavailableSetter[0]] = someValue.a // expected-error {{setter for 'unavailableSetter' is unavailable}}
// FIXME: spurious unavailable setter error
x[keyPath: \.unavailableSetter[0].b] = 1 // expected-error {{setter for 'unavailableSetter' is unavailable}}
a[keyPath: \.[takesInOut(&x.unavailableSetter.a.b)]] = 0
a[keyPath: \.[takesInOut(&x.unavailableSetter[0].b)]] = 0
x[keyPath: \.unavailableGetterAndSetter] = someValue // expected-error {{cannot assign through subscript: key path is read-only}}
x[keyPath: \.unavailableGetterAndSetter.a] = someValue.a // expected-error {{setter for 'unavailableGetterAndSetter' is unavailable}}
x[keyPath: \.unavailableGetterAndSetter[0]] = someValue.a // expected-error {{setter for 'unavailableGetterAndSetter' is unavailable}}
// FIXME: spurious unavailable setter error
x[keyPath: \.unavailableGetterAndSetter[0].b] = 1 // expected-error {{setter for 'unavailableGetterAndSetter' is unavailable}}
a[keyPath: \.[takesInOut(&x.unavailableGetterAndSetter.a.b)]] = 0 // expected-error {{getter for 'unavailableGetterAndSetter' is unavailable}}
a[keyPath: \.[takesInOut(&x.unavailableGetterAndSetter[0].b)]] = 0 // expected-error {{getter for 'unavailableGetterAndSetter' is unavailable}}
}
func testMutatingStructMember() {
var x = BaseStruct<StructValue>()
let a = [0]
x.available.setToZero()
x.available[0].setToZero()
_ = a[x.available.setToZero()]
_ = a[x.available.a.setToZero()]
_ = a[x.available[0].setToZero()]
x.unavailableGetter.setToZero() // expected-error {{getter for 'unavailableGetter' is unavailable}}
x.unavailableGetter[0].setToZero() // expected-error {{getter for 'unavailableGetter' is unavailable}}
_ = a[x.unavailableGetter.setToZero()] // expected-error {{getter for 'unavailableGetter' is unavailable}}
_ = a[x.unavailableGetter.a.setToZero()] // expected-error {{getter for 'unavailableGetter' is unavailable}}
_ = a[x.unavailableGetter[0].setToZero()] // expected-error {{getter for 'unavailableGetter' is unavailable}}
x.unavailableSetter.setToZero() // expected-error {{setter for 'unavailableSetter' is unavailable}}
x.unavailableSetter[0].setToZero() // expected-error {{setter for 'unavailableSetter' is unavailable}}
_ = a[x.unavailableSetter.setToZero()] // expected-error {{setter for 'unavailableSetter' is unavailable}}
_ = a[x.unavailableSetter.a.setToZero()] // expected-error {{setter for 'unavailableSetter' is unavailable}}
_ = a[x.unavailableSetter[0].setToZero()] // expected-error {{setter for 'unavailableSetter' is unavailable}}
x.unavailableGetterAndSetter.setToZero() // expected-error {{getter for 'unavailableGetterAndSetter' is unavailable}} expected-error {{setter for 'unavailableGetterAndSetter' is unavailable}}
x.unavailableGetterAndSetter[0].setToZero() // expected-error {{getter for 'unavailableGetterAndSetter' is unavailable}} expected-error {{setter for 'unavailableGetterAndSetter' is unavailable}}
_ = a[x.unavailableGetterAndSetter.setToZero()] // expected-error {{getter for 'unavailableGetterAndSetter' is unavailable}} expected-error {{setter for 'unavailableGetterAndSetter' is unavailable}}
_ = a[x.unavailableGetterAndSetter.a.setToZero()] // expected-error {{getter for 'unavailableGetterAndSetter' is unavailable}} expected-error {{setter for 'unavailableGetterAndSetter' is unavailable}}
_ = a[x.unavailableGetterAndSetter[0].setToZero()] // expected-error {{getter for 'unavailableGetterAndSetter' is unavailable}} expected-error {{setter for 'unavailableGetterAndSetter' is unavailable}}
}
func testIgnoredApplyOfFuncWithInOutParam_Struct() {
var x = BaseStruct<StructValue>()
takesInOut(&x.available)
takesInOut(&x.available.a)
takesInOut(&x.available[0])
takesInOut(&x.available[0].b)
takesInOut(&x.unavailableGetter) // expected-error {{getter for 'unavailableGetter' is unavailable}}
takesInOut(&x.unavailableGetter.a) // expected-error {{getter for 'unavailableGetter' is unavailable}}
takesInOut(&x.unavailableGetter[0]) // expected-error {{getter for 'unavailableGetter' is unavailable}}
takesInOut(&x.unavailableGetter[0].b) // expected-error {{getter for 'unavailableGetter' is unavailable}}
takesInOut(&x.unavailableSetter) // expected-error {{setter for 'unavailableSetter' is unavailable}}
takesInOut(&x.unavailableSetter.a) // expected-error {{setter for 'unavailableSetter' is unavailable}}
takesInOut(&x.unavailableSetter[0]) // expected-error {{setter for 'unavailableSetter' is unavailable}}
takesInOut(&x.unavailableSetter[0].b) // expected-error {{setter for 'unavailableSetter' is unavailable}}
takesInOut(&x.unavailableGetterAndSetter) // expected-error {{getter for 'unavailableGetterAndSetter' is unavailable}} expected-error {{setter for 'unavailableGetterAndSetter' is unavailable}}
takesInOut(&x.unavailableGetterAndSetter.a) // expected-error {{getter for 'unavailableGetterAndSetter' is unavailable}} expected-error {{setter for 'unavailableGetterAndSetter' is unavailable}}
takesInOut(&x.unavailableGetterAndSetter[0]) // expected-error {{getter for 'unavailableGetterAndSetter' is unavailable}} expected-error {{setter for 'unavailableGetterAndSetter' is unavailable}}
takesInOut(&x.unavailableGetterAndSetter[0].b) // expected-error {{getter for 'unavailableGetterAndSetter' is unavailable}} expected-error {{setter for 'unavailableGetterAndSetter' is unavailable}}
}
func testIgnoredApplyOfFuncWithInOutParam_Class() {
var x = BaseStruct<ClassValue>()
takesInOut(&x.available)
takesInOut(&x.available.a)
takesInOut(&x.available[0])
takesInOut(&x.available[0].b)
takesInOut(&x.unavailableGetter) // expected-error {{getter for 'unavailableGetter' is unavailable}}
takesInOut(&x.unavailableGetter.a) // expected-error {{getter for 'unavailableGetter' is unavailable}}
takesInOut(&x.unavailableGetter[0]) // expected-error {{getter for 'unavailableGetter' is unavailable}}
takesInOut(&x.unavailableGetter[0].b) // expected-error {{getter for 'unavailableGetter' is unavailable}}
takesInOut(&x.unavailableSetter) // expected-error {{setter for 'unavailableSetter' is unavailable}}
takesInOut(&x.unavailableSetter.a)
takesInOut(&x.unavailableSetter[0])
takesInOut(&x.unavailableSetter[0].b)
takesInOut(&x.unavailableGetterAndSetter) // expected-error {{getter for 'unavailableGetterAndSetter' is unavailable}} expected-error {{setter for 'unavailableGetterAndSetter' is unavailable}}
takesInOut(&x.unavailableGetterAndSetter.a) // expected-error {{getter for 'unavailableGetterAndSetter' is unavailable}}
takesInOut(&x.unavailableGetterAndSetter[0]) // expected-error {{getter for 'unavailableGetterAndSetter' is unavailable}}
takesInOut(&x.unavailableGetterAndSetter[0].b) // expected-error {{getter for 'unavailableGetterAndSetter' is unavailable}}
}
func testDiscardedApplyOfFuncWithInOutParam_Struct() {
var x = BaseStruct<StructValue>()
_ = takesInOut(&x.available)
_ = takesInOut(&x.available).a
_ = takesInOut(&x.available.a)
_ = takesInOut(&x.available.a).b
_ = takesInOut(&x.available[0])
_ = takesInOut(&x.available[0]).b
_ = takesInOut(&x.available[0].b)
_ = takesInOut(&x.available[0].b).magnitude
_ = takesInOut(&x.unavailableGetter) // expected-error {{getter for 'unavailableGetter' is unavailable}}
_ = takesInOut(&x.unavailableGetter).a // expected-error {{getter for 'unavailableGetter' is unavailable}}
_ = takesInOut(&x.unavailableGetter.a) // expected-error {{getter for 'unavailableGetter' is unavailable}}
_ = takesInOut(&x.unavailableGetter.a).b // expected-error {{getter for 'unavailableGetter' is unavailable}}
_ = takesInOut(&x.unavailableGetter[0]) // expected-error {{getter for 'unavailableGetter' is unavailable}}
_ = takesInOut(&x.unavailableGetter[0]).b // expected-error {{getter for 'unavailableGetter' is unavailable}}
_ = takesInOut(&x.unavailableGetter[0].b) // expected-error {{getter for 'unavailableGetter' is unavailable}}
_ = takesInOut(&x.unavailableGetter[0].b).magnitude // expected-error {{getter for 'unavailableGetter' is unavailable}}
_ = takesInOut(&x.unavailableSetter) // expected-error {{setter for 'unavailableSetter' is unavailable}}
_ = takesInOut(&x.unavailableSetter).a // expected-error {{setter for 'unavailableSetter' is unavailable}}
_ = takesInOut(&x.unavailableSetter.a) // expected-error {{setter for 'unavailableSetter' is unavailable}}
_ = takesInOut(&x.unavailableSetter.a).b // expected-error {{setter for 'unavailableSetter' is unavailable}}
_ = takesInOut(&x.unavailableSetter[0]) // expected-error {{setter for 'unavailableSetter' is unavailable}}
_ = takesInOut(&x.unavailableSetter[0]).b // expected-error {{setter for 'unavailableSetter' is unavailable}}
_ = takesInOut(&x.unavailableSetter[0].b) // expected-error {{setter for 'unavailableSetter' is unavailable}}
_ = takesInOut(&x.unavailableSetter[0].b).magnitude // expected-error {{setter for 'unavailableSetter' is unavailable}}
_ = takesInOut(&x.unavailableGetterAndSetter) // expected-error {{getter for 'unavailableGetterAndSetter' is unavailable}} expected-error {{setter for 'unavailableGetterAndSetter' is unavailable}}
_ = takesInOut(&x.unavailableGetterAndSetter).a // expected-error {{getter for 'unavailableGetterAndSetter' is unavailable}} expected-error {{setter for 'unavailableGetterAndSetter' is unavailable}}
_ = takesInOut(&x.unavailableGetterAndSetter.a) // expected-error {{getter for 'unavailableGetterAndSetter' is unavailable}} expected-error {{setter for 'unavailableGetterAndSetter' is unavailable}}
_ = takesInOut(&x.unavailableGetterAndSetter.a).b // expected-error {{getter for 'unavailableGetterAndSetter' is unavailable}} expected-error {{setter for 'unavailableGetterAndSetter' is unavailable}}
_ = takesInOut(&x.unavailableGetterAndSetter[0]) // expected-error {{getter for 'unavailableGetterAndSetter' is unavailable}} expected-error {{setter for 'unavailableGetterAndSetter' is unavailable}}
_ = takesInOut(&x.unavailableGetterAndSetter[0]).b // expected-error {{getter for 'unavailableGetterAndSetter' is unavailable}} expected-error {{setter for 'unavailableGetterAndSetter' is unavailable}}
_ = takesInOut(&x.unavailableGetterAndSetter[0].b) // expected-error {{getter for 'unavailableGetterAndSetter' is unavailable}} expected-error {{setter for 'unavailableGetterAndSetter' is unavailable}}
_ = takesInOut(&x.unavailableGetterAndSetter[0].b).magnitude // expected-error {{getter for 'unavailableGetterAndSetter' is unavailable}} expected-error {{setter for 'unavailableGetterAndSetter' is unavailable}}
}
func testDiscardedApplyOfFuncWithInOutParam_Class() {
var x = BaseStruct<ClassValue>()
_ = takesInOut(&x.available)
_ = takesInOut(&x.available).a
_ = takesInOut(&x.available.a)
_ = takesInOut(&x.available.a).b
_ = takesInOut(&x.available[0])
_ = takesInOut(&x.available[0]).b
_ = takesInOut(&x.available[0].b)
_ = takesInOut(&x.available[0].b).magnitude
_ = takesInOut(&x.unavailableGetter) // expected-error {{getter for 'unavailableGetter' is unavailable}}
_ = takesInOut(&x.unavailableGetter).a // expected-error {{getter for 'unavailableGetter' is unavailable}}
_ = takesInOut(&x.unavailableGetter.a) // expected-error {{getter for 'unavailableGetter' is unavailable}}
_ = takesInOut(&x.unavailableGetter.a).b // expected-error {{getter for 'unavailableGetter' is unavailable}}
_ = takesInOut(&x.unavailableGetter[0]) // expected-error {{getter for 'unavailableGetter' is unavailable}}
_ = takesInOut(&x.unavailableGetter[0]).b // expected-error {{getter for 'unavailableGetter' is unavailable}}
_ = takesInOut(&x.unavailableGetter[0].b) // expected-error {{getter for 'unavailableGetter' is unavailable}}
_ = takesInOut(&x.unavailableGetter[0].b).magnitude // expected-error {{getter for 'unavailableGetter' is unavailable}}
_ = takesInOut(&x.unavailableSetter) // expected-error {{setter for 'unavailableSetter' is unavailable}}
_ = takesInOut(&x.unavailableSetter).a // expected-error {{setter for 'unavailableSetter' is unavailable}}
_ = takesInOut(&x.unavailableSetter.a)
_ = takesInOut(&x.unavailableSetter.a).b
_ = takesInOut(&x.unavailableSetter[0])
_ = takesInOut(&x.unavailableSetter[0]).b
_ = takesInOut(&x.unavailableSetter[0].b)
_ = takesInOut(&x.unavailableSetter[0].b).magnitude
_ = takesInOut(&x.unavailableGetterAndSetter) // expected-error {{getter for 'unavailableGetterAndSetter' is unavailable}} expected-error {{setter for 'unavailableGetterAndSetter' is unavailable}}
_ = takesInOut(&x.unavailableGetterAndSetter).a // expected-error {{getter for 'unavailableGetterAndSetter' is unavailable}} expected-error {{setter for 'unavailableGetterAndSetter' is unavailable}}
_ = takesInOut(&x.unavailableGetterAndSetter.a) // expected-error {{getter for 'unavailableGetterAndSetter' is unavailable}}
_ = takesInOut(&x.unavailableGetterAndSetter.a).b // expected-error {{getter for 'unavailableGetterAndSetter' is unavailable}}
_ = takesInOut(&x.unavailableGetterAndSetter[0]) // expected-error {{getter for 'unavailableGetterAndSetter' is unavailable}}
_ = takesInOut(&x.unavailableGetterAndSetter[0]).b // expected-error {{getter for 'unavailableGetterAndSetter' is unavailable}}
_ = takesInOut(&x.unavailableGetterAndSetter[0].b) // expected-error {{getter for 'unavailableGetterAndSetter' is unavailable}}
_ = takesInOut(&x.unavailableGetterAndSetter[0].b).magnitude // expected-error {{getter for 'unavailableGetterAndSetter' is unavailable}}
}
func testKeyPathArguments_Struct() {
var x = BaseStruct<StructValue>()
func takesKeyPath<T, U>(_ t: T, _ keyPath: KeyPath<T, U>) -> () { }
takesKeyPath(x, \.available)
takesKeyPath(x, \.unavailableGetter) // expected-error {{getter for 'unavailableGetter' is unavailable}}
takesKeyPath(x, \.unavailableSetter)
takesKeyPath(x, \.unavailableGetterAndSetter) // expected-error {{getter for 'unavailableGetterAndSetter' is unavailable}}
takesKeyPath(x, \.deprecatedGetter) // expected-warning {{getter for 'deprecatedGetter' is deprecated: reading not recommended}}
takesKeyPath(x, \.deprecatedSetter)
func takesAnyKeyPath(_ keyPath: AnyKeyPath) -> () { }
takesAnyKeyPath(\BaseStruct<StructValue>.available)
takesAnyKeyPath(\BaseStruct<StructValue>.unavailableGetter) // expected-error {{getter for 'unavailableGetter' is unavailable}}
takesAnyKeyPath(\BaseStruct<StructValue>.unavailableSetter)
takesAnyKeyPath(\BaseStruct<StructValue>.unavailableGetterAndSetter) // expected-error {{getter for 'unavailableGetterAndSetter' is unavailable}}
takesAnyKeyPath(\BaseStruct<StructValue>.deprecatedGetter) // expected-warning {{getter for 'deprecatedGetter' is deprecated: reading not recommended}}
takesAnyKeyPath(\BaseStruct<StructValue>.deprecatedSetter)
func takesPartialKeyPath<T>(_ t: T, _ keyPath: PartialKeyPath<T>) -> () { }
takesPartialKeyPath(x, \.available)
takesPartialKeyPath(x, \.unavailableGetter) // expected-error {{getter for 'unavailableGetter' is unavailable}}
takesPartialKeyPath(x, \.unavailableSetter)
takesPartialKeyPath(x, \.unavailableGetterAndSetter) // expected-error {{getter for 'unavailableGetterAndSetter' is unavailable}}
takesPartialKeyPath(x, \.deprecatedGetter) // expected-warning {{getter for 'deprecatedGetter' is deprecated: reading not recommended}}
takesPartialKeyPath(x, \.deprecatedSetter)
func takesSendableKeyPath<T, U>(_ t: T, _ keyPath: KeyPath<T, U> & Sendable) -> () { }
takesSendableKeyPath(x, \.available)
takesSendableKeyPath(x, \.unavailableGetter) // expected-error {{getter for 'unavailableGetter' is unavailable}}
takesSendableKeyPath(x, \.unavailableSetter)
takesSendableKeyPath(x, \.unavailableGetterAndSetter) // expected-error {{getter for 'unavailableGetterAndSetter' is unavailable}}
takesSendableKeyPath(x, \.deprecatedGetter) // expected-warning {{getter for 'deprecatedGetter' is deprecated: reading not recommended}}
takesSendableKeyPath(x, \.deprecatedSetter)
func takesWritableKeyPath<T, U>(_ t: inout T, _ keyPath: WritableKeyPath<T, U>) -> () { }
// expected-note@-1 2 {{in call to function 'takesWritableKeyPath'}}
takesWritableKeyPath(&x, \.available)
takesWritableKeyPath(&x, \.unavailableGetter) // expected-error {{getter for 'unavailableGetter' is unavailable}}
// FIXME: Ideally we would diagnose the unavailability of the setter instead
// of simply indicating that a conversion to WritableKeyPath is not possible
// (rdar://157249275)
takesWritableKeyPath(&x, \.unavailableSetter) // expected-error {{cannot convert value of type 'KeyPath<BaseStruct<StructValue>, StructValue>' to expected argument type 'WritableKeyPath<BaseStruct<StructValue>, U>'}}
// expected-error@-1 {{generic parameter 'U' could not be inferred}}
takesWritableKeyPath(&x, \.unavailableGetterAndSetter) // expected-error {{cannot convert value of type 'KeyPath<BaseStruct<StructValue>, StructValue>' to expected argument type 'WritableKeyPath<BaseStruct<StructValue>, U>'}}
// expected-error@-1 {{generic parameter 'U' could not be inferred}}
takesWritableKeyPath(&x, \.deprecatedGetter) // expected-warning {{getter for 'deprecatedGetter' is deprecated: reading not recommended}}
takesWritableKeyPath(&x, \.deprecatedSetter) // expected-warning {{setter for 'deprecatedSetter' is deprecated: writing not recommended}}
func takesUnifiedTypes<T>(_: T, _: T) { }
takesUnifiedTypes(\BaseStruct<StructValue>.available, \BaseStruct<StructValue>.available)
takesUnifiedTypes(\BaseStruct<StructValue>.available, \BaseStruct<StructValue>.unavailableGetter) // expected-error {{getter for 'unavailableGetter' is unavailable}}
takesUnifiedTypes(\BaseStruct<StructValue>.available, \BaseStruct<StructValue>.unavailableSetter)
takesUnifiedTypes(\BaseStruct<StructValue>.available, \BaseStruct<StructValue>.deprecatedSetter) // expected-warning {{setter for 'deprecatedSetter' is deprecated: writing not recommended}}
takesUnifiedTypes(\BaseStruct<StructValue>.unavailableSetter, \BaseStruct<StructValue>.deprecatedSetter)
}
var global = BaseStruct<StructValue>()
struct TestPatternBindingInitExprs {
var available = global.available
var available_a = global.available.a
var available_0 = global.available[0]
var available_0_b = global.available[0].b
var unavailableGetter = global.unavailableGetter // expected-error {{getter for 'unavailableGetter' is unavailable}}
var unavailableGetter_a = global.unavailableGetter.a // expected-error {{getter for 'unavailableGetter' is unavailable}}
var unavailableGetter_0 = global.unavailableGetter[0] // expected-error {{getter for 'unavailableGetter' is unavailable}}
var unavailableGetter_0_b = global.unavailableGetter[0].b // expected-error {{getter for 'unavailableGetter' is unavailable}}
var unavailableSetter = global.unavailableSetter
var unavailableSetter_a = global.unavailableSetter.a
var unavailableSetter_0 = global.unavailableSetter[0]
var unavailableSetter_0_b = global.unavailableSetter[0].b
var unavailableGetterAndSetter = global.unavailableGetterAndSetter // expected-error {{getter for 'unavailableGetterAndSetter' is unavailable}}
var unavailableGetterAndSetter_a = global.unavailableGetterAndSetter.a // expected-error {{getter for 'unavailableGetterAndSetter' is unavailable}}
var unavailableGetterAndSetter_0 = global.unavailableGetterAndSetter[0] // expected-error {{getter for 'unavailableGetterAndSetter' is unavailable}}
var unavailableGetterAndSetter_0_b = global.unavailableGetterAndSetter[0].b // expected-error {{getter for 'unavailableGetterAndSetter' is unavailable}}
}
struct BadAccessorAvailability<T> {
var alwaysUnavailableObservers: T {
@available(*, unavailable) // expected-error {{willSet observer cannot be marked unavailable with '@available'}}
willSet { }
@available(*, unavailable) // expected-error {{didSet observer cannot be marked unavailable with '@available'}}
didSet { }
}
var observersUnavailableBeforeSwift99: T {
@available(swift, introduced: 99) // expected-error {{willSet observer cannot be marked unavailable with '@available'}}
willSet { }
@available(swift, introduced: 99) // expected-error {{didSet observer cannot be marked unavailable with '@available'}}
didSet { }
}
}