Files
swift-mirror/test/decl/protocol/protocol_enum_witness.swift
Suyash Srijan f724d1ff85 [SE-0280] Enum cases as protocol witnesses (#28916)
* [Typechecker] Allow enum cases without payload to witness a static get-only property with Self type protocol requirement

* [SIL] Add support for payload cases as well

* [SILGen] Clean up comment

* [Typechecker] Re-enable some previously disabled witness matching code

Also properly handle the matching in some cases

* [Test] Update typechecker tests with payload enum test cases

* [Test] Update SILGen test

* [SIL] Add two FIXME's to address soon

* [SIL] Emit the enum case constructor unconditionally when an enum case is used as a witness

Also, tweak SILDeclRef::getLinkage to update the 'limit' to 'OnDemand' if we have an enum declaration

* [SILGen] Properly handle a enum witness in addMethodImplementation

Also remove a FIXME and code added to workaround the original bug

* [TBDGen] Handle enum case witness

* [Typechecker] Fix conflicts

* [Test] Fix tests

* [AST] Fix indentation in diagnostics def file
2020-03-28 10:44:01 +00:00

132 lines
4.4 KiB
Swift

// RUN: %target-typecheck-verify-swift
////// WITNESS MATCHING FOR PAYLOAD-LESS ENUMS //////
// Requirement is settable, so witness cannot satisfy it //
protocol Foo1 {
static var bar: Self { get set } // expected-note {{protocol requires property 'bar' with type 'Bar1'; do you want to add a stub?}}
}
enum Bar1: Foo1 { // expected-error {{type 'Bar1' does not conform to protocol 'Foo1'}}
case bar // expected-note {{candidate is not settable, but protocol requires it}}
}
// Witness has associated values, which is unsupported //
protocol Foo2 {
static var bar: Self { get set } // expected-note {{protocol requires property 'bar' with type 'Bar2'; do you want to add a stub?}}
}
enum Bar2: Foo2 { // expected-error {{type 'Bar2' does not conform to protocol 'Foo2'}}
case bar(Int) // expected-note {{candidate is an enum case with associated values, but protocol does not allow it}}
}
protocol Foo3 {
static var bar: Self { get } // expected-note {{protocol requires property 'bar' with type 'Bar3'; do you want to add a stub?}}
}
enum Bar3: Foo3 { // expected-error {{type 'Bar3' does not conform to protocol 'Foo3'}}
case bar(Int) // expected-note {{candidate is an enum case with associated values, but protocol does not allow it}}
}
// Requirement is not static, so it cannot be witnessed by the enum case //
protocol Foo4 {
var bar: Self { get } // expected-note {{protocol requires property 'bar' with type 'Bar4'; do you want to add a stub?}}
}
enum Bar4: Foo4 { // expected-error {{type 'Bar4' does not conform to protocol 'Foo4'}}
case bar // expected-note {{candidate operates on a type, not an instance as required}}
}
protocol Foo5 {
var bar: Self { get set } // expected-note {{protocol requires property 'bar' with type 'Bar5'; do you want to add a stub?}}
}
enum Bar5: Foo5 { // expected-error {{type 'Bar5' does not conform to protocol 'Foo5'}}
case bar // expected-note {{candidate operates on a type, not an instance as required}}
}
// Requirement does not have Self type, so it cannot be witnessed by the enum case //
protocol Foo6 {
static var bar: Int { get } // expected-note {{protocol requires property 'bar' with type 'Int'; do you want to add a stub?}}
}
enum Bar6: Foo6 { // expected-error {{type 'Bar6' does not conform to protocol 'Foo6'}}
case bar // expected-note {{candidate has non-matching type '(Bar6.Type) -> Bar6'}}
}
// Valid cases
protocol Foo7 {
static var bar: Self { get }
}
enum Bar7: Foo7 {
case bar // Okay
}
protocol Foo8 {
static var bar: Bar8 { get }
}
enum Bar8: Foo8 {
case bar // Okay
}
////// WITNESS MATCHING FOR PAYLOAD ENUMS //////
// Witness does not have argument label, but requirement does
protocol Foo9 {
static func bar(f: Int) -> Self // expected-note {{protocol requires function 'bar(f:)' with type '(Int) -> Bar9'; do you want to add a stub?}}
}
enum Bar9: Foo9 { // expected-error {{type 'Bar9' does not conform to protocol 'Foo9'}}
case bar(_ f: Int) // expected-note {{candidate has non-matching type '(Bar9.Type) -> (Int) -> Bar9'}}
}
// Witness does not have any labels, but requirement does
protocol Foo10 {
static func bar(g: Int) -> Self // expected-note {{protocol requires function 'bar(g:)' with type '(Int) -> Bar10'; do you want to add a stub?}}
}
enum Bar10: Foo10 { // expected-error {{type 'Bar10' does not conform to protocol 'Foo10'}}
case bar(Int) // expected-note {{candidate has non-matching type '(Bar10.Type) -> (Int) -> Bar10'}}
}
// Witness does not have a payload, but requirement is a function
protocol Foo11 {
static func bar(h: Int) -> Self // expected-note {{protocol requires function 'bar(h:)' with type '(Int) -> Bar11'; do you want to add a stub?}}
}
enum Bar11: Foo11 { // expected-error {{type 'Bar11' does not conform to protocol 'Foo11'}}
case bar // expected-note {{candidate has non-matching type '(Bar11.Type) -> Bar11'}}
}
// Witness is static, but requirement is not
protocol Foo12 {
func bar(i: Int) -> Self // expected-note {{protocol requires function 'bar(i:)' with type '(Int) -> Bar12'; do you want to add a stub?}}
}
enum Bar12: Foo12 { // expected-error {{type 'Bar12' does not conform to protocol 'Foo12'}}
case bar // expected-note {{candidate operates on a type, not an instance as required}}
}
// Valid cases
protocol Foo13 {
static func bar(j: Int) -> Self
static func baz(_ k: String) -> Bar13
}
enum Bar13: Foo13 {
case bar(j: Int) // Okay
case baz(_ k: String) // Okay
}