Files
swift-mirror/test/decl/nested/protocol.swift

359 lines
9.8 KiB
Swift

// RUN: %target-typecheck-verify-swift -parse-as-library
// Protocols can be nested inside non-generic types.
protocol Delegate {}
enum Table {
protocol Delegate {}
}
enum Button {
protocol Delegate {}
}
struct PlainDelegateConformer: Delegate {}
struct TableDelegateConformer: Table.Delegate {}
struct ButtonDelegateConformer: Button.Delegate {}
func testDifferent() {
let plain = PlainDelegateConformer()
if plain is Delegate { print("ok (1)") } // expected-warning {{'is' test is always true}}
if plain is Table.Delegate { print("bad (2)") }
if plain is Button.Delegate { print("bad (3)") }
let tableDel = TableDelegateConformer()
if tableDel is Delegate { print("bad (4)") }
if tableDel is Table.Delegate { print("ok (5)") } // expected-warning {{'is' test is always true}}
if tableDel is Button.Delegate { print("bad (6)") }
let buttonDel = ButtonDelegateConformer()
if buttonDel is Delegate { print("bad (7)") }
if buttonDel is Table.Delegate { print("bad (8)") }
if buttonDel is Button.Delegate { print("ok (9)") } // expected-warning {{'is' test is always true}}
}
enum OuterEnum {
protocol C {}
case C(C)
// expected-error@-1{{invalid redeclaration of 'C'}}
// expected-note@-3{{'C' previously declared here}}
}
class OuterClass {
protocol InnerProtocol : OuterClass { }
}
// Name lookup circularity tests.
protocol SomeBaseProtocol {}
struct ConformanceOnDecl: ConformanceOnDecl.P {
protocol P: SomeBaseProtocol {}
}
struct ConformanceOnDecl_2: ConformanceOnDecl_2.P {
protocol P where Self: SomeBaseProtocol {}
}
struct ConformanceOnDecl_3: Self.P {
protocol P: SomeBaseProtocol {}
}
struct ConformanceOnDecl_4: ConformanceOnDecl_4.Q {
protocol P: SomeBaseProtocol {}
protocol Q: P {}
}
struct ConformanceInExtension {
protocol P: SomeBaseProtocol {}
}
extension ConformanceInExtension: ConformanceInExtension.P {}
struct ConformanceInExtension_2 {
protocol P where Self: SomeBaseProtocol {}
}
extension ConformanceInExtension_2: ConformanceInExtension_2.P {}
struct ConformanceInExtension_3 {
protocol P: SomeBaseProtocol {}
}
extension ConformanceInExtension_3: Self.P {}
struct ConformanceInExtension_4 {
protocol P: SomeBaseProtocol {}
protocol Q: P {}
}
extension ConformanceInExtension_4: ConformanceInExtension_4.Q {}
// Protocols can be nested in actors.
@available(macOS 10.15, iOS 13, tvOS 13, watchOS 6, *)
actor SomeActor {
protocol Proto {}
}
// Deeply nested.
enum Level0 {
struct Level1 {
class Level2 {
enum Level3 {
struct Level4 {
class Level5 {
protocol DeeplyNested {
func someRequirement()
}
func lookupTest(_ input: some DeeplyNested) {}
}
func lookupTest(_ input: some Level5.DeeplyNested) {}
}
func lookupTest(_ input: some Level4.Level5.DeeplyNested) {}
}
}
}
}
func useDeeplyNested(_ input: some Level0.Level1.Level2.Level3.Level4.Level5.DeeplyNested) {
input.someRequirement()
}
// Add a nested protocol in an extension.
extension Level0.Level1.Level2 {
protocol ModeratelyNested {
associatedtype ReturnValue
func anotherRequirement() -> ReturnValue
}
func lookupTest(_: some ModeratelyNested) { }
}
func useModeratelyNested<Input>(
_ input: Input
) -> Input.ReturnValue where Input: Level0.Level1.Level2.ModeratelyNested {
input.anotherRequirement()
}
struct ModeratelyNestedConformer: Level0.Level1.Level2.ModeratelyNested {
func anotherRequirement() -> Int {
99
}
}
let _umn: Int = useModeratelyNested(ModeratelyNestedConformer())
// Extend a nested protocol.
extension Level0.Level1.Level2.ModeratelyNested {
func extensionMethod() -> ReturnValue {
anotherRequirement()
}
}
extension Level0.Level1.Level2.ModeratelyNested where ReturnValue == Int {
func extensionMethod() -> Int {
anotherRequirement() + 1
}
}
// Protocols may be nested inside non-generic functions.
func someFunction_0() {
protocol Yes {}
struct Foo: Yes {}
struct Bar: Yes {}
}
func someFunction_1() {
struct HowAboutThis {
protocol AlsoYes {
associatedtype SomeType
func doSomething() -> SomeType
}
}
struct Conforms0: HowAboutThis.AlsoYes {
typealias SomeType = Int
func doSomething() -> SomeType { -99 }
}
struct Conforms1: HowAboutThis.AlsoYes {
typealias SomeType = String
func doSomething() -> SomeType { "works" }
}
func usesNested<T: HowAboutThis.AlsoYes>(_ input: T) -> T.SomeType {
input.doSomething()
}
let _: Int = usesNested(Conforms0())
let _: String = usesNested(Conforms1())
}
// Unqualified lookup searches parent scopes.
struct Lookup_Parent {
protocol A {}
class SomeClass {}
}
extension Lookup_Parent {
protocol B: A {}
protocol C: SomeClass, B {
func doSomething(_: some A) -> SomeClass
}
}
// Protocols cannot be nested in generic types or other protocols.
struct OuterGeneric<D> {
protocol InnerProtocol { // expected-error{{protocol 'InnerProtocol' cannot be nested in a generic context}}
associatedtype Rooster
func flip(_ r: Rooster)
func flop(_ t: D) // expected-error {{cannot find type 'D' in scope}}
}
}
class OuterGenericClass<T> {
protocol InnerProtocol { // expected-error{{protocol 'InnerProtocol' cannot be nested in a generic context}}
associatedtype Rooster
func flip(_ r: Rooster)
func flop(_ t: T) // expected-error {{cannot find type 'T' in scope}}
}
}
protocol OuterProtocol {
associatedtype Hen
protocol InnerProtocol { // expected-error{{protocol 'InnerProtocol' cannot be nested in protocol 'OuterProtocol'}}
associatedtype Rooster
func flip(_ r: Rooster)
func flop(_ h: Hen) // expected-error {{cannot find type 'Hen' in scope}}
}
}
extension OuterProtocol {
protocol DefinedInExtension {} // expected-error{{protocol 'DefinedInExtension' cannot be nested in protocol 'OuterProtocol'}}
}
struct ConformsToOuterProtocol : OuterProtocol {
typealias Hen = Int
func f() { let _ = InnerProtocol.self } // expected-warning {{use of protocol 'InnerProtocol' as a type must be written 'any InnerProtocol'}}
}
extension OuterProtocol {
func f() {
protocol Invalid_0 {} // expected-error{{type 'Invalid_0' cannot be nested in generic function 'f()'}}
struct SomeType { // expected-error{{type 'SomeType' cannot be nested in generic function 'f()'}}
protocol Invalid_1 {} // expected-error{{protocol 'Invalid_1' cannot be nested in a generic context}}
}
}
func g<T>(_: T) {
protocol Invalid_2 {} // expected-error{{type 'Invalid_2' cannot be nested in generic function 'g'}}
}
}
// 'InnerProtocol' does not inherit the generic parameters of
// 'OtherGenericClass', so the occurrence of 'OtherGenericClass'
// in 'InnerProtocol' is not "in context" with implicitly
// inferred generic arguments <T, U>.
class OtherGenericClass<T, U> { // expected-note {{generic class 'OtherGenericClass' declared here}}
protocol InnerProtocol : OtherGenericClass { }
// expected-error@-1 {{protocol 'InnerProtocol' cannot be nested in a generic context}}
// expected-error@-2 {{reference to generic type 'OtherGenericClass' requires arguments in <...>}}
}
protocol InferredGenericTest {
associatedtype A
}
extension OtherGenericClass {
protocol P: InferredGenericTest where Self.A == T {}
// expected-error@-1 {{protocol 'P' cannot be nested in a generic context}}
// expected-error@-2 {{cannot find type 'T' in scope}}
}
// A nested protocol does not satisfy an associated type requirement.
protocol HasAssoc {
associatedtype A // expected-note {{protocol requires nested type 'A'}}
}
struct ConformsToHasAssoc: HasAssoc { // expected-error {{type 'ConformsToHasAssoc' does not conform to protocol 'HasAssoc'}} expected-note {{add stubs for conformance}}
protocol A {}
}
// @usableFromInline.
struct OuterForUFI {
@usableFromInline
protocol Inner {
func req()
}
}
extension OuterForUFI.Inner {
public func extMethod() {} // The 'public' puts this in a special path.
}
func testLookup(_ x: OuterForUFI.Inner) {
x.req()
x.extMethod()
}
func testLookup<T: OuterForUFI.Inner>(_ x: T) {
x.req()
x.extMethod()
}
// Protocols cannot be nested inside of generic functions.
func invalidProtocolInGeneric<T>(_: T) {
protocol Test {} // expected-error{{type 'Test' cannot be nested in generic function 'invalidProtocolInGeneric'}}
}
struct NestedInGenericMethod<T> {
func someMethod() {
protocol AnotherTest {} // expected-error{{type 'AnotherTest' cannot be nested in generic function 'someMethod()'}}
}
}
// Types cannot be nested inside of protocols.
protocol Racoon {
associatedtype Stripes
class Claw<T> { // expected-error{{type 'Claw' cannot be nested in protocol 'Racoon'}}
func mangle(_ s: Stripes) {}
// expected-error@-1 {{cannot find type 'Stripes' in scope}}
}
struct Fang<T> { // expected-error{{type 'Fang' cannot be nested in protocol 'Racoon'}}
func gnaw(_ s: Stripes) {}
// expected-error@-1 {{cannot find type 'Stripes' in scope}}
}
enum Fur { // expected-error{{type 'Fur' cannot be nested in protocol 'Racoon'}}
case Stripes
}
}
enum SillyRawEnum : SillyProtocol.InnerClass {} // expected-error {{an enum with no cases cannot declare a raw type}}
// expected-error@-1 {{reference to generic type 'SillyProtocol.InnerClass' requires arguments in <...>}}
protocol SillyProtocol {
class InnerClass<T> {} // expected-error {{type 'InnerClass' cannot be nested in protocol 'SillyProtocol'}}
// expected-note@-1 {{generic class 'InnerClass' declared here}}
}
protocol SelfDotTest {
func f(_: Self.Class)
class Class {}
// expected-error@-1{{type 'Class' cannot be nested in protocol 'SelfDotTest'}}
}
struct Outer {
typealias E = NestedValidation.T
protocol NestedValidation {
typealias T = A.B
class A { // expected-error {{type 'A' cannot be nested in protocol 'NestedValidation'}}
typealias B = Int
}
}
}