| // RUN: %target-typecheck-verify-swift -parse-stdlib |
| |
| import Swift |
| |
| func someValidAddress<T>() -> UnsafeMutablePointer<T> { fatalError() } |
| func someValidAddress<T>() -> UnsafePointer<T> { fatalError() } |
| |
| struct ValidImmutable { |
| var base: UnsafePointer<Int> |
| |
| subscript(index: Int) -> Int { |
| unsafeAddress { |
| return base |
| } |
| } |
| } |
| |
| struct ValidBoth { |
| var base: UnsafeMutablePointer<Int> |
| |
| subscript(index: Int) -> Int { |
| unsafeAddress { |
| return UnsafePointer(base) |
| } |
| unsafeMutableAddress { |
| return base |
| } |
| } |
| } |
| |
| struct OnlyMutable { |
| var base: UnsafeMutablePointer<Int> |
| |
| subscript(index: Int) -> Int { |
| unsafeMutableAddress { // expected-error {{subscript with a mutable addressor must also have a getter, addressor, or 'read' accessor}} |
| return base |
| } |
| } |
| } |
| |
| struct Repeated { |
| var base: UnsafeMutablePointer<Int> |
| |
| subscript(index: Int) -> Int { |
| unsafeAddress { // expected-note {{previous definition}} |
| return UnsafePointer(base) |
| } |
| unsafeAddress { // expected-error {{subscript already has an addressor}} |
| return base // expected-error {{cannot convert return expression of type 'UnsafeMutablePointer<Int>' to return type 'UnsafePointer<Int>'}} |
| } |
| } |
| } |
| |
| struct RepeatedMutable { |
| var base: UnsafeMutablePointer<Int> |
| |
| subscript(index: Int) -> Int { |
| unsafeAddress { |
| return UnsafePointer(base) |
| } |
| unsafeMutableAddress { // expected-note {{previous definition}} |
| return base |
| } |
| unsafeMutableAddress { // expected-error {{subscript already has a mutable addressor}} |
| return base |
| } |
| } |
| } |
| |
| struct AddressorAndGet { |
| var base: UnsafePointer<Int> |
| |
| subscript(index: Int) -> Int { |
| unsafeAddress { // expected-error {{subscript cannot provide both an addressor and a getter}} |
| return base |
| } |
| get { // expected-note {{getter defined here}} |
| return base.get() // expected-error {{value of type 'UnsafePointer<Int>' has no member 'get'}} |
| } |
| } |
| } |
| |
| struct AddressorAndSet { |
| var base: UnsafePointer<Int> |
| |
| subscript(index: Int) -> Int { |
| unsafeAddress { |
| return base |
| } |
| set { |
| } |
| } |
| } |
| |
| struct MutableAddressorAndGet { |
| var base: UnsafeMutablePointer<Int> |
| |
| subscript(index: Int) -> Int { |
| unsafeMutableAddress { |
| return base |
| } |
| get { |
| return base.pointee |
| } |
| } |
| } |
| |
| protocol HasImmutableSubscript { |
| subscript(index: Int) -> Int { get } |
| } |
| protocol HasMutableSubscript { |
| subscript(index: Int) -> Int { get set } // expected-note {{protocol requires}} |
| } |
| |
| struct DisobedientImmutableAddressor: HasMutableSubscript { // expected-error {{does not conform}} |
| subscript(index: Int) -> Int { // expected-note {{candidate is not settable}} |
| unsafeAddress { return someValidAddress() } |
| } |
| } |
| |
| struct ObedientImmutableAddressor: HasImmutableSubscript { |
| subscript(index: Int) -> Int { |
| unsafeAddress { return someValidAddress() } |
| } |
| } |
| |
| struct ObedientMutableAddressor: HasMutableSubscript { |
| subscript(index: Int) -> Int { |
| unsafeAddress { return someValidAddress() } |
| unsafeMutableAddress { return someValidAddress() } |
| } |
| } |
| |
| protocol HasMutatingImmutableSubscript { |
| subscript(index: Int) -> Int { mutating get } |
| } |
| protocol HasMutatingMutableSubscript { |
| subscript(index: Int) -> Int { mutating get set } // expected-note {{protocol requires}} |
| } |
| |
| // We allow mutating accessor requirements to be implemented by non-mutating accessors. |
| |
| struct DisobedientImmutableAddressor2: HasMutatingMutableSubscript { // expected-error {{does not conform}} |
| subscript(index: Int) -> Int { // expected-note {{candidate is not settable}} |
| unsafeAddress { return someValidAddress() } |
| } |
| } |
| |
| struct ObedientImmutableAddressor2: HasMutatingImmutableSubscript { |
| subscript(index: Int) -> Int { |
| unsafeAddress { return someValidAddress() } |
| } |
| } |
| |
| struct ObedientMutableAddressor2: HasMutatingMutableSubscript { |
| subscript(index: Int) -> Int { |
| unsafeAddress { return someValidAddress() } |
| unsafeMutableAddress { return someValidAddress() } |
| } |
| } |
| |
| // Non-mutating accessor requirements cannot be implemented by mutating accessors. |
| |
| protocol HasNonMutatingMutableSubscript { |
| subscript(index: Int) -> Int { get nonmutating set } // expected-note {{protocol requires}} |
| } |
| |
| struct DisobedientNonMutatingMutableAddressor: HasNonMutatingMutableSubscript { // expected-error {{does not conform}} |
| subscript(index: Int) -> Int { |
| unsafeAddress { return someValidAddress() } |
| unsafeMutableAddress { return someValidAddress() } // expected-note {{candidate is marked 'mutating' but protocol does not allow it}} |
| } |
| } |
| |
| struct ObedientNonMutatingMutableAddressor: HasNonMutatingMutableSubscript { |
| subscript(index: Int) -> Int { |
| unsafeAddress { return someValidAddress() } |
| nonmutating unsafeMutableAddress { return someValidAddress() } |
| } |
| } |
| |
| struct RedundantAddressors { |
| var owner : Builtin.NativeObject |
| subscript(index: Int) -> Int { |
| unsafeAddress { return someValidAddress() } // expected-note {{previous definition of addressor here}} |
| unsafeAddress { return someValidAddress() } // expected-error {{subscript already has an addressor}} |
| } |
| } |
| |
| struct RedundantMutableAddressors { |
| var owner : Builtin.NativeObject |
| subscript(index: Int) -> Int { |
| unsafeAddress { return someValidAddress() } |
| unsafeMutableAddress { return someValidAddress() } // expected-note {{previous definition of mutable addressor here}} |
| unsafeMutableAddress { return someValidAddress() } // expected-error {{subscript already has a mutable addressor}} |
| } |
| } |