From 2800464fe66c1145b7cd34383295842bf21019a5 Mon Sep 17 00:00:00 2001 From: Suyash Srijan Date: Wed, 2 Sep 2020 20:39:14 +0100 Subject: [PATCH 01/10] [Typechecker] Drop the 'Self or associated type' diagnostic --- include/swift/AST/DiagnosticsSema.def | 3 --- lib/Sema/TypeCheckType.cpp | 33 +-------------------------- 2 files changed, 1 insertion(+), 35 deletions(-) diff --git a/include/swift/AST/DiagnosticsSema.def b/include/swift/AST/DiagnosticsSema.def index b1aa9b8d00fa7..3c7c764f0eff8 100644 --- a/include/swift/AST/DiagnosticsSema.def +++ b/include/swift/AST/DiagnosticsSema.def @@ -920,9 +920,6 @@ NOTE(object_literal_resolve_import,none, ERROR(use_local_before_declaration,none, "use of local variable %0 before its declaration", (DeclNameRef)) -ERROR(unsupported_existential_type,none, - "protocol %0 can only be used as a generic constraint because it has " - "Self or associated type requirements", (Identifier)) ERROR(decl_does_not_exist_in_module,none, "%select{%error|type|struct|class|enum|protocol|variable|function}0 " diff --git a/lib/Sema/TypeCheckType.cpp b/lib/Sema/TypeCheckType.cpp index e9ea56b2187ed..8bd0e193b0e20 100644 --- a/lib/Sema/TypeCheckType.cpp +++ b/lib/Sema/TypeCheckType.cpp @@ -3997,38 +3997,7 @@ class UnsupportedProtocolVisitor } void visitIdentTypeRepr(IdentTypeRepr *T) { - if (T->isInvalid()) - return; - - auto comp = T->getComponentRange().back(); - if (auto *proto = dyn_cast_or_null(comp->getBoundDecl())) { - if (!proto->existentialTypeSupported()) { - Ctx.Diags.diagnose(comp->getNameLoc(), - diag::unsupported_existential_type, - proto->getName()); - T->setInvalid(); - } - } else if (auto *alias = dyn_cast_or_null(comp->getBoundDecl())) { - auto type = Type(alias->getDeclaredInterfaceType()->getDesugaredType()); - type.findIf([&](Type type) -> bool { - if (T->isInvalid()) - return false; - if (type->isExistentialType()) { - auto layout = type->getExistentialLayout(); - for (auto *proto : layout.getProtocols()) { - auto *protoDecl = proto->getDecl(); - if (protoDecl->existentialTypeSupported()) - continue; - - Ctx.Diags.diagnose(comp->getNameLoc(), - diag::unsupported_existential_type, - protoDecl->getName()); - T->setInvalid(); - } - } - return false; - }); - } + return; } void visitRequirements(ArrayRef reqts) { From ccaa6707fea2c6d8cd45649af68729b2b227c368 Mon Sep 17 00:00:00 2001 From: Anthony Latsis Date: Mon, 16 Aug 2021 18:26:35 +0300 Subject: [PATCH 02/10] =?UTF-8?q?Docs:=20Reattach,=20rewrite=20and=20renam?= =?UTF-8?q?e=20the=20=C2=ABassociated-type-requirements=C2=BB=20educationa?= =?UTF-8?q?l=20note?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- include/swift/AST/EducationalNotes.def | 4 +- .../associated-type-requirements.md | 28 ---------- .../existential-member-access-limitations.md | 54 +++++++++++++++++++ 3 files changed, 56 insertions(+), 30 deletions(-) delete mode 100644 userdocs/diagnostics/associated-type-requirements.md create mode 100644 userdocs/diagnostics/existential-member-access-limitations.md diff --git a/include/swift/AST/EducationalNotes.def b/include/swift/AST/EducationalNotes.def index 0ba9c1e9fdd13..bc57ec20410c0 100644 --- a/include/swift/AST/EducationalNotes.def +++ b/include/swift/AST/EducationalNotes.def @@ -21,8 +21,8 @@ // EDUCATIONAL_NOTES(DIAG_ID, EDUCATIONAL_NOTE_FILENAMES...) -EDUCATIONAL_NOTES(unsupported_existential_type, - "associated-type-requirements.md") +EDUCATIONAL_NOTES(could_not_use_member_on_existential, + "existential-member-access-limitations.md") EDUCATIONAL_NOTES(cannot_pass_type_to_non_ephemeral, "temporary-pointers.md") EDUCATIONAL_NOTES(cannot_pass_type_to_non_ephemeral_warning, diff --git a/userdocs/diagnostics/associated-type-requirements.md b/userdocs/diagnostics/associated-type-requirements.md deleted file mode 100644 index 47c5dda89ee47..0000000000000 --- a/userdocs/diagnostics/associated-type-requirements.md +++ /dev/null @@ -1,28 +0,0 @@ -# Using Protocols with `Self` or Associated Type Requirements - -Protocols in Swift may be used as types, as part of a generic constraint, or as part of an opaque result type. - -```swift -// `CustomStringConvertible` can be used as a type. -func foo(bar: CustomStringConvertible) { /* ... */ } - -// ...or as a generic constraint on `T`. -func bar(baz: T) { /* ... */ } - -// ...or as part of an opaque result type. -func baz() -> some CustomStringConvertible { /* ... */ } -``` - -While all Swift protocols can be used as generic constraints and as part of opaque result types, not all protocols can be used as types. Specifically, if a protocol has a requirement which references `Self` (in contexts other than a function's return type) or an associated type, it cannot be used as a type. For example, the protocol `Equatable` requires `static func == (lhs: Self, rhs: Self) -> Bool`, and the protocol `Identifiable` requires `var id: ID { get }`, where `ID` is an associated type. As a result, the following code is not allowed: - -```swift -func foo(bar: Equatable) { /* ... */ } -// error: protocol 'Equatable' can only be used as a generic constraint because it has Self or associated type requirements - -func foo(bar: Identifiable) { /* ... */ } -// error: protocol 'Identifiable' can only be used as a generic constraint because it has Self or associated type requirements -``` - -These `Self` or associated type requirements cannot be used via a protocol type because they do not have a well-defined meaning without a concrete conforming type. Therefore, Swift does not support the use of protocols as types if they have such `Self` or associated type requirements, since those types would be able to present only a potentially unusable subset of the interface required for instances of concrete conforming types. - -When working with protocols that have `Self` or associated type requirements, most use cases can be supported by constrained generics, opaque result types, or manual type erasure. To learn more, see the sections on [protocols](https://docs.swift.org/swift-book/LanguageGuide/Protocols.html), [generics](https://docs.swift.org/swift-book/LanguageGuide/Generics.html), and [opaque types](https://docs.swift.org/swift-book/LanguageGuide/OpaqueTypes.html) in _The Swift Programming Language_. diff --git a/userdocs/diagnostics/existential-member-access-limitations.md b/userdocs/diagnostics/existential-member-access-limitations.md new file mode 100644 index 0000000000000..4ae0be9fd5881 --- /dev/null +++ b/userdocs/diagnostics/existential-member-access-limitations.md @@ -0,0 +1,54 @@ +# Using Protocol Members with References to `Self` or `Self`-rooted Associated Types + +Protocol requirements and protocol extension members may be accessed via a conformance constraint on a generic parameter, an opaque result type, or via the protocol type itself: + +```swift +// An appropriately constrained generic parameter. +func foo(arg: T) { + let description: String = arg.description +} + +do { + // An appropriately constrained opaque result type. + func foo() -> some CustomStringConvertible { true } + + let description: String = foo().description +} + +// The protocol type. +func foo(arg: CustomStringConvertible) { + let description: String = arg.description +} +``` + +While the former two options enable full access to the protocol interface, not all members may be accessible when the protocol is used as a type and not a constraint. Specifically, a protocol member cannot be accessed on a protocol type when its type signature contains a reference to `Self` or a `Self`-rooted associated type. Accessing such members on a protocol type is not supported because today the compiler does not have a well-defined meaning and means of representation for `Self` and `Self`-rooted associated types with respect to a protocol type `P`. As a result, the following code is not allowed: + +```swift +protocol Shape { + func matches(_ other: Self) -> Bool +} + +func foo(_ shape: Shape) { + // error: member 'matches' cannot be used on value of protocol type 'Shape'; use a generic constraint instead + shape.matches(shape) +} + +func foo(_ arg: Identifiable) { + // error: member 'id' cannot be used on value of protocol type 'Identifiable'; use a generic constraint instead + _ = arg.id +} +``` + +An exception to this limitation are members that contain `Self` only in [covariant](https://en.wikipedia.org/wiki/Covariance_and_contravariance_(computer_science)) position (such as a method result type), where `Self` can be safely substituted with the protocol or protocol composition type used to access the member — a representable supertype. On the other hand, resorting to this ploy in contravariant parameter type position, like allowing one to pass a type-erased value to a method that accepts `Self`, is not type-safe and would expose the opportunity to pass in an argument of non-matching type. + +```swift +protocol Shape { + func duplicate() -> Self +} + +func duplicateShape(_ shape: Shape) -> Shape { + return shape.duplicate // OK, produces a value of type 'Shape' +} +``` + +Most use cases involving usage of protocol members that fall under the above restriction can instead be supported by constrained generics, opaque result types, or manual type-erasing wrappers. To learn more, see the sections on [protocols](https://docs.swift.org/swift-book/LanguageGuide/Protocols.html), [generics](https://docs.swift.org/swift-book/LanguageGuide/Generics.html), and [opaque types](https://docs.swift.org/swift-book/LanguageGuide/OpaqueTypes.html) in the Language Guide. For a better understanding of existential types in particular, and an in-depth exploration of the relationships among these built-in abstraction models, we recommend reading the [design document for improving the UI of the generics model](https://forums.swift.org/t/improving-the-ui-of-generics/22814). From 4cc1506c27de9d9424e483cc95da81537366e509 Mon Sep 17 00:00:00 2001 From: Suyash Srijan Date: Wed, 2 Sep 2020 22:04:00 +0100 Subject: [PATCH 03/10] [Test] Add additional tests for new behavior --- .../protocols_with_self_or_assoc_reqs.swift | 472 ++++++++++++++++++ ...s_with_self_or_assoc_reqs_executable.swift | 107 ++++ 2 files changed, 579 insertions(+) create mode 100644 test/decl/protocol/protocols_with_self_or_assoc_reqs.swift create mode 100644 test/decl/protocol/protocols_with_self_or_assoc_reqs_executable.swift diff --git a/test/decl/protocol/protocols_with_self_or_assoc_reqs.swift b/test/decl/protocol/protocols_with_self_or_assoc_reqs.swift new file mode 100644 index 0000000000000..6ab23577f781d --- /dev/null +++ b/test/decl/protocol/protocols_with_self_or_assoc_reqs.swift @@ -0,0 +1,472 @@ +// RUN: %target-typecheck-verify-swift -disable-availability-checking + +//===----------------------------------------------------------------------===// +// Use of protocols with Self or associated type requirements +//===----------------------------------------------------------------------===// + +struct G { + class Inner {} +} +class C {} + +protocol P1 { + associatedtype Q + + // Methods + func covariantSelfSimple() -> Self + func covariantSelfComplex(_: (Self) -> Void, + _: (Self?) -> Void, + _: (Array) -> Void, + _: (Array?>) -> Void + ) -> [String : () -> (Self, Self)] + func covariantAssocSimple() -> Q + func covariantAssocComplex(_: (Q) -> Void, + _: (Q?) -> Void, + _: (Array) -> Void, + _: (Array?>) -> Void + ) -> [String : () -> (Q, Q)] + + func contravariantSelf1(_: Self?) + func contravariantSelf2(_: () -> Self) + func contravariantSelf3(_: Array<() -> Self>) + func contravariantSelf4(_: [String : () -> Self]) + func contravariantSelf5(_: () -> (Self, Self)) + func contravariantSelf6(_: ((Self) -> Void) -> Void) + func contravariantSelf7() -> (Self) -> Void + func contravariantSelf8() -> Array<((Self) -> Void)?> + func contravariantSelf9(_: [String : (() -> Self)?]) + func contravariantSelf10() -> (Array<[String : Self??]>) -> Void + func contravariantAssoc1(_: Q?) + func contravariantAssoc2(_: () -> Q) + func contravariantAssoc3(_: Array<() -> Q>) + func contravariantAssoc4(_: [String : () -> Q]) + func contravariantAssoc5(_: () -> (Q, Q)) + func contravariantAssoc6(_: ((Q) -> Void) -> Void) + func contravariantAssoc7() -> (Q) -> Void + func contravariantAssoc8() -> Array<((Q) -> Void)?> + func contravariantAssoc9(_: [String : (() -> Q)?]) + func contravariantAssoc10() -> (Array<[String : Q??]>) -> Void + + func invariantSelf1(_: inout Self) + func invariantSelf2(_: (inout Self) -> Void) + func invariantSelf3(_: inout Array<() -> Self>) + func invariantSelf4(_: G) + func invariantSelf5() -> G + func invariantSelf6() -> G.Inner + func invariantSelf7(_: (G) -> Void) + func invariantSelf8(_: G<(Self) -> Void>) + func invariantSelf9(_: G<() -> Self>) + func invariantSelf10(_: P1 & C) + func invariantAssoc1(_: inout Q) + func invariantAssoc2(_: (inout Q) -> Void) + func invariantAssoc3(_: inout Array<() -> Q>) + func invariantAssoc4(_: G) + func invariantAssoc5() -> G + func invariantAssoc6() -> G.Inner + func invariantAssoc7(_: (G) -> Void) + func invariantAssoc8(_: G<(Q) -> Void>) + func invariantAssoc9(_: G<() -> Q>) + func invariantAssoc10(_: P1 & C) + + // Properties + var covariantSelfPropSimple: Self { get } + var covariantSelfPropComplex: ( + _: (Self) -> Void, + _: (Self?) -> Void, + _: (Array) -> Void, + _: (Array?>) -> Void + ) -> [String : () -> (Self, Self)] { get } + var covariantAssocPropSimple: Q { get } + var covariantAssocPropComplex: ( + _: (Q) -> Void, + _: (Q?) -> Void, + _: (Array) -> Void, + _: (Array?>) -> Void + ) -> [String : () -> (Q, Q)] { get } + + var contravariantSelfProp1: (Self?) -> Void { get } + var contravariantSelfProp2: (() -> Self) -> Void { get } + var contravariantSelfProp3: (Array<() -> Self>) -> Void { get } + var contravariantSelfProp4: ([String : () -> Self]) -> Void { get } + var contravariantSelfProp5: (() -> (Self, Self)) -> Void { get } + var contravariantSelfProp6: (((Self) -> Void) -> Void) -> Void { get } + var contravariantSelfProp7: (Self) -> Void { get } + var contravariantSelfProp8: Array<((Self) -> Void)?> { get } + var contravariantSelfProp9: ([String : (() -> Self)?]) -> Void { get } + var contravariantSelfProp10: (Array<[String : Self??]>) -> Void { get } + var contravariantAssocProp1: (Q?) -> Void { get } + var contravariantAssocProp2: (() -> Q) -> Void { get } + var contravariantAssocProp3: (Array<() -> Q>) -> Void { get } + var contravariantAssocProp4: ([String : () -> Q]) -> Void { get } + var contravariantAssocProp5: (() -> (Q, Q)) -> Void { get } + var contravariantAssocProp6: (((Q) -> Void) -> Void) -> Void { get } + var contravariantAssocProp7: (Q) -> Void { get } + var contravariantAssocProp8: Array<((Q) -> Void)?> { get } + var contravariantAssocProp9: ([String : (() -> Q)?]) -> Void { get } + var contravariantAssocProp10: (Array<[String : Q??]>) -> Void { get } + + var invariantSelfProp1: (inout Self) -> Void { get } + var invariantSelfProp2: ((inout Self) -> Void) -> Void { get } + var invariantSelfProp3: (inout Array<() -> Self>) -> Void { get } + var invariantSelfProp4: (G) -> Void { get } + var invariantSelfProp5: G { get } + var invariantSelfProp6: G.Inner { get } + var invariantSelfProp7: ((G) -> Void) -> Void { get } + var invariantSelfProp8: (G<(Self) -> Void>) -> Void { get } + var invariantSelfProp9: (G<() -> Self>) -> Void { get } + var invariantSelfProp10: (P1 & C) -> Void { get } + var invariantAssocProp1: (inout Q) -> Void { get } + var invariantAssocProp2: ((inout Q) -> Void) -> Void { get } + var invariantAssocProp3: (inout Array<() -> Q>) -> Void { get } + var invariantAssocProp4: (G) -> Void { get } + var invariantAssocProp5: G { get } + var invariantAssocProp6: G.Inner { get } + var invariantAssocProp7: ((G) -> Void) { get } + var invariantAssocProp8: (G<(Q) -> Void>) { get } + var invariantAssocProp9: (G<() -> Q>) -> Void { get } + var invariantAssocProp10: (P1 & C) -> Void { get } + + // Subscripts + subscript(covariantSelfSubscriptSimple _: Void) -> Self { get } + subscript(covariantSelfSubscriptComplex _: (Self) -> Void, + _: (Self?) -> Void, + _: (Array) -> Void, + _: (Array?>) -> Void + ) -> [String : () -> (Self, Self)] { get } + subscript(covariantAssocSubscriptSimple _: Void) -> Q { get } + subscript(covariantAssocSubscriptComplex _: (Q) -> Void, + _: (Q?) -> Void, + _: (Array) -> Void, + _: (Array?>) -> Void + ) -> [String : () -> (Q, Q)] { get } + + subscript(contravariantSelfSubscript1 _: Self?) -> Void { get } + subscript(contravariantSelfSubscript2 _: () -> Self) -> Void { get } + subscript(contravariantSelfSubscript3 _: Array<() -> Self>) -> Void { get } + subscript(contravariantSelfSubscript4 _: [String : () -> Self]) -> Void { get } + subscript(contravariantSelfSubscript5 _: () -> (Self, Self)) -> Void { get } + subscript(contravariantSelfSubscript6 _: ((Self) -> Void) -> Void) -> Void { get } + subscript(contravariantSelfSubscript7 _: Void) -> (Self) -> Void { get } + subscript(contravariantSelfSubscript8 _: Void) -> Array<((Self) -> Void)?> { get } + subscript(contravariantSelfSubscript9 _: [String : (() -> Self)?]) -> Void { get } + subscript(contravariantSelfSubscript10 _: Void) -> (Array<[String : Self??]>) -> Void { get } + subscript(contravariantAssocSubscript1 _: Q?) -> Void { get } + subscript(contravariantAssocSubscript2 _: () -> Q) -> Void { get } + subscript(contravariantAssocSubscript3 _: Array<() -> Q>) -> Void { get } + subscript(contravariantAssocSubscript4 _: [String : () -> Q]) -> Void { get } + subscript(contravariantAssocSubscript5 _: () -> (Q, Q)) -> Void { get } + subscript(contravariantAssocSubscript6 _: ((Q) -> Void) -> Void) -> Void { get } + subscript(contravariantAssocSubscript7 _: Void) -> (Q) -> Void { get } + subscript(contravariantAssocSubscript8 _: Void) -> Array<((Q) -> Void)?> { get } + subscript(contravariantAssocSubscript9 _: [String : (() -> Q)?]) -> Void { get } + subscript(contravariantAssocSubscript10 _: Void) -> (Array<[String : Q??]>) -> Void { get } + + subscript(invariantSelfSubscript1 _: G) -> Void { get } + subscript(invariantSelfSubscript2 _: Void) -> G { get } + subscript(invariantSelfSubscript3 _: Void) -> G.Inner { get } + subscript(invariantSelfSubscript4 _: (G) -> Void) -> Void { get } + subscript(invariantSelfSubscript5 _: G<(Self) -> Void>) -> Void { get } + subscript(invariantSelfSubscript6 _: G<() -> Self>) -> Void { get } + subscript(invariantSelfSubscript7 _: P1 & C) -> Void { get } + subscript(invariantAssocSubscript1 _: G) -> Void { get } + subscript(invariantAssocSubscript2 _: Void) -> G { get } + subscript(invariantAssocSubscript3 _: Void) -> G.Inner { get } + subscript(invariantAssocSubscript4 _: (G) -> Void) -> Void { get } + subscript(invariantAssocSubscript5 _: G<(Q) -> Void>) -> Void { get } + subscript(invariantAssocSubscript6 _: G<() -> Q>) -> Void { get } + subscript(invariantAssocSubscript7 _: P1 & C) -> Void { get } +} +@available(macOS 10.15, *) +extension P1 { + func invariantSelf1_1() -> some P1 { self } + var invariantSelfProp1_1: some P1 { self } + subscript(invariantSelfSubscript1_1: Void) -> some P1 { self } +} + +do { + func testP1(arg: P1) { + _ = arg.covariantSelfSimple() // ok + let _: P1 = arg.covariantSelfSimple() // ok + _ = arg.covariantSelfComplex({ _ in }, { _ in }, { _ in }, { _ in }) // ok + let _: [String : () -> (P1, P1)] = arg.covariantSelfComplex( + { (x: P1) in }, + { (x: P1?) in }, + { (x: Array) in }, + { (x: Array?>) in } + ) // ok + arg.covariantAssocSimple // expected-error {{member 'covariantAssocSimple' cannot be used on value of protocol type 'P1'; use a generic constraint instead}} + arg.covariantAssocComplex({ _ in }, { _ in }, { _ in }, { _ in }) // expected-error {{member 'covariantAssocComplex' cannot be used on value of protocol type 'P1'; use a generic constraint instead}} + // FIXME: expected-error@-1 {{unable to infer type of a closure parameter '_' in the current context}} + + _ = arg.covariantSelfPropSimple // ok + let _: P1 = arg.covariantSelfPropSimple // ok + _ = arg.covariantSelfPropComplex // ok + let _: ( + _: (P1) -> Void, + _: (P1?) -> Void, + _: (Array) -> Void, + _: (Array?>) -> Void + ) -> [String : () -> (P1, P1)] = arg.covariantSelfPropComplex // ok + arg.covariantAssocPropSimple // expected-error {{member 'covariantAssocPropSimple' cannot be used on value of protocol type 'P1'; use a generic constraint instead}} + arg.covariantAssocPropComplex // expected-error {{member 'covariantAssocPropComplex' cannot be used on value of protocol type 'P1'; use a generic constraint instead}} + + _ = arg[covariantSelfSubscriptSimple: ()] // ok + let _: P1 = arg[covariantSelfSubscriptSimple: ()] // ok + _ = arg[covariantSelfSubscriptComplex: { _ in }, { _ in }, { _ in }, { _ in }] // ok + let _: [String : () -> (P1, P1)] = arg[ + covariantSelfSubscriptComplex: { (x: P1) in }, + { (x: P1?) in }, + { (x: Array) in }, + { (x: Array?>) in } + ] // ok + arg[covariantAssocSubscriptSimple: ()] // expected-error {{member 'subscript' cannot be used on value of protocol type 'P1'; use a generic constraint instead}} + arg[covariantAssocSubscriptComplex: { _ in }, { _ in }, { _ in }, { _ in }] // expected-error {{member 'subscript' cannot be used on value of protocol type 'P1'; use a generic constraint instead}} + + arg.contravariantSelf1(0) // expected-error {{member 'contravariantSelf1' cannot be used on value of protocol type 'P1'; use a generic constraint instead}} + // FIXME: Silence these since we cannot make use of the member anyway. + // expected-error@-2 {{argument type 'Int' does not conform to expected type 'P1'}} + arg.contravariantSelf2(0) // expected-error {{member 'contravariantSelf2' cannot be used on value of protocol type 'P1'; use a generic constraint instead}} + // expected-error@-1 {{cannot convert value of type 'Int' to expected argument type '() -> P1'}} + arg.contravariantSelf3(0) // expected-error {{member 'contravariantSelf3' cannot be used on value of protocol type 'P1'; use a generic constraint instead}} + // expected-error@-1 {{cannot convert value of type 'Int' to expected argument type 'Array<() -> P1>'}} + arg.contravariantSelf4(0) // expected-error {{member 'contravariantSelf4' cannot be used on value of protocol type 'P1'; use a generic constraint instead}} + // expected-error@-1 {{cannot convert value of type 'Int' to expected argument type '[String : () -> P1]'}} + arg.contravariantSelf5(0) // expected-error {{member 'contravariantSelf5' cannot be used on value of protocol type 'P1'; use a generic constraint instead}} + // expected-error@-1 {{cannot convert value of type 'Int' to expected argument type '() -> (P1, P1)'}} + arg.contravariantSelf6(0) // expected-error {{member 'contravariantSelf6' cannot be used on value of protocol type 'P1'; use a generic constraint instead}} + // expected-error@-1 {{cannot convert value of type 'Int' to expected argument type '((P1) -> Void) -> Void'}} + arg.contravariantSelf7() // expected-error {{member 'contravariantSelf7' cannot be used on value of protocol type 'P1'; use a generic constraint instead}} + arg.contravariantSelf8() // expected-error {{member 'contravariantSelf8' cannot be used on value of protocol type 'P1'; use a generic constraint instead}} + arg.contravariantSelf9(0) // expected-error {{member 'contravariantSelf9' cannot be used on value of protocol type 'P1'; use a generic constraint instead}} + // expected-error@-1 {{cannot convert value of type 'Int' to expected argument type '[String : (() -> P1)?]'}} + arg.contravariantSelf10() // expected-error {{member 'contravariantSelf10' cannot be used on value of protocol type 'P1'; use a generic constraint instead}} + arg.contravariantAssoc1(0) // expected-error {{member 'contravariantAssoc1' cannot be used on value of protocol type 'P1'; use a generic constraint instead}} + // FIXME: Silence these since we cannot make use of the member anyway. + // expected-error@-2 {{cannot convert value of type 'Int' to expected argument type 'P1.Q?'}} + arg.contravariantAssoc2(0) // expected-error {{member 'contravariantAssoc2' cannot be used on value of protocol type 'P1'; use a generic constraint instead}} + // expected-error@-1 {{cannot convert value of type 'Int' to expected argument type '() -> P1.Q'}} + arg.contravariantAssoc3(0) // expected-error {{member 'contravariantAssoc3' cannot be used on value of protocol type 'P1'; use a generic constraint instead}} + // expected-error@-1 {{cannot convert value of type 'Int' to expected argument type 'Array<() -> P1.Q>'}} + arg.contravariantAssoc4(0) // expected-error {{member 'contravariantAssoc4' cannot be used on value of protocol type 'P1'; use a generic constraint instead}} + // expected-error@-1 {{cannot convert value of type 'Int' to expected argument type '[String : () -> P1.Q]'}} + arg.contravariantAssoc5(0) // expected-error {{member 'contravariantAssoc5' cannot be used on value of protocol type 'P1'; use a generic constraint instead}} + // expected-error@-1 {{cannot convert value of type 'Int' to expected argument type '() -> (P1.Q, P1.Q)'}} + arg.contravariantAssoc6(0) // expected-error {{member 'contravariantAssoc6' cannot be used on value of protocol type 'P1'; use a generic constraint instead}} + // expected-error@-1 {{cannot convert value of type 'Int' to expected argument type '((P1.Q) -> Void) -> Void'}} + arg.contravariantAssoc7() // expected-error {{member 'contravariantAssoc7' cannot be used on value of protocol type 'P1'; use a generic constraint instead}} + arg.contravariantAssoc8() // expected-error {{member 'contravariantAssoc8' cannot be used on value of protocol type 'P1'; use a generic constraint instead}} + arg.contravariantAssoc9(0) // expected-error {{member 'contravariantAssoc9' cannot be used on value of protocol type 'P1'; use a generic constraint instead}} + // expected-error@-1 {{cannot convert value of type 'Int' to expected argument type '[String : (() -> P1.Q)?]'}} + arg.contravariantAssoc10() // expected-error {{member 'contravariantAssoc10' cannot be used on value of protocol type 'P1'; use a generic constraint instead}} + + + arg.invariantSelf1(0) // expected-error {{member 'invariantSelf1' cannot be used on value of protocol type 'P1'; use a generic constraint instead}} + // FIXME: Silence these since we cannot make use of the member anyway. + // expected-error@-2 {{argument type 'Int' does not conform to expected type 'P1'}} + if #available(macOS 10.15, *) { + arg.invariantSelf1_1() // expected-error {{member 'invariantSelf1_1' cannot be used on value of protocol type 'P1'; use a generic constraint instead}} + } + arg.invariantSelf2(0) // expected-error {{member 'invariantSelf2' cannot be used on value of protocol type 'P1'; use a generic constraint instead}} + // expected-error@-1 {{cannot convert value of type 'Int' to expected argument type '(inout P1) -> Void'}} + arg.invariantSelf3(0) // expected-error {{member 'invariantSelf3' cannot be used on value of protocol type 'P1'; use a generic constraint instead}} + // expected-error@-1 {{cannot convert value of type 'Int' to expected argument type 'Array<() -> P1>'}} + arg.invariantSelf4(0) // expected-error {{member 'invariantSelf4' cannot be used on value of protocol type 'P1'; use a generic constraint instead}} + // expected-error@-1 {{cannot convert value of type 'Int' to expected argument type 'G'}} + arg.invariantSelf5() // expected-error {{member 'invariantSelf5' cannot be used on value of protocol type 'P1'; use a generic constraint instead}} + // FIXME: Should be diagnosed. +// arg.invariantSelf6() + arg.invariantSelf7(0) // expected-error {{member 'invariantSelf7' cannot be used on value of protocol type 'P1'; use a generic constraint instead}} + // expected-error@-1 {{cannot convert value of type 'Int' to expected argument type '(G) -> Void'}} + arg.invariantSelf8(0) // expected-error {{member 'invariantSelf8' cannot be used on value of protocol type 'P1'; use a generic constraint instead}} + // expected-error@-1 {{cannot convert value of type 'Int' to expected argument type 'G<(P1) -> Void>'}} + arg.invariantSelf9(0) // expected-error {{member 'invariantSelf9' cannot be used on value of protocol type 'P1'; use a generic constraint instead}} + // expected-error@-1 {{cannot convert value of type 'Int' to expected argument type 'G<() -> P1>'}} + // FIXME: Should be diagnosed. +// arg.invariantSelf10(0) + arg.invariantAssoc1(0) // expected-error {{member 'invariantAssoc1' cannot be used on value of protocol type 'P1'; use a generic constraint instead}} + // FIXME: Silence these since we cannot make use of the member anyway. + // expected-error@-2 {{cannot convert value of type 'Int' to expected argument type 'P1.Q'}} + arg.invariantAssoc2(0) // expected-error {{member 'invariantAssoc2' cannot be used on value of protocol type 'P1'; use a generic constraint instead}} + // expected-error@-1 {{cannot convert value of type 'Int' to expected argument type '(inout P1.Q) -> Void'}} + arg.invariantAssoc3(0) // expected-error {{member 'invariantAssoc3' cannot be used on value of protocol type 'P1'; use a generic constraint instead}} + // expected-error@-1 {{cannot convert value of type 'Int' to expected argument type 'Array<() -> P1.Q>'}} + arg.invariantAssoc4(0) // expected-error {{member 'invariantAssoc4' cannot be used on value of protocol type 'P1'; use a generic constraint instead}} + // expected-error@-1 {{cannot convert value of type 'Int' to expected argument type 'G'}} + arg.invariantAssoc5() // expected-error {{member 'invariantAssoc5' cannot be used on value of protocol type 'P1'; use a generic constraint instead}} + // FIXME: Should be diagnosed. +// arg.invariantAssoc6() + arg.invariantAssoc7(0) // expected-error {{member 'invariantAssoc7' cannot be used on value of protocol type 'P1'; use a generic constraint instead}} + // expected-error@-1 {{cannot convert value of type 'Int' to expected argument type '(G) -> Void'}} + arg.invariantAssoc8(0) // expected-error {{member 'invariantAssoc8' cannot be used on value of protocol type 'P1'; use a generic constraint instead}} + // expected-error@-1 {{cannot convert value of type 'Int' to expected argument type 'G<(P1.Q) -> Void>'}} + arg.invariantAssoc9(0) // expected-error {{member 'invariantAssoc9' cannot be used on value of protocol type 'P1'; use a generic constraint instead}} + // expected-error@-1 {{cannot convert value of type 'Int' to expected argument type 'G<() -> P1.Q>'}} + // FIXME: Should be diagnosed. +// arg.invariantAssoc10(0) + + arg.contravariantSelfProp1 // expected-error {{member 'contravariantSelfProp1' cannot be used on value of protocol type 'P1'; use a generic constraint instead}} + arg.contravariantSelfProp2 // expected-error {{member 'contravariantSelfProp2' cannot be used on value of protocol type 'P1'; use a generic constraint instead}} + arg.contravariantSelfProp3 // expected-error {{member 'contravariantSelfProp3' cannot be used on value of protocol type 'P1'; use a generic constraint instead}} + arg.contravariantSelfProp4 // expected-error {{member 'contravariantSelfProp4' cannot be used on value of protocol type 'P1'; use a generic constraint instead}} + arg.contravariantSelfProp5 // expected-error {{member 'contravariantSelfProp5' cannot be used on value of protocol type 'P1'; use a generic constraint instead}} + arg.contravariantSelfProp6 // expected-error {{member 'contravariantSelfProp6' cannot be used on value of protocol type 'P1'; use a generic constraint instead}} + arg.contravariantSelfProp7 // expected-error {{member 'contravariantSelfProp7' cannot be used on value of protocol type 'P1'; use a generic constraint instead}} + arg.contravariantSelfProp8 // expected-error {{member 'contravariantSelfProp8' cannot be used on value of protocol type 'P1'; use a generic constraint instead}} + arg.contravariantSelfProp9 // expected-error {{member 'contravariantSelfProp9' cannot be used on value of protocol type 'P1'; use a generic constraint instead}} + arg.contravariantSelfProp10 // expected-error {{member 'contravariantSelfProp10' cannot be used on value of protocol type 'P1'; use a generic constraint instead}} + arg.contravariantAssocProp1 // expected-error {{member 'contravariantAssocProp1' cannot be used on value of protocol type 'P1'; use a generic constraint instead}} + arg.contravariantAssocProp2 // expected-error {{member 'contravariantAssocProp2' cannot be used on value of protocol type 'P1'; use a generic constraint instead}} + arg.contravariantAssocProp3 // expected-error {{member 'contravariantAssocProp3' cannot be used on value of protocol type 'P1'; use a generic constraint instead}} + arg.contravariantAssocProp4 // expected-error {{member 'contravariantAssocProp4' cannot be used on value of protocol type 'P1'; use a generic constraint instead}} + arg.contravariantAssocProp5 // expected-error {{member 'contravariantAssocProp5' cannot be used on value of protocol type 'P1'; use a generic constraint instead}} + arg.contravariantAssocProp6 // expected-error {{member 'contravariantAssocProp6' cannot be used on value of protocol type 'P1'; use a generic constraint instead}} + arg.contravariantAssocProp7 // expected-error {{member 'contravariantAssocProp7' cannot be used on value of protocol type 'P1'; use a generic constraint instead}} + arg.contravariantAssocProp8 // expected-error {{member 'contravariantAssocProp8' cannot be used on value of protocol type 'P1'; use a generic constraint instead}} + arg.contravariantAssocProp9 // expected-error {{member 'contravariantAssocProp9' cannot be used on value of protocol type 'P1'; use a generic constraint instead}} + arg.contravariantAssocProp10 // expected-error {{member 'contravariantAssocProp10' cannot be used on value of protocol type 'P1'; use a generic constraint instead}} + + arg.invariantSelfProp1 // expected-error {{member 'invariantSelfProp1' cannot be used on value of protocol type 'P1'; use a generic constraint instead}} + if #available(macOS 10.15, *) { + arg.invariantSelfProp1_1 // expected-error {{member 'invariantSelfProp1_1' cannot be used on value of protocol type 'P1'; use a generic constraint instead}} + } + arg.invariantSelfProp2 // expected-error {{member 'invariantSelfProp2' cannot be used on value of protocol type 'P1'; use a generic constraint instead}} + arg.invariantSelfProp3 // expected-error {{member 'invariantSelfProp3' cannot be used on value of protocol type 'P1'; use a generic constraint instead}} + arg.invariantSelfProp4 // expected-error {{member 'invariantSelfProp4' cannot be used on value of protocol type 'P1'; use a generic constraint instead}} + arg.invariantSelfProp5 // expected-error {{member 'invariantSelfProp5' cannot be used on value of protocol type 'P1'; use a generic constraint instead}} + // FIXME: Should be diagnosed. +// arg.invariantSelfProp6 + arg.invariantSelfProp7 // expected-error {{member 'invariantSelfProp7' cannot be used on value of protocol type 'P1'; use a generic constraint instead}} + arg.invariantSelfProp8 // expected-error {{member 'invariantSelfProp8' cannot be used on value of protocol type 'P1'; use a generic constraint instead}} + arg.invariantSelfProp9 // expected-error {{member 'invariantSelfProp9' cannot be used on value of protocol type 'P1'; use a generic constraint instead}} + // FIXME: Should be diagnosed. +// arg.invariantSelfProp10 + arg.invariantAssocProp1 // expected-error {{member 'invariantAssocProp1' cannot be used on value of protocol type 'P1'; use a generic constraint instead}} + arg.invariantAssocProp2 // expected-error {{member 'invariantAssocProp2' cannot be used on value of protocol type 'P1'; use a generic constraint instead}} + arg.invariantAssocProp3 // expected-error {{member 'invariantAssocProp3' cannot be used on value of protocol type 'P1'; use a generic constraint instead}} + arg.invariantAssocProp4 // expected-error {{member 'invariantAssocProp4' cannot be used on value of protocol type 'P1'; use a generic constraint instead}} + arg.invariantAssocProp5 // expected-error {{member 'invariantAssocProp5' cannot be used on value of protocol type 'P1'; use a generic constraint instead}} + // FIXME: Should be diagnosed. +// arg.invariantAssocProp6 + arg.invariantAssocProp7 // expected-error {{member 'invariantAssocProp7' cannot be used on value of protocol type 'P1'; use a generic constraint instead}} + arg.invariantAssocProp8 // expected-error {{member 'invariantAssocProp8' cannot be used on value of protocol type 'P1'; use a generic constraint instead}} + arg.invariantAssocProp9 // expected-error {{member 'invariantAssocProp9' cannot be used on value of protocol type 'P1'; use a generic constraint instead}} + // FIXME: Should be diagnosed. +// arg.invariantAssocProp10 + + arg[contravariantSelfSubscript1: 0] // expected-error {{member 'subscript' cannot be used on value of protocol type 'P1'; use a generic constraint instead}} + // FIXME: Silence these since we cannot make use of the member anyway. + // expected-error@-2 {{argument type 'Int' does not conform to expected type 'P1'}} + arg[contravariantSelfSubscript2: 0] // expected-error {{member 'subscript' cannot be used on value of protocol type 'P1'; use a generic constraint instead}} + // expected-error@-1 {{cannot convert value of type 'Int' to expected argument type '() -> P1'}} + arg[contravariantSelfSubscript3: 0] // expected-error {{member 'subscript' cannot be used on value of protocol type 'P1'; use a generic constraint instead}} + // expected-error@-1 {{cannot convert value of type 'Int' to expected argument type 'Array<() -> P1>'}} + arg[contravariantSelfSubscript4: 0] // expected-error {{member 'subscript' cannot be used on value of protocol type 'P1'; use a generic constraint instead}} + // expected-error@-1 {{cannot convert value of type 'Int' to expected argument type '[String : () -> P1]'}} + arg[contravariantSelfSubscript5: 0] // expected-error {{member 'subscript' cannot be used on value of protocol type 'P1'; use a generic constraint instead}} + // expected-error@-1 {{cannot convert value of type 'Int' to expected argument type '() -> (P1, P1)'}} + arg[contravariantSelfSubscript6: 0] // expected-error {{member 'subscript' cannot be used on value of protocol type 'P1'; use a generic constraint instead}} + // expected-error@-1 {{cannot convert value of type 'Int' to expected argument type '((P1) -> Void) -> Void'}} + arg[contravariantSelfSubscript7: ()] // expected-error {{member 'subscript' cannot be used on value of protocol type 'P1'; use a generic constraint instead}} + arg[contravariantSelfSubscript8: ()] // expected-error {{member 'subscript' cannot be used on value of protocol type 'P1'; use a generic constraint instead}} + arg[contravariantSelfSubscript9: 0] // expected-error {{member 'subscript' cannot be used on value of protocol type 'P1'; use a generic constraint instead}} + // expected-error@-1 {{cannot convert value of type 'Int' to expected argument type '[String : (() -> P1)?]'}} + arg[contravariantSelfSubscript10: ()] // expected-error {{member 'subscript' cannot be used on value of protocol type 'P1'; use a generic constraint instead}} + arg[contravariantAssocSubscript1: 0] // expected-error {{member 'subscript' cannot be used on value of protocol type 'P1'; use a generic constraint instead}} + // FIXME: Silence these since we cannot make use of the member anyway. + // expected-error@-2 {{cannot convert value of type 'Int' to expected argument type 'P1.Q?'}} + arg[contravariantAssocSubscript2: 0] // expected-error {{member 'subscript' cannot be used on value of protocol type 'P1'; use a generic constraint instead}} + // expected-error@-1 {{cannot convert value of type 'Int' to expected argument type '() -> P1.Q'}} + arg[contravariantAssocSubscript3: 0] // expected-error {{member 'subscript' cannot be used on value of protocol type 'P1'; use a generic constraint instead}} + // expected-error@-1 {{cannot convert value of type 'Int' to expected argument type 'Array<() -> P1.Q>'}} + arg[contravariantAssocSubscript4: 0] // expected-error {{member 'subscript' cannot be used on value of protocol type 'P1'; use a generic constraint instead}} + // expected-error@-1 {{cannot convert value of type 'Int' to expected argument type '[String : () -> P1.Q]'}} + arg[contravariantAssocSubscript5: 0] // expected-error {{member 'subscript' cannot be used on value of protocol type 'P1'; use a generic constraint instead}} + // expected-error@-1 {{cannot convert value of type 'Int' to expected argument type '() -> (P1.Q, P1.Q)'}} + arg[contravariantAssocSubscript6: 0] // expected-error {{member 'subscript' cannot be used on value of protocol type 'P1'; use a generic constraint instead}} + // expected-error@-1 {{cannot convert value of type 'Int' to expected argument type '((P1.Q) -> Void) -> Void'}} + arg[contravariantAssocSubscript7: ()] // expected-error {{member 'subscript' cannot be used on value of protocol type 'P1'; use a generic constraint instead}} + arg[contravariantAssocSubscript8: ()] // expected-error {{member 'subscript' cannot be used on value of protocol type 'P1'; use a generic constraint instead}} + arg[contravariantAssocSubscript9: 0] // expected-error {{member 'subscript' cannot be used on value of protocol type 'P1'; use a generic constraint instead}} + // expected-error@-1 {{cannot convert value of type 'Int' to expected argument type '[String : (() -> P1.Q)?]'}} + arg[contravariantAssocSubscript10: ()] // expected-error {{member 'subscript' cannot be used on value of protocol type 'P1'; use a generic constraint instead}} + + arg[invariantSelfSubscript1: 0] // expected-error {{member 'subscript' cannot be used on value of protocol type 'P1'; use a generic constraint instead}} + // FIXME: Silence these since we cannot make use of the member anyway. + // expected-error@-2 {{cannot convert value of type 'Int' to expected argument type 'G'}} + arg[invariantSelfSubscript2: ()] // expected-error {{member 'subscript' cannot be used on value of protocol type 'P1'; use a generic constraint instead}} + // FIXME: Should be diagnosed. +// arg[invariantSelfSubscript3: ()] + arg[invariantSelfSubscript4: 0] // expected-error {{member 'subscript' cannot be used on value of protocol type 'P1'; use a generic constraint instead}} + // expected-error@-1 {{cannot convert value of type 'Int' to expected argument type '(G) -> Void'}} + arg[invariantSelfSubscript5: 0] // expected-error {{member 'subscript' cannot be used on value of protocol type 'P1'; use a generic constraint instead}} + // expected-error@-1 {{cannot convert value of type 'Int' to expected argument type 'G<(P1) -> Void>'}} + arg[invariantSelfSubscript6: 0] // expected-error {{member 'subscript' cannot be used on value of protocol type 'P1'; use a generic constraint instead}} + // expected-error@-1 {{cannot convert value of type 'Int' to expected argument type 'G<() -> P1>'}} + // FIXME: Should be diagnosed. +// arg[invariantSelfSubscript7: 0] + arg[invariantAssocSubscript1: 0] // expected-error {{member 'subscript' cannot be used on value of protocol type 'P1'; use a generic constraint instead}} + // FIXME: Silence these since we cannot make use of the member anyway. + // expected-error@-2 {{cannot convert value of type 'Int' to expected argument type 'G'}} + arg[invariantAssocSubscript2: ()] // expected-error {{member 'subscript' cannot be used on value of protocol type 'P1'; use a generic constraint instead}} + // FIXME: Should be diagnosed. +// arg[invariantAssocSubscript3: ()] + arg[invariantAssocSubscript4: 0] // expected-error {{member 'subscript' cannot be used on value of protocol type 'P1'; use a generic constraint instead}} + // expected-error@-1 {{cannot convert value of type 'Int' to expected argument type '(G) -> Void'}} + arg[invariantAssocSubscript5: 0] // expected-error {{member 'subscript' cannot be used on value of protocol type 'P1'; use a generic constraint instead}} + // expected-error@-1 {{cannot convert value of type 'Int' to expected argument type 'G<(P1.Q) -> Void>'}} + arg[invariantAssocSubscript6: 0] // expected-error {{member 'subscript' cannot be used on value of protocol type 'P1'; use a generic constraint instead}} + // expected-error@-1 {{cannot convert value of type 'Int' to expected argument type 'G<() -> P1.Q>'}} + // FIXME: Should be diagnosed. +// arg[invariantAssocSubscript7: 0] + } +} + +protocol P1_TypeMemberOnInstanceAndViceVersa { + static func static_covariantSelfMethod() -> Self + static var static_covariantSelfProp: Self { get } + static subscript(static_covariantSelfSubscript _: Void) -> Self { get } + + static func static_invariantSelfMethod() -> G + static var static_invariantSelfProp: G { get } + static subscript(static_invariantSelfSubscript _: Void) -> G { get } + + func covariantSelfMethod() -> Self + + func invariantSelfMethod() -> G + var invariantSelfProp: G { get } + subscript(invariantSelfSubscript _: Void) -> G { get } +} +do { + func test(protoMeta: P1_TypeMemberOnInstanceAndViceVersa.Protocol, + existMeta: P1_TypeMemberOnInstanceAndViceVersa.Type, + instance: P1_TypeMemberOnInstanceAndViceVersa) { + // P1_TypeMemberOnInstanceAndViceVersa.Protocol + // FIXME: These should be diagnosed as invalid references. + protoMeta.static_invariantSelfMethod() // expected-error {{member 'static_invariantSelfMethod' cannot be used on value of protocol type 'P1_TypeMemberOnInstanceAndViceVersa.Protocol'; use a generic constraint instead}} + protoMeta.static_invariantSelfProp // expected-error {{member 'static_invariantSelfProp' cannot be used on value of protocol type 'P1_TypeMemberOnInstanceAndViceVersa.Protocol'; use a generic constraint instead}} + protoMeta[static_invariantSelfSubscript: ()] // expected-error {{member 'subscript' cannot be used on value of protocol type 'P1_TypeMemberOnInstanceAndViceVersa.Protocol'; use a generic constraint instead}} + _ = protoMeta.covariantSelfMethod // ok + protoMeta.invariantSelfMethod // expected-error {{member 'invariantSelfMethod' cannot be used on value of protocol type 'P1_TypeMemberOnInstanceAndViceVersa.Protocol'; use a generic constraint instead}} + // FIXME: These should be diagnosed as invalid references. + protoMeta.invariantSelfProp // expected-error {{member 'invariantSelfProp' cannot be used on value of protocol type 'P1_TypeMemberOnInstanceAndViceVersa.Protocol'; use a generic constraint instead}} + protoMeta[invariantSelfSubscript: ()] // expected-error {{member 'subscript' cannot be used on value of protocol type 'P1_TypeMemberOnInstanceAndViceVersa.Protocol'; use a generic constraint instead}} + + // P1_TypeMemberOnInstanceAndViceVersa.Type + _ = existMeta.static_covariantSelfMethod // ok + _ = existMeta.static_covariantSelfProp // ok + _ = existMeta[static_covariantSelfSubscript: ()] // ok + existMeta.static_invariantSelfMethod // expected-error {{member 'static_invariantSelfMethod' cannot be used on value of protocol type 'P1_TypeMemberOnInstanceAndViceVersa.Type'; use a generic constraint instead}} + existMeta.static_invariantSelfProp // expected-error {{member 'static_invariantSelfProp' cannot be used on value of protocol type 'P1_TypeMemberOnInstanceAndViceVersa.Type'; use a generic constraint instead}} + existMeta[static_invariantSelfSubscript: ()] // expected-error {{member 'subscript' cannot be used on value of protocol type 'P1_TypeMemberOnInstanceAndViceVersa.Type'; use a generic constraint instead}} + // FIXME: These should be diagnosed as invalid references. + existMeta.invariantSelfMethod // expected-error {{member 'invariantSelfMethod' cannot be used on value of protocol type 'P1_TypeMemberOnInstanceAndViceVersa.Type'; use a generic constraint instead}} + existMeta.invariantSelfProp // expected-error {{member 'invariantSelfProp' cannot be used on value of protocol type 'P1_TypeMemberOnInstanceAndViceVersa.Type'; use a generic constraint instead}} + existMeta[invariantSelfSubscript: ()] // expected-error {{member 'subscript' cannot be used on value of protocol type 'P1_TypeMemberOnInstanceAndViceVersa.Type'; use a generic constraint instead}} + + // P1_TypeMemberOnInstanceAndViceVersa + // FIXME: These should be diagnosed as invalid references. + instance.static_invariantSelfMethod // expected-error {{member 'static_invariantSelfMethod' cannot be used on value of protocol type 'P1_TypeMemberOnInstanceAndViceVersa'; use a generic constraint instead}} + instance.static_invariantSelfProp // expected-error {{member 'static_invariantSelfProp' cannot be used on value of protocol type 'P1_TypeMemberOnInstanceAndViceVersa'; use a generic constraint instead}} + instance[static_invariantSelfSubscript: ()] // expected-error {{member 'subscript' cannot be used on value of protocol type 'P1_TypeMemberOnInstanceAndViceVersa'; use a generic constraint instead}} + } +} diff --git a/test/decl/protocol/protocols_with_self_or_assoc_reqs_executable.swift b/test/decl/protocol/protocols_with_self_or_assoc_reqs_executable.swift new file mode 100644 index 0000000000000..58aa147a3ebe9 --- /dev/null +++ b/test/decl/protocol/protocols_with_self_or_assoc_reqs_executable.swift @@ -0,0 +1,107 @@ +// RUN: %target-run-simple-swift +// REQUIRES: executable_test + +import StdlibUnittest + +let Tests = TestSuite(#file) + +protocol P { + associatedtype Assoc = Self + + func getString() -> String + + func covariantSelfSimple() -> Self + func covariantSelfArray() -> Array + func covariantSelfDictionary() -> [String : Self] + func covariantSelfClosure(_: (Self) -> Void) + + var covariantSelfPropSimple: Self { get } + var covariantSelfPropArray: Array { get } + var covariantSelfPropDictionary: [String : Self] { get } + var covariantSelfPropClosure: ((Self) -> Void) -> Void { get } + + subscript(covariantSelfSubscriptSimple _: Void) -> Self { get } + subscript(covariantSelfSubscriptArray _: Void) -> Array { get } + subscript(covariantSelfSubscriptDictionary _: Void) -> [String : Self] { get } + subscript(covariantSelfSubscriptClosure _: (Self) -> Void) -> Void { get } +} +extension P { + func covariantSelfSimple() -> Self { self } + func covariantSelfArray() -> Array { [self] } + func covariantSelfDictionary() -> [String : Self] { [#file : self] } + func covariantSelfClosure(_ arg: (Self) -> Void) { arg(self) } + + var covariantSelfPropSimple: Self { self } + var covariantSelfPropArray: Array { [self] } + var covariantSelfPropDictionary: [String : Self] { [#file : self] } + var covariantSelfPropClosure: ((Self) -> Void) -> Void { { $0(self) } } + + subscript(covariantSelfSubscriptSimple _: Void) -> Self { self } + subscript(covariantSelfSubscriptArray _: Void) -> Array { [self] } + subscript(covariantSelfSubscriptDictionary _: Void) -> [String : Self] { [#file : self] } + subscript(covariantSelfSubscriptClosure arg: (Self) -> Void) -> Void { arg(self) } +} + +Tests.test("Basic") { + let collection: Collection = [0, 0, 0] + + expectEqual(3, collection.count) +} + +Tests.test("Covariant 'Self' erasure") { + struct S: P { + static let str = "Success" + func getString() -> String { Self.str } + } + + let p: P = S() + + // Partial Application + do { + let covariantSelfSimplePartialApp = p.covariantSelfSimple + let covariantSelfArrayPartialApp = p.covariantSelfArray + let covariantSelfDictionaryPartialApp = p.covariantSelfDictionary + let covariantSelfClosurePartialApp = p.covariantSelfClosure + + expectEqual(S.str, covariantSelfSimplePartialApp().getString()) + expectEqual(S.str, covariantSelfArrayPartialApp().first.unsafelyUnwrapped.getString()) + expectEqual(S.str, covariantSelfDictionaryPartialApp()[#file].unsafelyUnwrapped.getString()) + covariantSelfClosurePartialApp { expectEqual(S.str, $0.getString()) } + } + + // Instance method reference on metatype + do { + let covariantSelfSimpleRef = P.covariantSelfSimple + let covariantSelfArrayRef = P.covariantSelfArray + let covariantSelfDictionaryRef = P.covariantSelfDictionary + let covariantSelfClosureRef = P.covariantSelfClosure + + expectEqual(S.str, covariantSelfSimpleRef(p)().getString()) + expectEqual(S.str, covariantSelfArrayRef(p)().first.unsafelyUnwrapped.getString()) + expectEqual(S.str, covariantSelfDictionaryRef(p)()[#file].unsafelyUnwrapped.getString()) + covariantSelfClosureRef(p)({ expectEqual(S.str, $0.getString()) }) + } + + // Regular calls + expectEqual(S.str, p.covariantSelfSimple().getString()) + expectEqual(S.str, p.covariantSelfArray().first.unsafelyUnwrapped.getString()) + expectEqual(S.str, p.covariantSelfDictionary()[#file].unsafelyUnwrapped.getString()) + p.covariantSelfClosure { expectEqual(S.str, $0.getString()) } + + expectEqual(S.str, p.covariantSelfPropSimple.getString()) + expectEqual(S.str, p.covariantSelfPropArray.first.unsafelyUnwrapped.getString()) + expectEqual(S.str, p.covariantSelfPropDictionary[#file].unsafelyUnwrapped.getString()) + p.covariantSelfPropClosure { expectEqual(S.str, $0.getString()) } + + expectEqual(S.str, p[covariantSelfSubscriptSimple: ()].getString()) + expectEqual(S.str, p[covariantSelfSubscriptArray: ()].first.unsafelyUnwrapped.getString()) + expectEqual(S.str, p[covariantSelfSubscriptDictionary: ()][#file].unsafelyUnwrapped.getString()) + p[covariantSelfSubscriptClosure: { expectEqual(S.str, $0.getString()) }] + + expectEqual(S.str, (S() as P).getString()) + + expectEqual(true, p is P) + expectEqual(true, S() is P) +} + +runAllTests() From 396087d0d42c83410131971109df1af38d95667f Mon Sep 17 00:00:00 2001 From: Suyash Srijan Date: Wed, 2 Sep 2020 21:50:34 +0100 Subject: [PATCH 04/10] [Test] Update existing tests --- ...mbers_on_protocol_in_generic_context.swift | 18 -------- test/Generics/function_defs.swift | 8 ++-- test/Sema/existential_nested_type.swift | 2 +- test/decl/nested/protocol.swift | 3 +- test/decl/nested/type_in_function.swift | 3 +- test/decl/protocol/conforms/inherited.swift | 10 ++--- test/decl/protocol/protocols.swift | 20 ++++----- .../decl/protocol/recursive_requirement.swift | 6 +-- test/decl/protocol/req/dynamic_self.swift | 18 +------- test/stmt/foreach.swift | 4 +- test/type/protocol_types.swift | 45 ++++++------------- 11 files changed, 42 insertions(+), 95 deletions(-) diff --git a/test/Constraints/static_members_on_protocol_in_generic_context.swift b/test/Constraints/static_members_on_protocol_in_generic_context.swift index d9f342729509a..0516e08d92dc4 100644 --- a/test/Constraints/static_members_on_protocol_in_generic_context.swift +++ b/test/Constraints/static_members_on_protocol_in_generic_context.swift @@ -265,24 +265,6 @@ test_combo(.genericWithReqs([42])) test_combo(.genericWithReqs(())) // expected-error@-1 {{contextual member reference to static method 'genericWithReqs' requires 'Self' constraint in the protocol extension}} -protocol Z { - associatedtype T = Int - - static var prop: T { get } -} - -extension Z { - static func method() -> T { fatalError() } -} - -_ = Z.prop -// expected-error@-1 {{member 'prop' cannot be used on value of protocol type 'Z.Protocol'; use a generic constraint instead}} -// expected-error@-2 {{protocol 'Z' can only be used as a generic constraint because it has Self or associated type requirements}} - -_ = Z.method() -// expected-error@-1 {{member 'method' cannot be used on value of protocol type 'Z.Protocol'; use a generic constraint instead}} -// expected-error@-2 {{protocol 'Z' can only be used as a generic constraint because it has Self or associated type requirements}} - protocol TestWithAssoc { associatedtype U } diff --git a/test/Generics/function_defs.swift b/test/Generics/function_defs.swift index 5b83dba7d8c0c..fe4cfa9a6ed07 100644 --- a/test/Generics/function_defs.swift +++ b/test/Generics/function_defs.swift @@ -34,7 +34,7 @@ func min(_ x: T, y: T) -> T { //===----------------------------------------------------------------------===// func existential(_ t1: T, t2: T, u: U) { - var eqComp : EqualComparable = t1 // expected-error{{protocol 'EqualComparable' can only be used as a generic constraint}} + var eqComp : EqualComparable = t1 // Ok eqComp = u if t1.isEqual(eqComp) {} // expected-error{{cannot convert value of type 'EqualComparable' to expected argument type 'T'}} if eqComp.isEqual(t2) {} // expected-error{{member 'isEqual' cannot be used on value of protocol type 'EqualComparable'; use a generic constraint instead}} @@ -49,11 +49,11 @@ func otherExistential(_ t1: T) { otherEqComp = t1 // expected-error{{value of type 'T' does not conform to 'OtherEqualComparable' in assignment}} _ = otherEqComp - var otherEqComp2 : OtherEqualComparable // expected-error{{protocol 'OtherEqualComparable' can only be used as a generic constraint}} + var otherEqComp2 : OtherEqualComparable // Ok otherEqComp2 = t1 // expected-error{{value of type 'T' does not conform to 'OtherEqualComparable' in assignment}} _ = otherEqComp2 - _ = t1 as EqualComparable & OtherEqualComparable // expected-error{{value of type 'T' does not conform to 'EqualComparable & OtherEqualComparable' in coercion}} expected-error{{protocol 'OtherEqualComparable' can only be used as a generic constraint}} expected-error{{protocol 'EqualComparable' can only be used as a generic constraint}} + _ = t1 as EqualComparable & OtherEqualComparable // expected-error{{value of type 'T' does not conform to 'EqualComparable & OtherEqualComparable' in coercion}} } protocol Runcible { @@ -61,7 +61,7 @@ protocol Runcible { func spoon(_ x: Self) } -func testRuncible(_ x: Runcible) { // expected-error{{protocol 'Runcible' can only be used as a generic constraint}} +func testRuncible(_ x: Runcible) { // Ok x.runce(5) } diff --git a/test/Sema/existential_nested_type.swift b/test/Sema/existential_nested_type.swift index 8189415c1f70e..cfc8f72c9d93e 100644 --- a/test/Sema/existential_nested_type.swift +++ b/test/Sema/existential_nested_type.swift @@ -15,7 +15,7 @@ enum MyError : Error { func checkIt(_ js: Any) throws { switch js { - case let dbl as HasAssoc: // expected-error {{protocol 'HasAssoc' can only be used as a generic constraint because it has Self or associated type requirements}} + case let dbl as HasAssoc: // Ok throw MyError.bad(dbl) default: diff --git a/test/decl/nested/protocol.swift b/test/decl/nested/protocol.swift index 2ccc15b74e9a3..ab0427513619a 100644 --- a/test/decl/nested/protocol.swift +++ b/test/decl/nested/protocol.swift @@ -31,8 +31,7 @@ protocol OuterProtocol { struct ConformsToOuterProtocol : OuterProtocol { typealias Hen = Int - func f() { let _ = InnerProtocol.self } - // expected-error@-1 {{protocol 'InnerProtocol' can only be used as a generic constraint because it has Self or associated type requirements}} + func f() { let _ = InnerProtocol.self } // Ok } protocol Racoon { diff --git a/test/decl/nested/type_in_function.swift b/test/decl/nested/type_in_function.swift index 7fa1c325d4b60..c01d7efca13d0 100644 --- a/test/decl/nested/type_in_function.swift +++ b/test/decl/nested/type_in_function.swift @@ -144,8 +144,7 @@ func freeFunction() { struct ConformingType : ProtoWithAssocType { typealias T = Int - func method() -> ProtoWithAssocType {} - // expected-error@-1 {{can only be used as a generic constraint because it has Self or associated type requirements}} + func method() -> ProtoWithAssocType {} // Ok } } diff --git a/test/decl/protocol/conforms/inherited.swift b/test/decl/protocol/conforms/inherited.swift index 75c4c5de1aa21..33e50e5ee418b 100644 --- a/test/decl/protocol/conforms/inherited.swift +++ b/test/decl/protocol/conforms/inherited.swift @@ -167,13 +167,13 @@ class B : A { } func testB(_ b: B) { - var _: P1 = b // expected-error{{has Self or associated type requirements}} - var _: P4 = b // expected-error{{has Self or associated type requirements}} + var _: P1 = b + var _: P4 = b var _: P5 = b var _: P6 = b - var _: P7 = b // expected-error{{has Self or associated type requirements}} - var _: P8 = b // okay - var _: P9 = b // expected-error{{has Self or associated type requirements}} + var _: P7 = b + var _: P8 = b + var _: P9 = b } // Class A5 conforms to P5 in an inheritable manner. diff --git a/test/decl/protocol/protocols.swift b/test/decl/protocol/protocols.swift index 0a2d9c5e48b39..9cee54070abfa 100644 --- a/test/decl/protocol/protocols.swift +++ b/test/decl/protocol/protocols.swift @@ -102,10 +102,10 @@ struct DoesNotConform : Up { // Circular protocols protocol CircleMiddle : CircleStart { func circle_middle() } // expected-error {{protocol 'CircleMiddle' refines itself}} -// expected-note@-1 2 {{protocol 'CircleMiddle' declared here}} -protocol CircleStart : CircleEnd { func circle_start() } // expected-error 2 {{protocol 'CircleStart' refines itself}} +// expected-note@-1 {{protocol 'CircleMiddle' declared here}} +protocol CircleStart : CircleEnd { func circle_start() } // expected-error {{protocol 'CircleStart' refines itself}} // expected-note@-1 {{protocol 'CircleStart' declared here}} -protocol CircleEnd : CircleMiddle { func circle_end()} // expected-note 3 {{protocol 'CircleEnd' declared here}} +protocol CircleEnd : CircleMiddle { func circle_end()} // expected-note 2 {{protocol 'CircleEnd' declared here}} protocol CircleEntry : CircleTrivial { } protocol CircleTrivial : CircleTrivial { } // expected-error {{protocol 'CircleTrivial' refines itself}} @@ -267,7 +267,7 @@ struct WrongIsEqual : IsEqualComparable { // expected-error{{type 'WrongIsEqual' // Using values of existential type. //===----------------------------------------------------------------------===// -func existentialSequence(_ e: Sequence) { // expected-error{{has Self or associated type requirements}} +func existentialSequence(_ e: Sequence) { var x = e.makeIterator() // expected-error{{member 'makeIterator' cannot be used on value of protocol type 'Sequence'; use a generic constraint instead}} x.next() x.nonexistent() @@ -278,7 +278,7 @@ protocol HasSequenceAndStream { func getR() -> R } -func existentialSequenceAndStreamType(_ h: HasSequenceAndStream) { // expected-error{{has Self or associated type requirements}} +func existentialSequenceAndStreamType(_ h: HasSequenceAndStream) { // FIXME: Crummy diagnostics. var x = h.getR() // expected-error{{member 'getR' cannot be used on value of protocol type 'HasSequenceAndStream'; use a generic constraint instead}} x.makeIterator() @@ -307,7 +307,7 @@ struct DictionaryIntInt { } } -func testSubscripting(_ iis: IntIntSubscriptable, i_s: IntSubscriptable) { // expected-error{{has Self or associated type requirements}} +func testSubscripting(_ iis: IntIntSubscriptable, i_s: IntSubscriptable) { // Ok var i: Int = iis[17] var i2 = i_s[17] // expected-error{{member 'subscript' cannot be used on value of protocol type 'IntSubscriptable'; use a generic constraint instead}} } @@ -488,18 +488,18 @@ func g(_ x : T) { class C3 : P1 {} // expected-error{{type 'C3' does not conform to protocol 'P1'}} func h(_ x : T) { - _ = x as P1 // expected-error{{protocol 'P1' can only be used as a generic constraint because it has Self or associated type requirements}} + _ = x as P1 } func i(_ x : T?) -> Bool { - return x is P1 // expected-error{{protocol 'P1' can only be used as a generic constraint because it has Self or associated type requirements}} + return x is P1 // FIXME: Bogus diagnostic. See SR-11920. // expected-warning@-2 {{checking a value with optional type 'T?' against dynamic type 'P1' succeeds whenever the value is non-nil; did you mean to use '!= nil'?}} } func j(_ x : C1) -> Bool { - return x is P1 // expected-error{{protocol 'P1' can only be used as a generic constraint because it has Self or associated type requirements}} + return x is P1 } func k(_ x : C1?) -> Bool { - return x is P1 // expected-error{{protocol 'P1' can only be used as a generic constraint because it has Self or associated type requirements}} + return x is P1 } diff --git a/test/decl/protocol/recursive_requirement.swift b/test/decl/protocol/recursive_requirement.swift index fd6ee93d412ae..c99dadbb6b4bd 100644 --- a/test/decl/protocol/recursive_requirement.swift +++ b/test/decl/protocol/recursive_requirement.swift @@ -91,7 +91,7 @@ protocol AsExistentialB { } protocol AsExistentialAssocTypeA { - var delegate : AsExistentialAssocTypeB? { get } // expected-error {{protocol 'AsExistentialAssocTypeB' can only be used as a generic constraint because it has Self or associated type requirements}} + var delegate : AsExistentialAssocTypeB? { get } } protocol AsExistentialAssocTypeB { func aMethod(_ object : AsExistentialAssocTypeA) @@ -103,7 +103,7 @@ protocol AsExistentialAssocTypeAgainA { associatedtype Bar } protocol AsExistentialAssocTypeAgainB { - func aMethod(_ object : AsExistentialAssocTypeAgainA) // expected-error {{protocol 'AsExistentialAssocTypeAgainA' can only be used as a generic constraint because it has Self or associated type requirements}} + func aMethod(_ object : AsExistentialAssocTypeAgainA) } // SR-547 @@ -124,5 +124,3 @@ protocol B { func observeChangeOfProperty(_ property: BC, observable: BA) } - - diff --git a/test/decl/protocol/req/dynamic_self.swift b/test/decl/protocol/req/dynamic_self.swift index ef4f33a100b1d..110ee0e0d600f 100644 --- a/test/decl/protocol/req/dynamic_self.swift +++ b/test/decl/protocol/req/dynamic_self.swift @@ -87,22 +87,8 @@ enum EError : P { // expected-error{{type 'EError' does not conform to protocol func f() -> Int { 0 } // expected-note{{candidate has non-matching type '() -> Int'}} } - -// Settable storage declaration requirements with a 'Self' result type may not -// be used with an existential base. -protocol P2 { - subscript() -> Self { get set } -} -protocol P3 { - var prop: Self { get set } -} -protocol P4 { - subscript() -> T where T.Element == Self { get set } -} -func takesP2P3P4(p2: P2, p3: P3, p4: P4) { } -// expected-error@-1{{protocol 'P2' can only be used as a generic constraint because it has Self or associated type requirements}} -// expected-error@-2{{protocol 'P3' can only be used as a generic constraint because it has Self or associated type requirements}} - +// Settable storage members with a 'Self' result type may not be used with an +// existential base. protocol P5 { } extension P5 { diff --git a/test/stmt/foreach.swift b/test/stmt/foreach.swift index 20ddf6add1cfd..e3c3d6a3cb6eb 100644 --- a/test/stmt/foreach.swift +++ b/test/stmt/foreach.swift @@ -175,8 +175,8 @@ func testOptionalSequence() { } } -// Crash with (invalid) for each over an existential -func testExistentialSequence(s: Sequence) { // expected-error {{protocol 'Sequence' can only be used as a generic constraint because it has Self or associated type requirements}} +// FIXME: Should this be allowed? +func testExistentialSequence(s: Sequence) { for x in s { // expected-error {{protocol 'Sequence' as a type cannot conform to the protocol itself}} expected-note {{only concrete types such as structs, enums and classes can conform to protocols}} _ = x } diff --git a/test/type/protocol_types.swift b/test/type/protocol_types.swift index 840dd52b3a311..97066e8769bbf 100644 --- a/test/type/protocol_types.swift +++ b/test/type/protocol_types.swift @@ -3,7 +3,7 @@ protocol HasSelfRequirements { func foo(_ x: Self) - func returnsOwnProtocol() -> HasSelfRequirements // expected-error{{protocol 'HasSelfRequirements' can only be used as a generic constraint because it has Self or associated type requirements}} {{educational-notes=associated-type-requirements}} + func returnsOwnProtocol() -> HasSelfRequirements } protocol Bar { // init() methods should not prevent use as an existential. @@ -36,10 +36,10 @@ func useCompoAsWhereRequirement(_ x: T) where T: HasSelfRequirements & Bar {} func useCompoAliasAsWhereRequirement(_ x: T) where T: Compo {} func useNestedCompoAliasAsWhereRequirement(_ x: T) where T: CompoAssocType.Compo {} -func useAsType(_ x: HasSelfRequirements) { } // expected-error{{protocol 'HasSelfRequirements' can only be used as a generic constraint}} -func useCompoAsType(_ x: HasSelfRequirements & Bar) { } // expected-error{{protocol 'HasSelfRequirements' can only be used as a generic constraint}} -func useCompoAliasAsType(_ x: Compo) { } // expected-error{{protocol 'HasSelfRequirements' can only be used as a generic constraint}} -func useNestedCompoAliasAsType(_ x: CompoAssocType.Compo) { } // expected-error{{protocol 'HasSelfRequirements' can only be used as a generic constraint}} +func useAsType(_: HasSelfRequirements, + _: HasSelfRequirements & Bar, + _: Compo, + _: CompoAssocType.Compo) { } struct TypeRequirement {} struct CompoTypeRequirement {} @@ -67,29 +67,20 @@ protocol HasAssoc { func foo() } -func testHasAssoc(_ x: Any) { - if let p = x as? HasAssoc { // expected-error {{protocol 'HasAssoc' can only be used as a generic constraint}} {{educational-notes=associated-type-requirements}} +func testHasAssoc(_ x: Any, _: HasAssoc) { + if let p = x as? HasAssoc { p.foo() // don't crash here. } } -// rdar://problem/16803384 -protocol InheritsAssoc : HasAssoc { - func silverSpoon() -} - -func testInheritsAssoc(_ x: InheritsAssoc) { // expected-error {{protocol 'InheritsAssoc' can only be used as a generic constraint}} - x.silverSpoon() -} - // SR-38 -var b: HasAssoc // expected-error {{protocol 'HasAssoc' can only be used as a generic constraint because it has Self or associated type requirements}} +var b: HasAssoc // Further generic constraint error testing - typealias used inside statements protocol P {} typealias MoreHasAssoc = HasAssoc & P func testHasMoreAssoc(_ x: Any) { - if let p = x as? MoreHasAssoc { // expected-error {{protocol 'HasAssoc' can only be used as a generic constraint}} + if let p = x as? MoreHasAssoc { p.foo() // don't crash here. } } @@ -103,37 +94,30 @@ struct Outer { typealias X = Struct1 _ = Struct1.self -typealias BadAlias = T +typealias AliasWhere = T where T : HasAssoc, T.Assoc == HasAssoc -// expected-error@-1 {{protocol 'HasAssoc' can only be used as a generic constraint because it has Self or associated type requirements}} -struct BadStruct +struct StructWhere where T : HasAssoc, T.Assoc == HasAssoc {} -// expected-error@-1 {{protocol 'HasAssoc' can only be used as a generic constraint because it has Self or associated type requirements}} -protocol BadProtocol where T == HasAssoc { - // expected-error@-1 {{protocol 'HasAssoc' can only be used as a generic constraint because it has Self or associated type requirements}} +protocol ProtocolWhere where T == HasAssoc { associatedtype T associatedtype U : HasAssoc where U.Assoc == HasAssoc - // expected-error@-1 {{protocol 'HasAssoc' can only be used as a generic constraint because it has Self or associated type requirements}} } extension HasAssoc where Assoc == HasAssoc {} -// expected-error@-1 {{protocol 'HasAssoc' can only be used as a generic constraint because it has Self or associated type requirements}} -func badFunction(_: T) +func FunctionWhere(_: T) where T : HasAssoc, T.Assoc == HasAssoc {} -// expected-error@-1 {{protocol 'HasAssoc' can only be used as a generic constraint because it has Self or associated type requirements}} -struct BadSubscript { +struct SubscriptWhere { subscript(_: T) -> Int where T : HasAssoc, T.Assoc == HasAssoc { - // expected-error@-1 {{protocol 'HasAssoc' can only be used as a generic constraint because it has Self or associated type requirements}} get {} set {} } @@ -141,5 +125,4 @@ struct BadSubscript { struct OuterGeneric { func contextuallyGenericMethod() where T == HasAssoc {} - // expected-error@-1 {{protocol 'HasAssoc' can only be used as a generic constraint because it has Self or associated type requirements}} } From c2e5d04669aaec957a6347dff87229056973408f Mon Sep 17 00:00:00 2001 From: Anthony Latsis Date: Fri, 13 Aug 2021 01:45:49 +0300 Subject: [PATCH 05/10] Test: Find better locations for some updated tests --- test/Generics/function_defs.swift | 9 ---- test/Sema/existential_nested_type.swift | 24 --------- test/decl/nested/type_in_function.swift | 13 ----- test/decl/protocol/protocols.swift | 49 ------------------- .../protocols_with_self_or_assoc_reqs.swift | 48 ++++++++++++++++++ test/decl/protocol/req/dynamic_self.swift | 22 --------- test/type/protocol_types.swift | 23 +++++++++ 7 files changed, 71 insertions(+), 117 deletions(-) delete mode 100644 test/Sema/existential_nested_type.swift diff --git a/test/Generics/function_defs.swift b/test/Generics/function_defs.swift index fe4cfa9a6ed07..8b5d8499ebfa3 100644 --- a/test/Generics/function_defs.swift +++ b/test/Generics/function_defs.swift @@ -56,15 +56,6 @@ func otherExistential(_ t1: T) { _ = t1 as EqualComparable & OtherEqualComparable // expected-error{{value of type 'T' does not conform to 'EqualComparable & OtherEqualComparable' in coercion}} } -protocol Runcible { - func runce(_ x: A) - func spoon(_ x: Self) -} - -func testRuncible(_ x: Runcible) { // Ok - x.runce(5) -} - //===----------------------------------------------------------------------===// // Overloading //===----------------------------------------------------------------------===// diff --git a/test/Sema/existential_nested_type.swift b/test/Sema/existential_nested_type.swift deleted file mode 100644 index cfc8f72c9d93e..0000000000000 --- a/test/Sema/existential_nested_type.swift +++ /dev/null @@ -1,24 +0,0 @@ -// RUN: %target-swift-frontend -typecheck -verify -swift-version 4 %s - -// rdar://29605388 -- Swift 3 admitted opening an existential type with -// associated types in one case. - -// See test/IRGen/existential_nested_type.swift for the Swift 3 test. - -protocol HasAssoc { - associatedtype A -} - -enum MyError : Error { - case bad(Any) -} - -func checkIt(_ js: Any) throws { - switch js { - case let dbl as HasAssoc: // Ok - throw MyError.bad(dbl) - - default: - fatalError("wrong") - } -} diff --git a/test/decl/nested/type_in_function.swift b/test/decl/nested/type_in_function.swift index c01d7efca13d0..3908dad939434 100644 --- a/test/decl/nested/type_in_function.swift +++ b/test/decl/nested/type_in_function.swift @@ -135,19 +135,6 @@ func genericFunction(t: T) { // expected-error@-2 {{'Second' inherits from itself}} } -// Spurious "Self or associated type requirements" diagnostic. -protocol ProtoWithAssocType { - associatedtype T = Int -} - -func freeFunction() { - struct ConformingType : ProtoWithAssocType { - typealias T = Int - - func method() -> ProtoWithAssocType {} // Ok - } -} - // Superclass lookup archetype vs interface type mixup class Generic { struct Nested {} diff --git a/test/decl/protocol/protocols.swift b/test/decl/protocol/protocols.swift index 9cee54070abfa..6689695102b62 100644 --- a/test/decl/protocol/protocols.swift +++ b/test/decl/protocol/protocols.swift @@ -263,55 +263,6 @@ struct WrongIsEqual : IsEqualComparable { // expected-error{{type 'WrongIsEqual' func isEqual(other: Int) -> Bool {} // expected-note{{candidate has non-matching type '(Int) -> Bool'}} } -//===----------------------------------------------------------------------===// -// Using values of existential type. -//===----------------------------------------------------------------------===// - -func existentialSequence(_ e: Sequence) { - var x = e.makeIterator() // expected-error{{member 'makeIterator' cannot be used on value of protocol type 'Sequence'; use a generic constraint instead}} - x.next() - x.nonexistent() -} - -protocol HasSequenceAndStream { - associatedtype R : IteratorProtocol, Sequence - func getR() -> R -} - -func existentialSequenceAndStreamType(_ h: HasSequenceAndStream) { - // FIXME: Crummy diagnostics. - var x = h.getR() // expected-error{{member 'getR' cannot be used on value of protocol type 'HasSequenceAndStream'; use a generic constraint instead}} - x.makeIterator() - x.next() - - x.nonexistent() -} - -//===----------------------------------------------------------------------===// -// Subscripting -//===----------------------------------------------------------------------===// -protocol IntIntSubscriptable { - subscript (i: Int) -> Int { get } -} - -protocol IntSubscriptable { - associatedtype Element - subscript (i: Int) -> Element { get } -} - -struct DictionaryIntInt { - subscript (i: Int) -> Int { - get { - return i - } - } -} - -func testSubscripting(_ iis: IntIntSubscriptable, i_s: IntSubscriptable) { // Ok - var i: Int = iis[17] - var i2 = i_s[17] // expected-error{{member 'subscript' cannot be used on value of protocol type 'IntSubscriptable'; use a generic constraint instead}} -} - //===----------------------------------------------------------------------===// // Static methods //===----------------------------------------------------------------------===// diff --git a/test/decl/protocol/protocols_with_self_or_assoc_reqs.swift b/test/decl/protocol/protocols_with_self_or_assoc_reqs.swift index 6ab23577f781d..e6a7dfc935470 100644 --- a/test/decl/protocol/protocols_with_self_or_assoc_reqs.swift +++ b/test/decl/protocol/protocols_with_self_or_assoc_reqs.swift @@ -470,3 +470,51 @@ do { instance[static_invariantSelfSubscript: ()] // expected-error {{member 'subscript' cannot be used on value of protocol type 'P1_TypeMemberOnInstanceAndViceVersa'; use a generic constraint instead}} } } + +// Settable storage members with a 'Self' result type may not be used with an +// existential base. +protocol P2 { + subscript() -> Self { get set } + + var prop: Self { get set } +} +func takesP2(p2: P2) { + _ = p2[] + // expected-error@-1{{member 'subscript' cannot be used on value of protocol type 'P2'; use a generic constraint instead}} + _ = p2.prop + // expected-error@-1{{member 'prop' cannot be used on value of protocol type 'P2'; use a generic constraint instead}} +} + +protocol MiscTestsProto { + associatedtype Assoc + func runce(_: A) + func spoon(_: Self) + + associatedtype R : IteratorProtocol, Sequence + func getR() -> R + + subscript(intToAssoc _: Int) -> Assoc { get } + subscript(intToInt _: Int) -> Int { get } +} +do { + func miscTests(_ arg: MiscTestsProto) { // ok + arg.runce(5) + + do { + // FIXME: Crummy diagnostics. + var x = arg.getR() // expected-error{{member 'getR' cannot be used on value of protocol type 'MiscTestsProto'; use a generic constraint instead}} + x.makeIterator() + x.next() + x.nonexistent() + } + + var _: Int = arg[intToInt: 17] + _ = arg[intToAssoc: 17] // expected-error{{member 'subscript' cannot be used on value of protocol type 'MiscTestsProto'; use a generic constraint instead}} + } + + func existentialSequence(_ e: Sequence) { + var x = e.makeIterator() // expected-error{{member 'makeIterator' cannot be used on value of protocol type 'Sequence'; use a generic constraint instead}} + x.next() + x.nonexistent() + } +} diff --git a/test/decl/protocol/req/dynamic_self.swift b/test/decl/protocol/req/dynamic_self.swift index 110ee0e0d600f..758a301ef6f22 100644 --- a/test/decl/protocol/req/dynamic_self.swift +++ b/test/decl/protocol/req/dynamic_self.swift @@ -86,25 +86,3 @@ enum EError : P { // expected-error{{type 'EError' does not conform to protocol subscript() -> Int { 0 } // expected-note{{candidate has non-matching type '() -> Int'}} func f() -> Int { 0 } // expected-note{{candidate has non-matching type '() -> Int'}} } - -// Settable storage members with a 'Self' result type may not be used with an -// existential base. -protocol P5 { -} -extension P5 { - var prop: Self { - get { self } - set { } - } - - subscript() -> Self { - get { self } - set { } - } -} -func takesP5(p5: P5) { - _ = p5[] - // expected-error@-1{{member 'subscript' cannot be used on value of protocol type 'P5'; use a generic constraint instead}} - _ = p5.prop - // expected-error@-1{{member 'prop' cannot be used on value of protocol type 'P5'; use a generic constraint instead}} -} diff --git a/test/type/protocol_types.swift b/test/type/protocol_types.swift index 97066e8769bbf..d2d02dd612a3b 100644 --- a/test/type/protocol_types.swift +++ b/test/type/protocol_types.swift @@ -67,10 +67,33 @@ protocol HasAssoc { func foo() } +do { + enum MyError : Error { + case bad(Any) + } + + func checkIt(_ js: Any) throws { + switch js { + case let dbl as HasAssoc: + throw MyError.bad(dbl) + + default: + fatalError("wrong") + } + } +} + func testHasAssoc(_ x: Any, _: HasAssoc) { if let p = x as? HasAssoc { p.foo() // don't crash here. } + + struct ConformingType : HasAssoc { + typealias Assoc = Int + func foo() {} + + func method() -> HasAssoc {} + } } // SR-38 From 15f88e9be3ad84b4c9831975a2acb1f1ddc442de Mon Sep 17 00:00:00 2001 From: Suyash Srijan Date: Thu, 3 Sep 2020 00:06:24 +0100 Subject: [PATCH 06/10] [NFC, Typechecker] Remove UnsupportedProtocolVisitor and checkUnsupportedProtocolType() --- lib/Sema/MiscDiagnostics.cpp | 4 - lib/Sema/TypeCheckDeclPrimary.cpp | 2 - lib/Sema/TypeCheckType.cpp | 122 ------------------------------ lib/Sema/TypeChecker.h | 16 ---- 4 files changed, 144 deletions(-) diff --git a/lib/Sema/MiscDiagnostics.cpp b/lib/Sema/MiscDiagnostics.cpp index 8e425b4d589f5..28fdbcdc60cde 100644 --- a/lib/Sema/MiscDiagnostics.cpp +++ b/lib/Sema/MiscDiagnostics.cpp @@ -3329,8 +3329,6 @@ static void checkSwitch(ASTContext &ctx, const SwitchStmt *stmt) { // We want to warn about "case .Foo, .Bar where 1 != 100:" since the where // clause only applies to the second case, and this is surprising. for (auto cs : stmt->getCases()) { - TypeChecker::checkUnsupportedProtocolType(ctx, cs); - // The case statement can have multiple case items, each can have a where. // If we find a "where", and there is a preceding item without a where, and // if they are on the same source line, then warn. @@ -4747,8 +4745,6 @@ void swift::performSyntacticExprDiagnostics(const Expr *E, void swift::performStmtDiagnostics(const Stmt *S, DeclContext *DC) { auto &ctx = DC->getASTContext(); - TypeChecker::checkUnsupportedProtocolType(ctx, const_cast(S)); - if (auto switchStmt = dyn_cast(S)) checkSwitch(ctx, switchStmt); diff --git a/lib/Sema/TypeCheckDeclPrimary.cpp b/lib/Sema/TypeCheckDeclPrimary.cpp index 1f4c1b4eba1b4..e2b21faafbf2b 100644 --- a/lib/Sema/TypeCheckDeclPrimary.cpp +++ b/lib/Sema/TypeCheckDeclPrimary.cpp @@ -1659,8 +1659,6 @@ class DeclChecker : public DeclVisitor { DeclVisitor::visit(decl); - TypeChecker::checkUnsupportedProtocolType(decl); - if (auto VD = dyn_cast(decl)) { auto &Context = getASTContext(); TypeChecker::checkForForbiddenPrefix(Context, VD->getBaseName()); diff --git a/lib/Sema/TypeCheckType.cpp b/lib/Sema/TypeCheckType.cpp index 8bd0e193b0e20..078cd050f5ef8 100644 --- a/lib/Sema/TypeCheckType.cpp +++ b/lib/Sema/TypeCheckType.cpp @@ -3949,128 +3949,6 @@ Type TypeChecker::substMemberTypeWithBase(ModuleDecl *module, return resultType; } -namespace { - -class UnsupportedProtocolVisitor - : public TypeReprVisitor, public ASTWalker -{ - ASTContext &Ctx; - bool checkStatements; - bool hitTopStmt; - -public: - UnsupportedProtocolVisitor(ASTContext &ctx, bool checkStatements) - : Ctx(ctx), checkStatements(checkStatements), hitTopStmt(false) { } - - bool walkToTypeReprPre(TypeRepr *T) override { - if (T->isInvalid()) - return false; - if (auto compound = dyn_cast(T)) { - // Only visit the last component to check, because nested typealiases in - // existentials are okay. - visit(compound->getComponentRange().back()); - return false; - } - // Arbitrary protocol constraints are OK on opaque types. - if (isa(T)) - return false; - - visit(T); - return true; - } - - std::pair walkToStmtPre(Stmt *S) override { - if (checkStatements && !hitTopStmt) { - hitTopStmt = true; - return { true, S }; - } - - return { false, S }; - } - - bool walkToDeclPre(Decl *D) override { - return !checkStatements; - } - - void visitTypeRepr(TypeRepr *T) { - // Do nothing for all TypeReprs except the ones listed below. - } - - void visitIdentTypeRepr(IdentTypeRepr *T) { - return; - } - - void visitRequirements(ArrayRef reqts) { - for (auto reqt : reqts) { - if (reqt.getKind() == RequirementReprKind::SameType) { - if (auto *repr = reqt.getFirstTypeRepr()) - repr->walk(*this); - if (auto *repr = reqt.getSecondTypeRepr()) - repr->walk(*this); - } - } - } -}; - -} // end anonymous namespace - -void TypeChecker::checkUnsupportedProtocolType(Decl *decl) { - if (!decl || decl->isInvalid()) - return; - - auto &ctx = decl->getASTContext(); - if (auto *protocolDecl = dyn_cast(decl)) { - checkUnsupportedProtocolType(ctx, protocolDecl->getTrailingWhereClause()); - } else if (auto *genericDecl = dyn_cast(decl)) { - checkUnsupportedProtocolType(ctx, genericDecl->getGenericParams()); - checkUnsupportedProtocolType(ctx, genericDecl->getTrailingWhereClause()); - } else if (auto *assocType = dyn_cast(decl)) { - checkUnsupportedProtocolType(ctx, assocType->getTrailingWhereClause()); - } else if (auto *extDecl = dyn_cast(decl)) { - checkUnsupportedProtocolType(ctx, extDecl->getTrailingWhereClause()); - } else if (auto *subscriptDecl = dyn_cast(decl)) { - checkUnsupportedProtocolType(ctx, subscriptDecl->getGenericParams()); - checkUnsupportedProtocolType(ctx, subscriptDecl->getTrailingWhereClause()); - } else if (auto *funcDecl = dyn_cast(decl)) { - if (!isa(funcDecl)) { - checkUnsupportedProtocolType(ctx, funcDecl->getGenericParams()); - checkUnsupportedProtocolType(ctx, funcDecl->getTrailingWhereClause()); - } - } - - if (isa(decl) || isa(decl)) - return; - - UnsupportedProtocolVisitor visitor(ctx, /*checkStatements=*/false); - decl->walk(visitor); -} - -void TypeChecker::checkUnsupportedProtocolType(ASTContext &ctx, Stmt *stmt) { - if (!stmt) - return; - - UnsupportedProtocolVisitor visitor(ctx, /*checkStatements=*/true); - stmt->walk(visitor); -} - -void TypeChecker::checkUnsupportedProtocolType( - ASTContext &ctx, TrailingWhereClause *whereClause) { - if (whereClause == nullptr) - return; - - UnsupportedProtocolVisitor visitor(ctx, /*checkStatements=*/false); - visitor.visitRequirements(whereClause->getRequirements()); -} - -void TypeChecker::checkUnsupportedProtocolType( - ASTContext &ctx, GenericParamList *genericParams) { - if (genericParams == nullptr) - return; - - UnsupportedProtocolVisitor visitor(ctx, /*checkStatements=*/false); - visitor.visitRequirements(genericParams->getRequirements()); -} - Type CustomAttrTypeRequest::evaluate(Evaluator &eval, CustomAttr *attr, DeclContext *dc, CustomAttrTypeKind typeKind) const { diff --git a/lib/Sema/TypeChecker.h b/lib/Sema/TypeChecker.h index d89144a636847..027a8afda44f2 100644 --- a/lib/Sema/TypeChecker.h +++ b/lib/Sema/TypeChecker.h @@ -242,22 +242,6 @@ Type getOptionalType(SourceLoc loc, Type elementType); Expr *resolveDeclRefExpr(UnresolvedDeclRefExpr *UDRE, DeclContext *Context, bool replaceInvalidRefsWithErrors); -/// Check for unsupported protocol types in the given declaration. -void checkUnsupportedProtocolType(Decl *decl); - -/// Check for unsupported protocol types in the given statement. -void checkUnsupportedProtocolType(ASTContext &ctx, Stmt *stmt); - -/// Check for unsupported protocol types in the given generic requirement -/// list. -void checkUnsupportedProtocolType(ASTContext &ctx, - TrailingWhereClause *whereClause); - -/// Check for unsupported protocol types in the given generic requirement -/// list. -void checkUnsupportedProtocolType(ASTContext &ctx, - GenericParamList *genericParams); - /// Substitute the given base type into the type of the given nested type, /// producing the effective type that the nested type will have. /// From eb1bd07bb36f08c1c7651d8eace3b4c5924c8d11 Mon Sep 17 00:00:00 2001 From: Anthony Latsis Date: Sat, 20 Mar 2021 12:24:07 +0300 Subject: [PATCH 07/10] NFC: Remove the now dead ProtocolDecl::existentialTypeSupported() --- include/swift/AST/Decl.h | 30 +-------------------- include/swift/AST/TypeCheckRequests.h | 26 ------------------ include/swift/AST/TypeCheckerTypeIDZone.def | 2 -- lib/AST/Decl.cpp | 5 ---- lib/AST/TypeCheckRequests.cpp | 25 ----------------- lib/Sema/TypeCheckDecl.cpp | 28 ------------------- lib/Serialization/Deserialization.cpp | 5 +--- lib/Serialization/ModuleFormat.h | 1 - lib/Serialization/Serialization.cpp | 1 - 9 files changed, 2 insertions(+), 121 deletions(-) diff --git a/include/swift/AST/Decl.h b/include/swift/AST/Decl.h index 458bce26c6011..dcac2cb90e979 100644 --- a/include/swift/AST/Decl.h +++ b/include/swift/AST/Decl.h @@ -514,7 +514,7 @@ class alignas(1 << DeclAlignInBits) Decl : public ASTAllocated { IsComputingSemanticMembers : 1 ); - SWIFT_INLINE_BITFIELD_FULL(ProtocolDecl, NominalTypeDecl, 1+1+1+1+1+1+1+1+1+1+1+8+16, + SWIFT_INLINE_BITFIELD_FULL(ProtocolDecl, NominalTypeDecl, 1+1+1+1+1+1+1+1+1+8+16, /// Whether the \c RequiresClass bit is valid. RequiresClassValid : 1, @@ -527,12 +527,6 @@ class alignas(1 << DeclAlignInBits) Decl : public ASTAllocated { /// Whether the existential of this protocol conforms to itself. ExistentialConformsToSelf : 1, - /// Whether the \c ExistentialTypeSupported bit is valid. - ExistentialTypeSupportedValid : 1, - - /// Whether the existential of this protocol can be represented. - ExistentialTypeSupported : 1, - /// True if the protocol has requirements that cannot be satisfied (e.g. /// because they could not be imported from Objective-C). HasMissingRequirements : 1, @@ -4151,21 +4145,6 @@ class ProtocolDecl final : public NominalTypeDecl { Bits.ProtocolDecl.ExistentialConformsToSelf = result; } - /// Returns the cached result of \c existentialTypeSupported or \c None if it - /// hasn't yet been computed. - Optional getCachedExistentialTypeSupported() { - if (Bits.ProtocolDecl.ExistentialTypeSupportedValid) - return Bits.ProtocolDecl.ExistentialTypeSupported; - - return None; - } - - /// Caches the result of \c existentialTypeSupported - void setCachedExistentialTypeSupported(bool supported) { - Bits.ProtocolDecl.ExistentialTypeSupportedValid = true; - Bits.ProtocolDecl.ExistentialTypeSupported = supported; - } - bool hasLazyRequirementSignature() const { return Bits.ProtocolDecl.HasLazyRequirementSignature; } @@ -4175,7 +4154,6 @@ class ProtocolDecl final : public NominalTypeDecl { friend class RequirementSignatureRequest; friend class ProtocolRequiresClassRequest; friend class ExistentialConformsToSelfRequest; - friend class ExistentialTypeSupportedRequest; friend class InheritedProtocolsRequest; public: @@ -4264,12 +4242,6 @@ class ProtocolDecl final : public NominalTypeDecl { /// contain 'Self' in 'parameter' or 'other' position. bool isAvailableInExistential(const ValueDecl *decl) const; - /// Determine whether we are allowed to refer to an existential type - /// conforming to this protocol. This is only permitted if the types of - /// all the members do not contain any associated types, and do not - /// contain 'Self' in 'parameter' or 'other' position. - bool existentialTypeSupported() const; - /// Returns a list of protocol requirements that must be assessed to /// determine a concrete's conformance effect polymorphism kind. PolymorphicEffectRequirementList getPolymorphicEffectRequirements( diff --git a/include/swift/AST/TypeCheckRequests.h b/include/swift/AST/TypeCheckRequests.h index d5ba12351e716..7c28cd38b2290 100644 --- a/include/swift/AST/TypeCheckRequests.h +++ b/include/swift/AST/TypeCheckRequests.h @@ -287,32 +287,6 @@ class ExistentialConformsToSelfRequest : void cacheResult(bool value) const; }; -/// Determine whether we are allowed to refer to an existential type conforming -/// to this protocol. -class ExistentialTypeSupportedRequest : - public SimpleRequest { -public: - using SimpleRequest::SimpleRequest; - -private: - friend SimpleRequest; - - // Evaluation. - bool evaluate(Evaluator &evaluator, ProtocolDecl *decl) const; - -public: - // Cycle handling. - void diagnoseCycle(DiagnosticEngine &diags) const; - void noteCycleStep(DiagnosticEngine &diags) const; - - // Separate caching. - bool isCached() const { return true; } - Optional getCachedResult() const; - void cacheResult(bool value) const; -}; - class PolymorphicEffectRequirementsRequest : public SimpleRequest(this)}, true); -} - StringRef ProtocolDecl::getObjCRuntimeName( llvm::SmallVectorImpl &buffer) const { // If there is an 'objc' attribute with a name, use that name. diff --git a/lib/AST/TypeCheckRequests.cpp b/lib/AST/TypeCheckRequests.cpp index 4c59adca8da4f..8e21777014742 100644 --- a/lib/AST/TypeCheckRequests.cpp +++ b/lib/AST/TypeCheckRequests.cpp @@ -253,31 +253,6 @@ void ExistentialConformsToSelfRequest::cacheResult(bool value) const { decl->setCachedExistentialConformsToSelf(value); } -//----------------------------------------------------------------------------// -// existentialTypeSupported computation. -//----------------------------------------------------------------------------// - -void ExistentialTypeSupportedRequest::diagnoseCycle(DiagnosticEngine &diags) const { - auto decl = std::get<0>(getStorage()); - diags.diagnose(decl, diag::circular_protocol_def, decl->getName()); -} - -void ExistentialTypeSupportedRequest::noteCycleStep(DiagnosticEngine &diags) const { - auto requirement = std::get<0>(getStorage()); - diags.diagnose(requirement, diag::kind_declname_declared_here, - DescriptiveDeclKind::Protocol, requirement->getName()); -} - -Optional ExistentialTypeSupportedRequest::getCachedResult() const { - auto decl = std::get<0>(getStorage()); - return decl->getCachedExistentialTypeSupported(); -} - -void ExistentialTypeSupportedRequest::cacheResult(bool value) const { - auto decl = std::get<0>(getStorage()); - decl->setCachedExistentialTypeSupported(value); -} - //----------------------------------------------------------------------------// // isFinal computation. //----------------------------------------------------------------------------// diff --git a/lib/Sema/TypeCheckDecl.cpp b/lib/Sema/TypeCheckDecl.cpp index 873e93b0ea98a..8404c66777501 100644 --- a/lib/Sema/TypeCheckDecl.cpp +++ b/lib/Sema/TypeCheckDecl.cpp @@ -672,34 +672,6 @@ ExistentialConformsToSelfRequest::evaluate(Evaluator &evaluator, return true; } -bool -ExistentialTypeSupportedRequest::evaluate(Evaluator &evaluator, - ProtocolDecl *decl) const { - // ObjC protocols can always be existential. - if (decl->isObjC()) - return true; - - for (auto member : decl->getMembers()) { - // Existential types cannot be used if the protocol has an associated type. - if (isa(member)) - return false; - - // For value members, look at their type signatures. - if (auto valueMember = dyn_cast(member)) { - if (!decl->isAvailableInExistential(valueMember)) - return false; - } - } - - // Check whether all of the inherited protocols support existential types. - for (auto proto : decl->getInheritedProtocols()) { - if (!proto->existentialTypeSupported()) - return false; - } - - return true; -} - bool IsFinalRequest::evaluate(Evaluator &evaluator, ValueDecl *decl) const { if (isa(decl)) diff --git a/lib/Serialization/Deserialization.cpp b/lib/Serialization/Deserialization.cpp index 1c4aab3483a5a..3dff7b9d2fda8 100644 --- a/lib/Serialization/Deserialization.cpp +++ b/lib/Serialization/Deserialization.cpp @@ -3561,14 +3561,13 @@ class DeclDeserializer { StringRef blobData) { IdentifierID nameID; DeclContextID contextID; - bool isImplicit, isClassBounded, isObjC, existentialTypeSupported; + bool isImplicit, isClassBounded, isObjC; uint8_t rawAccessLevel; unsigned numInheritedTypes; ArrayRef rawInheritedAndDependencyIDs; decls_block::ProtocolLayout::readRecord(scratch, nameID, contextID, isImplicit, isClassBounded, isObjC, - existentialTypeSupported, rawAccessLevel, numInheritedTypes, rawInheritedAndDependencyIDs); @@ -3594,8 +3593,6 @@ class DeclDeserializer { ctx.evaluator.cacheOutput(ProtocolRequiresClassRequest{proto}, std::move(isClassBounded)); - ctx.evaluator.cacheOutput(ExistentialTypeSupportedRequest{proto}, - std::move(existentialTypeSupported)); if (auto accessLevel = getActualAccessLevel(rawAccessLevel)) proto->setAccess(*accessLevel); diff --git a/lib/Serialization/ModuleFormat.h b/lib/Serialization/ModuleFormat.h index f0bc0bf3666b7..e2165a62c24f2 100644 --- a/lib/Serialization/ModuleFormat.h +++ b/lib/Serialization/ModuleFormat.h @@ -1257,7 +1257,6 @@ namespace decls_block { BCFixed<1>, // implicit flag BCFixed<1>, // class-bounded? BCFixed<1>, // objc? - BCFixed<1>, // existential-type-supported? AccessLevelField, // access level BCVBR<4>, // number of inherited types BCArray // inherited types, followed by dependency types diff --git a/lib/Serialization/Serialization.cpp b/lib/Serialization/Serialization.cpp index 0b8c74577c983..b326e40795fdf 100644 --- a/lib/Serialization/Serialization.cpp +++ b/lib/Serialization/Serialization.cpp @@ -3545,7 +3545,6 @@ class Serializer::DeclSerializer : public DeclVisitor { const_cast(proto) ->requiresClass(), proto->isObjC(), - proto->existentialTypeSupported(), rawAccessLevel, numInherited, inheritedAndDependencyTypes); From 64b8f61b13b28d47ebf21a6a3567e14d674f7c8f Mon Sep 17 00:00:00 2001 From: Anthony Latsis Date: Fri, 13 Aug 2021 19:56:10 +0300 Subject: [PATCH 08/10] =?UTF-8?q?AST:=20Account=20for=20protocol=20composi?= =?UTF-8?q?tions=20and=20nested=20types=20in=20=C2=ABfindProtocolSelfRefer?= =?UTF-8?q?ences=C2=BB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/AST/Decl.cpp | 47 ++++++++++------ .../protocols_with_self_or_assoc_reqs.swift | 53 ++++++++++--------- 2 files changed, 61 insertions(+), 39 deletions(-) diff --git a/lib/AST/Decl.cpp b/lib/AST/Decl.cpp index 7bad2421f96f6..c12db3be1c837 100644 --- a/lib/AST/Decl.cpp +++ b/lib/AST/Decl.cpp @@ -5008,24 +5008,31 @@ findProtocolSelfReferences(const ProtocolDecl *proto, Type type, return findProtocolSelfReferences(proto, selfType->getSelfType(), position); } - // Most bound generic types are invariant. - if (auto *const bgt = type->getAs()) { + if (auto *const nominal = type->getAs()) { auto info = SelfReferenceInfo(); - if (bgt->isArray()) { - // Swift.Array preserves variance in its Value type. - info |= findProtocolSelfReferences(proto, bgt->getGenericArgs().front(), - position); - } else if (bgt->isDictionary()) { - // Swift.Dictionary preserves variance in its Element type. - info |= findProtocolSelfReferences(proto, bgt->getGenericArgs().front(), - SelfReferencePosition::Invariant); - info |= findProtocolSelfReferences(proto, bgt->getGenericArgs().back(), - position); - } else { - for (auto paramType : bgt->getGenericArgs()) { - info |= findProtocolSelfReferences(proto, paramType, + // Don't forget to look in the parent. + if (const auto parent = nominal->getParent()) { + info |= findProtocolSelfReferences(proto, parent, position); + } + + // Most bound generic types are invariant. + if (auto *const bgt = type->getAs()) { + if (bgt->isArray()) { + // Swift.Array preserves variance in its Value type. + info |= findProtocolSelfReferences(proto, bgt->getGenericArgs().front(), + position); + } else if (bgt->isDictionary()) { + // Swift.Dictionary preserves variance in its Element type. + info |= findProtocolSelfReferences(proto, bgt->getGenericArgs().front(), SelfReferencePosition::Invariant); + info |= findProtocolSelfReferences(proto, bgt->getGenericArgs().back(), + position); + } else { + for (auto paramType : bgt->getGenericArgs()) { + info |= findProtocolSelfReferences(proto, paramType, + SelfReferencePosition::Invariant); + } } } @@ -5037,6 +5044,16 @@ findProtocolSelfReferences(const ProtocolDecl *proto, Type type, if (type->is()) return SelfReferenceInfo::forSelfRef(SelfReferencePosition::Invariant); + // Protocol compositions preserve variance. + if (auto *comp = type->getAs()) { + // 'Self' may be referenced only in a superclass component. + if (const auto superclass = comp->getSuperclass()) { + return findProtocolSelfReferences(proto, superclass, position); + } + + return SelfReferenceInfo(); + } + // A direct reference to 'Self'. if (proto->getSelfInterfaceType()->isEqual(type)) return SelfReferenceInfo::forSelfRef(position); diff --git a/test/decl/protocol/protocols_with_self_or_assoc_reqs.swift b/test/decl/protocol/protocols_with_self_or_assoc_reqs.swift index e6a7dfc935470..5bbac18ffb89e 100644 --- a/test/decl/protocol/protocols_with_self_or_assoc_reqs.swift +++ b/test/decl/protocol/protocols_with_self_or_assoc_reqs.swift @@ -6,6 +6,7 @@ struct G { class Inner {} + struct InnerG {} } class C {} @@ -57,6 +58,7 @@ protocol P1 { func invariantSelf8(_: G<(Self) -> Void>) func invariantSelf9(_: G<() -> Self>) func invariantSelf10(_: P1 & C) + func invariantSelf11() -> G.InnerG func invariantAssoc1(_: inout Q) func invariantAssoc2(_: (inout Q) -> Void) func invariantAssoc3(_: inout Array<() -> Q>) @@ -67,6 +69,7 @@ protocol P1 { func invariantAssoc8(_: G<(Q) -> Void>) func invariantAssoc9(_: G<() -> Q>) func invariantAssoc10(_: P1 & C) + func invariantAssoc11() -> G.InnerG // Properties var covariantSelfPropSimple: Self { get } @@ -115,6 +118,7 @@ protocol P1 { var invariantSelfProp8: (G<(Self) -> Void>) -> Void { get } var invariantSelfProp9: (G<() -> Self>) -> Void { get } var invariantSelfProp10: (P1 & C) -> Void { get } + var invariantSelfProp11: G.InnerG { get } var invariantAssocProp1: (inout Q) -> Void { get } var invariantAssocProp2: ((inout Q) -> Void) -> Void { get } var invariantAssocProp3: (inout Array<() -> Q>) -> Void { get } @@ -125,6 +129,7 @@ protocol P1 { var invariantAssocProp8: (G<(Q) -> Void>) { get } var invariantAssocProp9: (G<() -> Q>) -> Void { get } var invariantAssocProp10: (P1 & C) -> Void { get } + var invariantAssocProp11: G.InnerG { get } // Subscripts subscript(covariantSelfSubscriptSimple _: Void) -> Self { get } @@ -168,6 +173,7 @@ protocol P1 { subscript(invariantSelfSubscript5 _: G<(Self) -> Void>) -> Void { get } subscript(invariantSelfSubscript6 _: G<() -> Self>) -> Void { get } subscript(invariantSelfSubscript7 _: P1 & C) -> Void { get } + subscript(invariantSelfSubscript8 _: Void) -> G.InnerG { get } subscript(invariantAssocSubscript1 _: G) -> Void { get } subscript(invariantAssocSubscript2 _: Void) -> G { get } subscript(invariantAssocSubscript3 _: Void) -> G.Inner { get } @@ -175,6 +181,7 @@ protocol P1 { subscript(invariantAssocSubscript5 _: G<(Q) -> Void>) -> Void { get } subscript(invariantAssocSubscript6 _: G<() -> Q>) -> Void { get } subscript(invariantAssocSubscript7 _: P1 & C) -> Void { get } + subscript(invariantAssocSubscript8 _: Void) -> G.InnerG { get } } @available(macOS 10.15, *) extension P1 { @@ -273,16 +280,16 @@ do { arg.invariantSelf4(0) // expected-error {{member 'invariantSelf4' cannot be used on value of protocol type 'P1'; use a generic constraint instead}} // expected-error@-1 {{cannot convert value of type 'Int' to expected argument type 'G'}} arg.invariantSelf5() // expected-error {{member 'invariantSelf5' cannot be used on value of protocol type 'P1'; use a generic constraint instead}} - // FIXME: Should be diagnosed. -// arg.invariantSelf6() + arg.invariantSelf6() // expected-error {{member 'invariantSelf6' cannot be used on value of protocol type 'P1'; use a generic constraint instead}} arg.invariantSelf7(0) // expected-error {{member 'invariantSelf7' cannot be used on value of protocol type 'P1'; use a generic constraint instead}} // expected-error@-1 {{cannot convert value of type 'Int' to expected argument type '(G) -> Void'}} arg.invariantSelf8(0) // expected-error {{member 'invariantSelf8' cannot be used on value of protocol type 'P1'; use a generic constraint instead}} // expected-error@-1 {{cannot convert value of type 'Int' to expected argument type 'G<(P1) -> Void>'}} arg.invariantSelf9(0) // expected-error {{member 'invariantSelf9' cannot be used on value of protocol type 'P1'; use a generic constraint instead}} // expected-error@-1 {{cannot convert value of type 'Int' to expected argument type 'G<() -> P1>'}} - // FIXME: Should be diagnosed. -// arg.invariantSelf10(0) + arg.invariantSelf10(0) // expected-error {{member 'invariantSelf10' cannot be used on value of protocol type 'P1'; use a generic constraint instead}} + // expected-error@-1 {{cannot convert value of type 'Int' to expected argument type 'C'}} + arg.invariantSelf11() // expected-error {{member 'invariantSelf11' cannot be used on value of protocol type 'P1'; use a generic constraint instead}} arg.invariantAssoc1(0) // expected-error {{member 'invariantAssoc1' cannot be used on value of protocol type 'P1'; use a generic constraint instead}} // FIXME: Silence these since we cannot make use of the member anyway. // expected-error@-2 {{cannot convert value of type 'Int' to expected argument type 'P1.Q'}} @@ -293,16 +300,16 @@ do { arg.invariantAssoc4(0) // expected-error {{member 'invariantAssoc4' cannot be used on value of protocol type 'P1'; use a generic constraint instead}} // expected-error@-1 {{cannot convert value of type 'Int' to expected argument type 'G'}} arg.invariantAssoc5() // expected-error {{member 'invariantAssoc5' cannot be used on value of protocol type 'P1'; use a generic constraint instead}} - // FIXME: Should be diagnosed. -// arg.invariantAssoc6() + arg.invariantAssoc6() // expected-error {{member 'invariantAssoc6' cannot be used on value of protocol type 'P1'; use a generic constraint instead}} arg.invariantAssoc7(0) // expected-error {{member 'invariantAssoc7' cannot be used on value of protocol type 'P1'; use a generic constraint instead}} // expected-error@-1 {{cannot convert value of type 'Int' to expected argument type '(G) -> Void'}} arg.invariantAssoc8(0) // expected-error {{member 'invariantAssoc8' cannot be used on value of protocol type 'P1'; use a generic constraint instead}} // expected-error@-1 {{cannot convert value of type 'Int' to expected argument type 'G<(P1.Q) -> Void>'}} arg.invariantAssoc9(0) // expected-error {{member 'invariantAssoc9' cannot be used on value of protocol type 'P1'; use a generic constraint instead}} // expected-error@-1 {{cannot convert value of type 'Int' to expected argument type 'G<() -> P1.Q>'}} - // FIXME: Should be diagnosed. -// arg.invariantAssoc10(0) + arg.invariantAssoc10(0) // expected-error {{member 'invariantAssoc10' cannot be used on value of protocol type 'P1'; use a generic constraint instead}} + // expected-error@-1 {{cannot convert value of type 'Int' to expected argument type 'C'}} + arg.invariantAssoc11() // expected-error {{member 'invariantAssoc11' cannot be used on value of protocol type 'P1'; use a generic constraint instead}} arg.contravariantSelfProp1 // expected-error {{member 'contravariantSelfProp1' cannot be used on value of protocol type 'P1'; use a generic constraint instead}} arg.contravariantSelfProp2 // expected-error {{member 'contravariantSelfProp2' cannot be used on value of protocol type 'P1'; use a generic constraint instead}} @@ -333,25 +340,23 @@ do { arg.invariantSelfProp3 // expected-error {{member 'invariantSelfProp3' cannot be used on value of protocol type 'P1'; use a generic constraint instead}} arg.invariantSelfProp4 // expected-error {{member 'invariantSelfProp4' cannot be used on value of protocol type 'P1'; use a generic constraint instead}} arg.invariantSelfProp5 // expected-error {{member 'invariantSelfProp5' cannot be used on value of protocol type 'P1'; use a generic constraint instead}} - // FIXME: Should be diagnosed. -// arg.invariantSelfProp6 + arg.invariantSelfProp6 // expected-error {{member 'invariantSelfProp6' cannot be used on value of protocol type 'P1'; use a generic constraint instead}} arg.invariantSelfProp7 // expected-error {{member 'invariantSelfProp7' cannot be used on value of protocol type 'P1'; use a generic constraint instead}} arg.invariantSelfProp8 // expected-error {{member 'invariantSelfProp8' cannot be used on value of protocol type 'P1'; use a generic constraint instead}} arg.invariantSelfProp9 // expected-error {{member 'invariantSelfProp9' cannot be used on value of protocol type 'P1'; use a generic constraint instead}} - // FIXME: Should be diagnosed. -// arg.invariantSelfProp10 + arg.invariantSelfProp10 // expected-error {{member 'invariantSelfProp10' cannot be used on value of protocol type 'P1'; use a generic constraint instead}} + arg.invariantSelfProp11 // expected-error {{member 'invariantSelfProp11' cannot be used on value of protocol type 'P1'; use a generic constraint instead}} arg.invariantAssocProp1 // expected-error {{member 'invariantAssocProp1' cannot be used on value of protocol type 'P1'; use a generic constraint instead}} arg.invariantAssocProp2 // expected-error {{member 'invariantAssocProp2' cannot be used on value of protocol type 'P1'; use a generic constraint instead}} arg.invariantAssocProp3 // expected-error {{member 'invariantAssocProp3' cannot be used on value of protocol type 'P1'; use a generic constraint instead}} arg.invariantAssocProp4 // expected-error {{member 'invariantAssocProp4' cannot be used on value of protocol type 'P1'; use a generic constraint instead}} arg.invariantAssocProp5 // expected-error {{member 'invariantAssocProp5' cannot be used on value of protocol type 'P1'; use a generic constraint instead}} - // FIXME: Should be diagnosed. -// arg.invariantAssocProp6 + arg.invariantAssocProp6 // expected-error {{member 'invariantAssocProp6' cannot be used on value of protocol type 'P1'; use a generic constraint instead}} arg.invariantAssocProp7 // expected-error {{member 'invariantAssocProp7' cannot be used on value of protocol type 'P1'; use a generic constraint instead}} arg.invariantAssocProp8 // expected-error {{member 'invariantAssocProp8' cannot be used on value of protocol type 'P1'; use a generic constraint instead}} arg.invariantAssocProp9 // expected-error {{member 'invariantAssocProp9' cannot be used on value of protocol type 'P1'; use a generic constraint instead}} - // FIXME: Should be diagnosed. -// arg.invariantAssocProp10 + arg.invariantAssocProp10 // expected-error {{member 'invariantAssocProp10' cannot be used on value of protocol type 'P1'; use a generic constraint instead}} + arg.invariantAssocProp11 // expected-error {{member 'invariantAssocProp11' cannot be used on value of protocol type 'P1'; use a generic constraint instead}} arg[contravariantSelfSubscript1: 0] // expected-error {{member 'subscript' cannot be used on value of protocol type 'P1'; use a generic constraint instead}} // FIXME: Silence these since we cannot make use of the member anyway. @@ -394,30 +399,30 @@ do { // FIXME: Silence these since we cannot make use of the member anyway. // expected-error@-2 {{cannot convert value of type 'Int' to expected argument type 'G'}} arg[invariantSelfSubscript2: ()] // expected-error {{member 'subscript' cannot be used on value of protocol type 'P1'; use a generic constraint instead}} - // FIXME: Should be diagnosed. -// arg[invariantSelfSubscript3: ()] + arg[invariantSelfSubscript3: ()] // expected-error {{member 'subscript' cannot be used on value of protocol type 'P1'; use a generic constraint instead}} arg[invariantSelfSubscript4: 0] // expected-error {{member 'subscript' cannot be used on value of protocol type 'P1'; use a generic constraint instead}} // expected-error@-1 {{cannot convert value of type 'Int' to expected argument type '(G) -> Void'}} arg[invariantSelfSubscript5: 0] // expected-error {{member 'subscript' cannot be used on value of protocol type 'P1'; use a generic constraint instead}} // expected-error@-1 {{cannot convert value of type 'Int' to expected argument type 'G<(P1) -> Void>'}} arg[invariantSelfSubscript6: 0] // expected-error {{member 'subscript' cannot be used on value of protocol type 'P1'; use a generic constraint instead}} // expected-error@-1 {{cannot convert value of type 'Int' to expected argument type 'G<() -> P1>'}} - // FIXME: Should be diagnosed. -// arg[invariantSelfSubscript7: 0] + arg[invariantSelfSubscript7: 0] // expected-error {{member 'subscript' cannot be used on value of protocol type 'P1'; use a generic constraint instead}} + // expected-error@-1 {{cannot convert value of type 'Int' to expected argument type 'C'}} + arg[invariantSelfSubscript8: ()] // expected-error {{member 'subscript' cannot be used on value of protocol type 'P1'; use a generic constraint instead}} arg[invariantAssocSubscript1: 0] // expected-error {{member 'subscript' cannot be used on value of protocol type 'P1'; use a generic constraint instead}} // FIXME: Silence these since we cannot make use of the member anyway. // expected-error@-2 {{cannot convert value of type 'Int' to expected argument type 'G'}} arg[invariantAssocSubscript2: ()] // expected-error {{member 'subscript' cannot be used on value of protocol type 'P1'; use a generic constraint instead}} - // FIXME: Should be diagnosed. -// arg[invariantAssocSubscript3: ()] + arg[invariantAssocSubscript3: ()] // expected-error {{member 'subscript' cannot be used on value of protocol type 'P1'; use a generic constraint instead}} arg[invariantAssocSubscript4: 0] // expected-error {{member 'subscript' cannot be used on value of protocol type 'P1'; use a generic constraint instead}} // expected-error@-1 {{cannot convert value of type 'Int' to expected argument type '(G) -> Void'}} arg[invariantAssocSubscript5: 0] // expected-error {{member 'subscript' cannot be used on value of protocol type 'P1'; use a generic constraint instead}} // expected-error@-1 {{cannot convert value of type 'Int' to expected argument type 'G<(P1.Q) -> Void>'}} arg[invariantAssocSubscript6: 0] // expected-error {{member 'subscript' cannot be used on value of protocol type 'P1'; use a generic constraint instead}} // expected-error@-1 {{cannot convert value of type 'Int' to expected argument type 'G<() -> P1.Q>'}} - // FIXME: Should be diagnosed. -// arg[invariantAssocSubscript7: 0] + arg[invariantAssocSubscript7: 0] // expected-error {{member 'subscript' cannot be used on value of protocol type 'P1'; use a generic constraint instead}} + // expected-error@-1 {{cannot convert value of type 'Int' to expected argument type 'C'}} + arg[invariantAssocSubscript8: ()] // expected-error {{member 'subscript' cannot be used on value of protocol type 'P1'; use a generic constraint instead}} } } From e49ca21bf07b9373f736037f1f119a3822c24b66 Mon Sep 17 00:00:00 2001 From: Anthony Latsis Date: Fri, 13 Aug 2021 20:08:04 +0300 Subject: [PATCH 09/10] Sema: Check for invalid reference *before* checking for unsupported existential member access --- lib/Sema/CSSimplify.cpp | 75 ++++++++++++------- .../protocols_with_self_or_assoc_reqs.swift | 28 ++++--- 2 files changed, 62 insertions(+), 41 deletions(-) diff --git a/lib/Sema/CSSimplify.cpp b/lib/Sema/CSSimplify.cpp index 5a3a5824c5a16..17ef27b6cc133 100644 --- a/lib/Sema/CSSimplify.cpp +++ b/lib/Sema/CSSimplify.cpp @@ -7322,7 +7322,7 @@ performMemberLookup(ConstraintKind constraintKind, DeclNameRef memberName, // Dig out the instance type and figure out what members of the instance type // we are going to see. auto baseTy = candidate.getBaseType(); - auto baseObjTy = baseTy->getRValueType(); + const auto baseObjTy = baseTy->getRValueType(); bool hasInstanceMembers = false; bool hasInstanceMethods = false; @@ -7369,18 +7369,6 @@ performMemberLookup(ConstraintKind constraintKind, DeclNameRef memberName, hasInstanceMethods = true; } - // If our base is an existential type, we can't make use of any - // member whose signature involves associated types. - if (instanceTy->isExistentialType()) { - if (auto *proto = decl->getDeclContext()->getSelfProtocolDecl()) { - if (!proto->isAvailableInExistential(decl)) { - result.addUnviable(candidate, - MemberLookupResult::UR_UnavailableInExistential); - return; - } - } - } - // If the invocation's argument expression has a favored type, // use that information to determine whether a specific overload for // the candidate should be favored. @@ -7400,6 +7388,20 @@ performMemberLookup(ConstraintKind constraintKind, DeclNameRef memberName, } } + const auto isUnsupportedExistentialMemberAccess = [&] { + // If our base is an existential type, we can't make use of any + // member whose signature involves associated types. + if (instanceTy->isExistentialType()) { + if (auto *proto = decl->getDeclContext()->getSelfProtocolDecl()) { + if (!proto->isAvailableInExistential(decl)) { + return true; + } + } + } + + return false; + }; + // See if we have an instance method, instance member or static method, // and check if it can be accessed on our base type. @@ -7413,20 +7415,35 @@ performMemberLookup(ConstraintKind constraintKind, DeclNameRef memberName, ? candidate : OverloadChoice(instanceTy, decl, FunctionRefKind::SingleApply); - // If this is an instance member referenced from metatype - // let's add unviable result to the set because it could be - // either curried reference or an invalid call. - // - // New candidate shouldn't affect performance because such - // choice would only be attempted when solver is in diagnostic mode. - result.addUnviable(choice, MemberLookupResult::UR_InstanceMemberOnType); - - bool invalidMethodRef = isa(decl) && !hasInstanceMethods; - bool invalidMemberRef = !isa(decl) && !hasInstanceMembers; - // If this is definitely an invalid way to reference a method or member - // on the metatype, let's stop here. - if (invalidMethodRef || invalidMemberRef) + + const bool invalidMethodRef = isa(decl) && !hasInstanceMethods; + const bool invalidMemberRef = !isa(decl) && !hasInstanceMembers; + + if (invalidMethodRef || invalidMemberRef) { + // If this is definitely an invalid way to reference a method or member + // on the metatype, let's stop here. + result.addUnviable(choice, + MemberLookupResult::UR_InstanceMemberOnType); + return; + } else if (isUnsupportedExistentialMemberAccess()) { + // If the member reference itself is legal, but it turns out to be an + // unsupported existential member access, do not make further + // assumptions about the correctness of a potential call -- let + // the unsupported member access error prevail. + result.addUnviable(candidate, + MemberLookupResult::UR_UnavailableInExistential); return; + } else { + // Otherwise, still add an unviable result to the set, because it + // could be an invalid call that was supposed to be performed on an + // instance of the type. + // + // New candidate shouldn't affect performance because such + // choice would only be attempted when solver is in diagnostic mode. + result.addUnviable(choice, + MemberLookupResult::UR_InstanceMemberOnType); + + } } // If the underlying type of a typealias is fully concrete, it is legal @@ -7477,6 +7494,12 @@ performMemberLookup(ConstraintKind constraintKind, DeclNameRef memberName, } } + if (isUnsupportedExistentialMemberAccess()) { + result.addUnviable(candidate, + MemberLookupResult::UR_UnavailableInExistential); + return; + } + // If we have an rvalue base, make sure that the result isn't 'mutating' // (only valid on lvalues). if (!baseTy->is() && diff --git a/test/decl/protocol/protocols_with_self_or_assoc_reqs.swift b/test/decl/protocol/protocols_with_self_or_assoc_reqs.swift index 5bbac18ffb89e..05d6410ead2fa 100644 --- a/test/decl/protocol/protocols_with_self_or_assoc_reqs.swift +++ b/test/decl/protocol/protocols_with_self_or_assoc_reqs.swift @@ -442,19 +442,19 @@ protocol P1_TypeMemberOnInstanceAndViceVersa { subscript(invariantSelfSubscript _: Void) -> G { get } } do { + // Test that invalid reference errors prevail over unsupported existential + // member accesses. func test(protoMeta: P1_TypeMemberOnInstanceAndViceVersa.Protocol, existMeta: P1_TypeMemberOnInstanceAndViceVersa.Type, instance: P1_TypeMemberOnInstanceAndViceVersa) { // P1_TypeMemberOnInstanceAndViceVersa.Protocol - // FIXME: These should be diagnosed as invalid references. - protoMeta.static_invariantSelfMethod() // expected-error {{member 'static_invariantSelfMethod' cannot be used on value of protocol type 'P1_TypeMemberOnInstanceAndViceVersa.Protocol'; use a generic constraint instead}} - protoMeta.static_invariantSelfProp // expected-error {{member 'static_invariantSelfProp' cannot be used on value of protocol type 'P1_TypeMemberOnInstanceAndViceVersa.Protocol'; use a generic constraint instead}} - protoMeta[static_invariantSelfSubscript: ()] // expected-error {{member 'subscript' cannot be used on value of protocol type 'P1_TypeMemberOnInstanceAndViceVersa.Protocol'; use a generic constraint instead}} + protoMeta.static_invariantSelfMethod() // expected-error {{static member 'static_invariantSelfMethod' cannot be used on protocol metatype 'P1_TypeMemberOnInstanceAndViceVersa.Protocol'}} + protoMeta.static_invariantSelfProp // expected-error {{static member 'static_invariantSelfProp' cannot be used on protocol metatype 'P1_TypeMemberOnInstanceAndViceVersa.Protocol'}} + protoMeta[static_invariantSelfSubscript: ()] // expected-error {{static member 'subscript' cannot be used on protocol metatype 'P1_TypeMemberOnInstanceAndViceVersa.Protocol'}} _ = protoMeta.covariantSelfMethod // ok protoMeta.invariantSelfMethod // expected-error {{member 'invariantSelfMethod' cannot be used on value of protocol type 'P1_TypeMemberOnInstanceAndViceVersa.Protocol'; use a generic constraint instead}} - // FIXME: These should be diagnosed as invalid references. - protoMeta.invariantSelfProp // expected-error {{member 'invariantSelfProp' cannot be used on value of protocol type 'P1_TypeMemberOnInstanceAndViceVersa.Protocol'; use a generic constraint instead}} - protoMeta[invariantSelfSubscript: ()] // expected-error {{member 'subscript' cannot be used on value of protocol type 'P1_TypeMemberOnInstanceAndViceVersa.Protocol'; use a generic constraint instead}} + protoMeta.invariantSelfProp // expected-error {{instance member 'invariantSelfProp' cannot be used on type 'P1_TypeMemberOnInstanceAndViceVersa'}} + protoMeta[invariantSelfSubscript: ()] // expected-error {{instance member 'subscript' cannot be used on type 'P1_TypeMemberOnInstanceAndViceVersa'}} // P1_TypeMemberOnInstanceAndViceVersa.Type _ = existMeta.static_covariantSelfMethod // ok @@ -463,16 +463,14 @@ do { existMeta.static_invariantSelfMethod // expected-error {{member 'static_invariantSelfMethod' cannot be used on value of protocol type 'P1_TypeMemberOnInstanceAndViceVersa.Type'; use a generic constraint instead}} existMeta.static_invariantSelfProp // expected-error {{member 'static_invariantSelfProp' cannot be used on value of protocol type 'P1_TypeMemberOnInstanceAndViceVersa.Type'; use a generic constraint instead}} existMeta[static_invariantSelfSubscript: ()] // expected-error {{member 'subscript' cannot be used on value of protocol type 'P1_TypeMemberOnInstanceAndViceVersa.Type'; use a generic constraint instead}} - // FIXME: These should be diagnosed as invalid references. - existMeta.invariantSelfMethod // expected-error {{member 'invariantSelfMethod' cannot be used on value of protocol type 'P1_TypeMemberOnInstanceAndViceVersa.Type'; use a generic constraint instead}} - existMeta.invariantSelfProp // expected-error {{member 'invariantSelfProp' cannot be used on value of protocol type 'P1_TypeMemberOnInstanceAndViceVersa.Type'; use a generic constraint instead}} - existMeta[invariantSelfSubscript: ()] // expected-error {{member 'subscript' cannot be used on value of protocol type 'P1_TypeMemberOnInstanceAndViceVersa.Type'; use a generic constraint instead}} + existMeta.invariantSelfMethod // expected-error {{instance member 'invariantSelfMethod' cannot be used on type 'P1_TypeMemberOnInstanceAndViceVersa'}} + existMeta.invariantSelfProp // expected-error {{instance member 'invariantSelfProp' cannot be used on type 'P1_TypeMemberOnInstanceAndViceVersa'}} + existMeta[invariantSelfSubscript: ()] // expected-error {{instance member 'subscript' cannot be used on type 'P1_TypeMemberOnInstanceAndViceVersa'}} // P1_TypeMemberOnInstanceAndViceVersa - // FIXME: These should be diagnosed as invalid references. - instance.static_invariantSelfMethod // expected-error {{member 'static_invariantSelfMethod' cannot be used on value of protocol type 'P1_TypeMemberOnInstanceAndViceVersa'; use a generic constraint instead}} - instance.static_invariantSelfProp // expected-error {{member 'static_invariantSelfProp' cannot be used on value of protocol type 'P1_TypeMemberOnInstanceAndViceVersa'; use a generic constraint instead}} - instance[static_invariantSelfSubscript: ()] // expected-error {{member 'subscript' cannot be used on value of protocol type 'P1_TypeMemberOnInstanceAndViceVersa'; use a generic constraint instead}} + instance.static_invariantSelfMethod // expected-error {{static member 'static_invariantSelfMethod' cannot be used on instance of type 'P1_TypeMemberOnInstanceAndViceVersa'}} + instance.static_invariantSelfProp // expected-error {{static member 'static_invariantSelfProp' cannot be used on instance of type 'P1_TypeMemberOnInstanceAndViceVersa'}} + instance[static_invariantSelfSubscript: ()] // expected-error {{static member 'subscript' cannot be used on instance of type 'P1_TypeMemberOnInstanceAndViceVersa'}} } } From 06b2f556f71d54c20dfb2a79c553830b9c196960 Mon Sep 17 00:00:00 2001 From: Anthony Latsis Date: Mon, 30 Aug 2021 21:01:19 +0300 Subject: [PATCH 10/10] Hack: Avoid devirtualizing calls to requirements with covariant Self inside collections, since the optimizer doesn't know how to handle them yet --- .../protocols_with_self_or_assoc_reqs_executable.swift | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/test/decl/protocol/protocols_with_self_or_assoc_reqs_executable.swift b/test/decl/protocol/protocols_with_self_or_assoc_reqs_executable.swift index 58aa147a3ebe9..94ebc2f2eb6ff 100644 --- a/test/decl/protocol/protocols_with_self_or_assoc_reqs_executable.swift +++ b/test/decl/protocol/protocols_with_self_or_assoc_reqs_executable.swift @@ -48,7 +48,10 @@ Tests.test("Basic") { expectEqual(3, collection.count) } -Tests.test("Covariant 'Self' erasure") { +// FIXME: Teach the devirtualizer how to handle calls to requirements with covariant `Self` nested +// inside known-covariant stdlib types such as an array or dictionary. +@_optimize(none) +func convariantSelfErasureTest() { struct S: P { static let str = "Success" func getString() -> String { Self.str } @@ -104,4 +107,7 @@ Tests.test("Covariant 'Self' erasure") { expectEqual(true, S() is P) } + +Tests.test("Covariant 'Self' erasure", convariantSelfErasureTest) + runAllTests()