| // RUN: %target-typecheck-verify-swift -swift-version 5 -enable-conformance-availability-errors |
| |
| // REQUIRES: OS=macosx |
| |
| public protocol Horse {} |
| func takesHorse<T : Horse>(_: T) {} |
| |
| extension Horse { |
| func giddyUp() {} |
| } |
| |
| struct UsesHorse<T : Horse> {} |
| |
| // Unconditional unavailability |
| public struct HasUnavailableConformance1 {} |
| |
| @available(*, unavailable) |
| extension HasUnavailableConformance1 : Horse {} |
| // expected-note@-1 7{{conformance of 'HasUnavailableConformance1' to 'Horse' has been explicitly marked unavailable here}} |
| |
| func passUnavailableConformance1(x: HasUnavailableConformance1) { |
| takesHorse(x) // expected-error {{conformance of 'HasUnavailableConformance1' to 'Horse' is unavailable}} |
| x.giddyUp() // expected-error {{conformance of 'HasUnavailableConformance1' to 'Horse' is unavailable}} |
| _ = UsesHorse<HasUnavailableConformance1>.self // expected-error {{conformance of 'HasUnavailableConformance1' to 'Horse' is unavailable}} |
| } |
| |
| @available(*, unavailable) |
| func passUnavailableConformance1a(x: HasUnavailableConformance1) { |
| takesHorse(x) // expected-error {{conformance of 'HasUnavailableConformance1' to 'Horse' is unavailable}} |
| x.giddyUp() // expected-error {{conformance of 'HasUnavailableConformance1' to 'Horse' is unavailable}} |
| _ = UsesHorse<HasUnavailableConformance1>.self // expected-error {{conformance of 'HasUnavailableConformance1' to 'Horse' is unavailable}} |
| } |
| |
| // Platform unavailability |
| public struct HasUnavailableConformance2 {} |
| |
| @available(macOS, unavailable) |
| extension HasUnavailableConformance2 : Horse {} |
| // expected-note@-1 3{{conformance of 'HasUnavailableConformance2' to 'Horse' has been explicitly marked unavailable here}} |
| |
| func passUnavailableConformance2(x: HasUnavailableConformance2) { |
| takesHorse(x) // expected-error {{conformance of 'HasUnavailableConformance2' to 'Horse' is unavailable in macOS}} |
| x.giddyUp() // expected-error {{conformance of 'HasUnavailableConformance2' to 'Horse' is unavailable in macOS}} |
| _ = UsesHorse<HasUnavailableConformance2>.self // expected-error {{conformance of 'HasUnavailableConformance2' to 'Horse' is unavailable in macOS}} |
| } |
| |
| @available(macOS, unavailable) |
| func passUnavailableConformance2a(x: HasUnavailableConformance2) { |
| // This is allowed |
| takesHorse(x) |
| x.giddyUp() |
| } |
| |
| // Swift version unavailability |
| public struct HasUnavailableConformance3 {} |
| |
| @available(swift 12) |
| extension HasUnavailableConformance3 : Horse {} |
| // expected-note@-1 6{{conformance of 'HasUnavailableConformance3' to 'Horse' was introduced in Swift 12}} |
| |
| func passUnavailableConformance3(x: HasUnavailableConformance3) { |
| takesHorse(x) // expected-error {{conformance of 'HasUnavailableConformance3' to 'Horse' is unavailable}} |
| x.giddyUp() // expected-error {{conformance of 'HasUnavailableConformance3' to 'Horse' is unavailable}} |
| _ = UsesHorse<HasUnavailableConformance3>.self // expected-error {{conformance of 'HasUnavailableConformance3' to 'Horse' is unavailable}} |
| } |
| |
| @available(swift 12) |
| func passUnavailableConformance3a(x: HasUnavailableConformance3) { |
| takesHorse(x) // expected-error {{conformance of 'HasUnavailableConformance3' to 'Horse' is unavailable}} |
| x.giddyUp() // expected-error {{conformance of 'HasUnavailableConformance3' to 'Horse' is unavailable}} |
| _ = UsesHorse<HasUnavailableConformance3>.self // expected-error {{conformance of 'HasUnavailableConformance3' to 'Horse' is unavailable}} |
| } |
| |
| // Platform obsoleted |
| public struct HasUnavailableConformance4 {} |
| |
| @available(macOS, obsoleted: 10.1) |
| extension HasUnavailableConformance4 : Horse {} |
| // expected-note@-1 6{{conformance of 'HasUnavailableConformance4' to 'Horse' was obsoleted in macOS 10.1}} |
| |
| func passUnavailableConformance4(x: HasUnavailableConformance4) { |
| takesHorse(x) // expected-error {{conformance of 'HasUnavailableConformance4' to 'Horse' is unavailable in macOS}} |
| x.giddyUp() // expected-error {{conformance of 'HasUnavailableConformance4' to 'Horse' is unavailable in macOS}} |
| _ = UsesHorse<HasUnavailableConformance4>.self // expected-error {{conformance of 'HasUnavailableConformance4' to 'Horse' is unavailable in macOS}} |
| } |
| |
| @available(macOS, obsoleted: 10.1) |
| func passUnavailableConformance4a(x: HasUnavailableConformance4) { |
| takesHorse(x) // expected-error {{conformance of 'HasUnavailableConformance4' to 'Horse' is unavailable in macOS}} |
| x.giddyUp() // expected-error {{conformance of 'HasUnavailableConformance4' to 'Horse' is unavailable in macOS}} |
| _ = UsesHorse<HasUnavailableConformance4>.self // expected-error {{conformance of 'HasUnavailableConformance4' to 'Horse' is unavailable in macOS}} |
| } |
| |
| // Swift obsoleted |
| public struct HasUnavailableConformance5 {} |
| |
| @available(swift, obsoleted: 4) |
| extension HasUnavailableConformance5 : Horse {} |
| // expected-note@-1 6{{conformance of 'HasUnavailableConformance5' to 'Horse' was obsoleted in Swift 4}} |
| |
| func passUnavailableConformance5(x: HasUnavailableConformance5) { |
| takesHorse(x) // expected-error {{conformance of 'HasUnavailableConformance5' to 'Horse' is unavailable}} |
| x.giddyUp() // expected-error {{conformance of 'HasUnavailableConformance5' to 'Horse' is unavailable}} |
| _ = UsesHorse<HasUnavailableConformance5>.self // expected-error {{conformance of 'HasUnavailableConformance5' to 'Horse' is unavailable}} |
| } |
| |
| @available(swift, obsoleted: 4) |
| func passUnavailableConformance5a(x: HasUnavailableConformance5) { |
| takesHorse(x) // expected-error {{conformance of 'HasUnavailableConformance5' to 'Horse' is unavailable}} |
| x.giddyUp() // expected-error {{conformance of 'HasUnavailableConformance5' to 'Horse' is unavailable}} |
| _ = UsesHorse<HasUnavailableConformance5>.self // expected-error {{conformance of 'HasUnavailableConformance5' to 'Horse' is unavailable}} |
| } |
| |
| // Unavailable with message |
| public struct HasUnavailableConformance6 {} |
| |
| @available(*, unavailable, message: "This conformance is bad") |
| extension HasUnavailableConformance6 : Horse {} |
| // expected-note@-1 3{{conformance of 'HasUnavailableConformance6' to 'Horse' has been explicitly marked unavailable here}} |
| |
| func passUnavailableConformance6(x: HasUnavailableConformance6) { |
| takesHorse(x) // expected-error {{conformance of 'HasUnavailableConformance6' to 'Horse' is unavailable: This conformance is bad}} |
| x.giddyUp() // expected-error {{conformance of 'HasUnavailableConformance6' to 'Horse' is unavailable: This conformance is bad}} |
| _ = UsesHorse<HasUnavailableConformance6>.self // expected-error {{conformance of 'HasUnavailableConformance6' to 'Horse' is unavailable: This conformance is bad}} |
| } |
| |
| // Deprecated |
| public struct HasDeprecatedConformance1 {} |
| |
| @available(*, deprecated) |
| extension HasDeprecatedConformance1 : Horse {} |
| |
| func passDeprecatedConformance1(x: HasDeprecatedConformance1) { |
| takesHorse(x) // expected-warning {{conformance of 'HasDeprecatedConformance1' to 'Horse' is deprecated}} |
| x.giddyUp() // expected-warning {{conformance of 'HasDeprecatedConformance1' to 'Horse' is deprecated}} |
| _ = UsesHorse<HasDeprecatedConformance1>.self // expected-warning {{conformance of 'HasDeprecatedConformance1' to 'Horse' is deprecated}} |
| } |
| |
| @available(*, deprecated) |
| func passDeprecatedConformance1a(x: HasDeprecatedConformance1) { |
| takesHorse(x) |
| x.giddyUp() |
| _ = UsesHorse<HasDeprecatedConformance1>.self |
| } |
| |
| // Deprecated with message |
| public struct HasDeprecatedConformance2 {} |
| |
| @available(*, deprecated, message: "This conformance is deprecated") |
| extension HasDeprecatedConformance2 : Horse {} |
| |
| func passDeprecatedConformance2(x: HasDeprecatedConformance2) { |
| takesHorse(x) // expected-warning {{conformance of 'HasDeprecatedConformance2' to 'Horse' is deprecated: This conformance is deprecated}} |
| x.giddyUp() // expected-warning {{conformance of 'HasDeprecatedConformance2' to 'Horse' is deprecated: This conformance is deprecated}} |
| _ = UsesHorse<HasDeprecatedConformance2>.self // expected-warning {{conformance of 'HasDeprecatedConformance2' to 'Horse' is deprecated: This conformance is deprecated}} |
| } |
| |
| @available(*, deprecated) |
| func passDeprecatedConformance2a(x: HasDeprecatedConformance2) { |
| takesHorse(x) |
| x.giddyUp() |
| _ = UsesHorse<HasDeprecatedConformance2>.self |
| } |
| |
| // Deprecated with version |
| public struct HasDeprecatedConformance3 {} |
| |
| @available(macOS, introduced: 10.7, deprecated: 10.8) |
| extension HasDeprecatedConformance3 : Horse {} |
| |
| func passDeprecatedConformance3(x: HasDeprecatedConformance3) { |
| takesHorse(x) // expected-warning {{conformance of 'HasDeprecatedConformance3' to 'Horse' was deprecated in macOS 10.8}} |
| x.giddyUp() // expected-warning {{conformance of 'HasDeprecatedConformance3' to 'Horse' was deprecated in macOS 10.8}} |
| _ = UsesHorse<HasDeprecatedConformance3>.self // expected-warning {{conformance of 'HasDeprecatedConformance3' to 'Horse' was deprecated in macOS 10.8}} |
| } |
| |
| func passDeprecatedConformance3a(x: HasDeprecatedConformance3) { |
| if #available(macOS 10.8, *) { |
| } else { |
| // This branch is dead with our minimum deployment target, so don't emit |
| // deprecation diagnostics in it. |
| takesHorse(x) |
| x.giddyUp() |
| _ = UsesHorse<HasDeprecatedConformance3>.self |
| } |
| } |
| |
| // Availability with version |
| public struct HasAvailableConformance1 {} |
| |
| @available(macOS 100, *) |
| extension HasAvailableConformance1 : Horse {} |
| |
| // These availability violations are errors because this test passes the |
| // -enable-conformance-availability-errors flag. See the other test case |
| // in test/Sema/conformance_availability_warn.swift for the same example |
| // but without this flag. |
| |
| func passAvailableConformance1(x: HasAvailableConformance1) { // expected-note 3{{add @available attribute to enclosing global function}} |
| takesHorse(x) // expected-error {{conformance of 'HasAvailableConformance1' to 'Horse' is only available in macOS 100 or newer}} |
| // expected-note@-1 {{add 'if #available' version check}} |
| |
| x.giddyUp() // expected-error {{conformance of 'HasAvailableConformance1' to 'Horse' is only available in macOS 100 or newer}} |
| // expected-note@-1 {{add 'if #available' version check}} |
| |
| _ = UsesHorse<HasAvailableConformance1>.self // expected-error {{conformance of 'HasAvailableConformance1' to 'Horse' is only available in macOS 100 or newer}} |
| // expected-note@-1 {{add 'if #available' version check}} |
| } |
| |
| @available(macOS 100, *) |
| func passAvailableConformance1a(x: HasAvailableConformance1) { |
| takesHorse(x) |
| x.giddyUp() |
| _ = UsesHorse<HasAvailableConformance1>.self |
| } |
| |
| // Associated conformance with unavailability |
| protocol Rider { |
| associatedtype H : Horse |
| } |
| |
| struct AssocConformanceUnavailable : Rider { |
| // expected-error@-1 {{conformance of 'HasUnavailableConformance1' to 'Horse' is unavailable}} |
| // expected-note@-2 {{in associated type 'Self.H' (inferred as 'HasUnavailableConformance1')}} |
| typealias H = HasUnavailableConformance1 |
| } |
| |
| // Associated conformance with deprecation |
| struct AssocConformanceDeprecated : Rider { |
| // expected-warning@-1 {{conformance of 'HasDeprecatedConformance1' to 'Horse' is deprecated}} |
| // expected-note@-2 {{in associated type 'Self.H' (inferred as 'HasDeprecatedConformance1')}} |
| typealias H = HasDeprecatedConformance1 |
| } |
| |
| // Associated conformance with availability |
| struct AssocConformanceAvailable1 : Rider { |
| // expected-error@-1 {{conformance of 'HasAvailableConformance1' to 'Horse' is only available in macOS 100 or newer}} |
| // expected-note@-2 {{in associated type 'Self.H' (inferred as 'HasAvailableConformance1')}} |
| // expected-note@-3 {{add @available attribute to enclosing struct}} |
| typealias H = HasAvailableConformance1 |
| } |
| |
| @available(macOS 100, *) |
| struct AssocConformanceAvailable2 : Rider { |
| typealias H = HasAvailableConformance1 |
| } |
| |
| struct AssocConformanceAvailable3 {} |
| |
| extension AssocConformanceAvailable3 : Rider { |
| // expected-error@-1 {{conformance of 'HasAvailableConformance1' to 'Horse' is only available in macOS 100 or newer}} |
| // expected-note@-2 {{in associated type 'Self.H' (inferred as 'HasAvailableConformance1')}} |
| // expected-note@-3 {{add @available attribute to enclosing extension}} |
| typealias H = HasAvailableConformance1 |
| } |
| |
| struct AssocConformanceAvailable4 {} |
| |
| @available(macOS 100, *) |
| extension AssocConformanceAvailable4 : Rider { |
| typealias H = HasAvailableConformance1 |
| } |
| |
| // Solution ranking should down-rank solutions involving unavailable conformances |
| protocol First {} |
| extension First { |
| func doStuff<T>(_: T) -> Bool {} |
| } |
| |
| protocol Second {} |
| extension Second { |
| func doStuff(_: Int) -> Int {} |
| } |
| |
| struct ConformingType1 {} |
| |
| extension ConformingType1 : First {} |
| |
| @available(macOS 100, *) |
| extension ConformingType1 : Second {} |
| |
| func usesConformingType1(_ c: ConformingType1) { |
| // We should pick First.doStuff() here, since Second.doStuff() is unavailable |
| let result = c.doStuff(123) |
| let _: Bool = result |
| } |
| |
| @available(macOS 100, *) |
| func usesConformingType1a(_ c: ConformingType1) { |
| // We should pick Second.doStuff() here, since it is more specialized than |
| // First.doStuff() |
| let result = c.doStuff(123) |
| let _: Int = result |
| } |
| |
| // Same as above but unconditionally unavailable |
| struct ConformingType2 {} |
| |
| extension ConformingType2 : First {} |
| |
| @available(*, unavailable) |
| extension ConformingType2 : Second {} |
| |
| func usesConformingType2(_ c: ConformingType2) { |
| // We should pick First.doStuff() here, since Second.doStuff() is unavailable |
| let result = c.doStuff(123) |
| let _: Bool = result |
| } |
| |
| // Make sure this also works for synthesized conformances |
| struct UnavailableHashable { |
| let x: Int |
| let y: Int |
| } |
| |
| @available(macOS 100, *) |
| extension UnavailableHashable : Hashable {} |
| |
| func usesUnavailableHashable(_ c: UnavailableHashable) { |
| // expected-note@-1 2 {{add @available attribute to enclosing global function}} |
| _ = Set([c]) |
| // expected-error@-1 2 {{conformance of 'UnavailableHashable' to 'Hashable' is only available in macOS 100 or newer}} |
| // expected-note@-2 2 {{add 'if #available' version check}} |
| } |