From ea7837b9f90f7711b7915f39f4fd806586213c41 Mon Sep 17 00:00:00 2001 From: Anthony Latsis Date: Mon, 1 Apr 2019 17:35:59 +0300 Subject: [PATCH 01/14] Create 0000-where-on-contextually-generic.md --- .../0000-where-on-contextually-generic.md | 76 +++++++++++++++++++ 1 file changed, 76 insertions(+) create mode 100644 proposals/0000-where-on-contextually-generic.md diff --git a/proposals/0000-where-on-contextually-generic.md b/proposals/0000-where-on-contextually-generic.md new file mode 100644 index 0000000000..2f14de8f10 --- /dev/null +++ b/proposals/0000-where-on-contextually-generic.md @@ -0,0 +1,76 @@ +# `where` clauses on contextually generic declaractions + +* Proposal: [SE-NNNN](NNNN-filename.md) +* Authors: [Anthony Latsis](https://github.com/AnthonyLatsis) +* Review Manager: TBD +* Status: **Ongoing Discussion** +* Implementation: [apple/swift#23489](https://github.com/apple/swift/pull/23489) + +## Introduction + +The objective of this proposal is to lift the restriction on attaching `where` clauses to generic declarations that themselves +do not declare generic parameters, but inherit the surrounding generic environment. Simply put, this means you no longer have +to worry about the `'where' clause cannot be attached` error within generic contexts. + +```swift +struct Box { + func sequence() -> [Box] where Wrapped: Sequence { ... } +} + +``` + +> The described enhancement only applies to declarations that *can* be generic and already support being constrained via +> an extension. Properties and new constraint kinds are out +> of scope for this document. For example, the following remains an error: +> ```swift +> protocol P { +> // error: Instance method requirement 'foo(arg:)' cannot add constraint 'Self: Equatable' on 'Self' +> func foo() where Self: Equatable +> } +> + +Swift-evolution thread: [Discussion thread topic for that proposal](https://forums.swift.org/) + +## Motivation + +Today, `where` clauses on contextually generic declarations can only be expressed indirectly by placing them on conditional +extensions. Unless the constraints are identical, every such declaration requires a separate extension. This apparent +dependence on extensions is an obstacle to stacking up constraints or grouping semantically related APIs and usually +becomes a pain point in heavily generic code that unnecessarily complicates the structure of a program for the developer +and the compiler. + +Leaving ergonomic shortcomings behind, it is only natural for a `where` clause to work anywhere a constraint can be +meaningfully imposed, meaning both of the these layout variants should be possible: +```swift +struct Foo // 'Foo' can be any kind of nominal type declaration. For a protocol, 'T' would be an associatedtype. + +extension Foo where T: Sequence, T.Element: Equatable { + func slowFoo() { ... } +} +extension Foo where T: Sequence, T.Element: Hashable { + func optimizedFoo() { ... } +} +extension Foo where T: Sequence, T.Element == Character { + func specialCaseFoo() { ... } +} + +extension Foo where T: Sequence, T.Element: Equatable { + func slowFoo() { ... } + + func optimizedFoo() where T.Element: Hashable { ... } + + func specialCaseFoo() where T.Element == Character { ... } +} +``` +A move towards «untying» generic parameter lists and `where` clauses is an obvious and farsighted improvement to the generics +system with numerous future applications, including contextually generic computed properties, [opaque types](https://github.com/apple/swift-evolution/blob/master/proposals/0244-opaque-result-types.md), [generalized +existentials](https://github.com/apple/swift/blob/master/docs/GenericsManifesto.md#generalized-existentials) and constrained protocol requirements. + +## Source compatibility and ABI stability + +This is an additive change with no impact on the ABI and existing code. + +## Effect on API resilience + +For public declarations in resilient libraries, switching between a constrained extension and a «direct» `where` clause +will not be a source-breaking change, but it most likely will break the ABI due to subtle mangling differences. From 1391db5a6b4ce16113c51b206c862a62e9d34709 Mon Sep 17 00:00:00 2001 From: Anthony Latsis Date: Mon, 1 Apr 2019 17:47:37 +0300 Subject: [PATCH 02/14] Update 0000-where-on-contextually-generic.md --- proposals/0000-where-on-contextually-generic.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/proposals/0000-where-on-contextually-generic.md b/proposals/0000-where-on-contextually-generic.md index 2f14de8f10..c701c9b1e8 100644 --- a/proposals/0000-where-on-contextually-generic.md +++ b/proposals/0000-where-on-contextually-generic.md @@ -8,7 +8,7 @@ ## Introduction -The objective of this proposal is to lift the restriction on attaching `where` clauses to generic declarations that themselves +The objective of this proposal is to lift the restriction on attaching `where` clauses to declarations that themselves do not declare generic parameters, but inherit the surrounding generic environment. Simply put, this means you no longer have to worry about the `'where' clause cannot be attached` error within generic contexts. @@ -19,8 +19,8 @@ struct Box { ``` -> The described enhancement only applies to declarations that *can* be generic and already support being constrained via -> an extension. Properties and new constraint kinds are out +> Only declarations that can already be generic and support being constrained via a conditional +> extension are covered by the described enhancement. Properties and new constraint kinds are out > of scope for this document. For example, the following remains an error: > ```swift > protocol P { From 5d6d9a166a55f9372cb4dbd875cfbd4879cff6f0 Mon Sep 17 00:00:00 2001 From: Anthony Latsis Date: Mon, 1 Apr 2019 17:56:16 +0300 Subject: [PATCH 03/14] Update 0000-where-on-contextually-generic.md --- proposals/0000-where-on-contextually-generic.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/proposals/0000-where-on-contextually-generic.md b/proposals/0000-where-on-contextually-generic.md index c701c9b1e8..7d9e0c2940 100644 --- a/proposals/0000-where-on-contextually-generic.md +++ b/proposals/0000-where-on-contextually-generic.md @@ -9,8 +9,7 @@ ## Introduction The objective of this proposal is to lift the restriction on attaching `where` clauses to declarations that themselves -do not declare generic parameters, but inherit the surrounding generic environment. Simply put, this means you no longer have -to worry about the `'where' clause cannot be attached` error within generic contexts. +do not carry a generic parameter list explicitly, but inherit the surrounding generic environment. Simply put, this means you no longer have to worry about the `'where' clause cannot be attached` error within generic contexts. ```swift struct Box { From fb55401bbcdfb34ac8ec388d863ee6ec6a3d7aae Mon Sep 17 00:00:00 2001 From: Anthony Latsis Date: Mon, 1 Apr 2019 18:21:26 +0300 Subject: [PATCH 04/14] Update 0000-where-on-contextually-generic.md --- proposals/0000-where-on-contextually-generic.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/proposals/0000-where-on-contextually-generic.md b/proposals/0000-where-on-contextually-generic.md index 7d9e0c2940..b04210a0b7 100644 --- a/proposals/0000-where-on-contextually-generic.md +++ b/proposals/0000-where-on-contextually-generic.md @@ -1,4 +1,4 @@ -# `where` clauses on contextually generic declaractions +# `where` clauses on contextually generic declarations * Proposal: [SE-NNNN](NNNN-filename.md) * Authors: [Anthony Latsis](https://github.com/AnthonyLatsis) @@ -28,7 +28,7 @@ struct Box { > } > -Swift-evolution thread: [Discussion thread topic for that proposal](https://forums.swift.org/) +Swift-evolution thread: [Discussion thread topic for that proposal](https://forums.swift.org/t/where-clauses-on-contextually-generic-declaractions/22449) ## Motivation From 6c132c654aed1fc40f5aa1317755d89c1a8ad0d9 Mon Sep 17 00:00:00 2001 From: Anthony Latsis Date: Tue, 2 Apr 2019 14:23:25 +0300 Subject: [PATCH 05/14] Update 0000-where-on-contextually-generic.md --- proposals/0000-where-on-contextually-generic.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/proposals/0000-where-on-contextually-generic.md b/proposals/0000-where-on-contextually-generic.md index b04210a0b7..3eea5dec17 100644 --- a/proposals/0000-where-on-contextually-generic.md +++ b/proposals/0000-where-on-contextually-generic.md @@ -39,7 +39,7 @@ becomes a pain point in heavily generic code that unnecessarily complicates the and the compiler. Leaving ergonomic shortcomings behind, it is only natural for a `where` clause to work anywhere a constraint can be -meaningfully imposed, meaning both of the these layout variants should be possible: +meaningfully imposed, meaning both of these layout variants should be possible: ```swift struct Foo // 'Foo' can be any kind of nominal type declaration. For a protocol, 'T' would be an associatedtype. From af0a9fb0542c2e1b9f3f5375d425ac8f12e812ae Mon Sep 17 00:00:00 2001 From: Anthony Latsis Date: Tue, 9 Apr 2019 05:47:49 +0300 Subject: [PATCH 06/14] Update 0000-where-on-contextually-generic.md --- proposals/0000-where-on-contextually-generic.md | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/proposals/0000-where-on-contextually-generic.md b/proposals/0000-where-on-contextually-generic.md index 3eea5dec17..2e0ed409cb 100644 --- a/proposals/0000-where-on-contextually-generic.md +++ b/proposals/0000-where-on-contextually-generic.md @@ -9,7 +9,7 @@ ## Introduction The objective of this proposal is to lift the restriction on attaching `where` clauses to declarations that themselves -do not carry a generic parameter list explicitly, but inherit the surrounding generic environment. Simply put, this means you no longer have to worry about the `'where' clause cannot be attached` error within generic contexts. +do not introduce type variables explicitly, but inherit the surrounding generic environment. Simply put, this means you no longer have to worry about the `'where' clause cannot be attached` error within generic contexts. ```swift struct Box { @@ -26,7 +26,7 @@ struct Box { > // error: Instance method requirement 'foo(arg:)' cannot add constraint 'Self: Equatable' on 'Self' > func foo() where Self: Equatable > } -> +> ``` Swift-evolution thread: [Discussion thread topic for that proposal](https://forums.swift.org/t/where-clauses-on-contextually-generic-declaractions/22449) @@ -40,6 +40,7 @@ and the compiler. Leaving ergonomic shortcomings behind, it is only natural for a `where` clause to work anywhere a constraint can be meaningfully imposed, meaning both of these layout variants should be possible: + ```swift struct Foo // 'Foo' can be any kind of nominal type declaration. For a protocol, 'T' would be an associatedtype. @@ -62,7 +63,7 @@ extension Foo where T: Sequence, T.Element: Equatable { } ``` A move towards «untying» generic parameter lists and `where` clauses is an obvious and farsighted improvement to the generics -system with numerous future applications, including contextually generic computed properties, [opaque types](https://github.com/apple/swift-evolution/blob/master/proposals/0244-opaque-result-types.md), [generalized +system with numerous future applications, including [opaque types](https://github.com/apple/swift-evolution/blob/master/proposals/0244-opaque-result-types.md), [generalized existentials](https://github.com/apple/swift/blob/master/docs/GenericsManifesto.md#generalized-existentials) and constrained protocol requirements. ## Source compatibility and ABI stability From df7d32b712ffdb54f82c1d56d352327b4040ef76 Mon Sep 17 00:00:00 2001 From: Anthony Latsis Date: Mon, 23 Sep 2019 02:44:12 +0300 Subject: [PATCH 07/14] Update 0000-where-on-contextually-generic.md --- .../0000-where-on-contextually-generic.md | 23 ++++++++----------- 1 file changed, 10 insertions(+), 13 deletions(-) diff --git a/proposals/0000-where-on-contextually-generic.md b/proposals/0000-where-on-contextually-generic.md index 2e0ed409cb..d894bbfb61 100644 --- a/proposals/0000-where-on-contextually-generic.md +++ b/proposals/0000-where-on-contextually-generic.md @@ -8,8 +8,8 @@ ## Introduction -The objective of this proposal is to lift the restriction on attaching `where` clauses to declarations that themselves -do not introduce type variables explicitly, but inherit the surrounding generic environment. Simply put, this means you no longer have to worry about the `'where' clause cannot be attached` error within generic contexts. +The objective of the proposal is to lift the restriction on attaching `where` clauses to declarations that themselves +do not introduce new generic parameters, but inherit the surrounding generic environment. Simply put, this means you no longer have to worry about the `'where' clause cannot be attached` error inside a generic context. ```swift struct Box { @@ -18,9 +18,9 @@ struct Box { ``` -> Only declarations that can already be generic and support being constrained via a conditional -> extension are covered by the described enhancement. Properties and new constraint kinds are out -> of scope for this document. For example, the following remains an error: +> Only declarations that already support genericity and being constrained via a conditional +> extension fall under this enhancement. Properties and hitherto unsupported constraint kinds are out +> of scope for the proposal. For instance, the following remains an error: > ```swift > protocol P { > // error: Instance method requirement 'foo(arg:)' cannot add constraint 'Self: Equatable' on 'Self' @@ -32,14 +32,11 @@ Swift-evolution thread: [Discussion thread topic for that proposal](https://foru ## Motivation -Today, `where` clauses on contextually generic declarations can only be expressed indirectly by placing them on conditional -extensions. Unless the constraints are identical, every such declaration requires a separate extension. This apparent -dependence on extensions is an obstacle to stacking up constraints or grouping semantically related APIs and usually -becomes a pain point in heavily generic code that unnecessarily complicates the structure of a program for the developer -and the compiler. +Today, `where` clauses on contextually generic declarations are expressed indirectly by placing them inside conditional extensions. Unless constraints are identical, every such declaration requires a separate extension. +This dependence on extensions can be an obstacle to grouping semantically related APIs, stacking up constraints and, +sometimes, the legibility of heavily generic interfaces. -Leaving ergonomic shortcomings behind, it is only natural for a `where` clause to work anywhere a constraint can be -meaningfully imposed, meaning both of these layout variants should be possible: +It is reasonable to expect a `where` clause to work anywhere a constraint can be meaningfully imposed, meaning both of these should be possible: ```swift struct Foo // 'Foo' can be any kind of nominal type declaration. For a protocol, 'T' would be an associatedtype. @@ -62,7 +59,7 @@ extension Foo where T: Sequence, T.Element: Equatable { func specialCaseFoo() where T.Element == Character { ... } } ``` -A move towards «untying» generic parameter lists and `where` clauses is an obvious and farsighted improvement to the generics +A step towards "untying" generic parameter lists and `where` clauses is an obvious and farsighted improvement to the generics system with numerous future applications, including [opaque types](https://github.com/apple/swift-evolution/blob/master/proposals/0244-opaque-result-types.md), [generalized existentials](https://github.com/apple/swift/blob/master/docs/GenericsManifesto.md#generalized-existentials) and constrained protocol requirements. From e72224466d7be8923eeea98df7d1d821c90ec2ad Mon Sep 17 00:00:00 2001 From: Anthony Latsis Date: Mon, 23 Sep 2019 02:46:15 +0300 Subject: [PATCH 08/14] Update 0000-where-on-contextually-generic.md --- proposals/0000-where-on-contextually-generic.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/proposals/0000-where-on-contextually-generic.md b/proposals/0000-where-on-contextually-generic.md index d894bbfb61..e4910a9e14 100644 --- a/proposals/0000-where-on-contextually-generic.md +++ b/proposals/0000-where-on-contextually-generic.md @@ -36,7 +36,7 @@ Today, `where` clauses on contextually generic declarations are expressed indire This dependence on extensions can be an obstacle to grouping semantically related APIs, stacking up constraints and, sometimes, the legibility of heavily generic interfaces. -It is reasonable to expect a `where` clause to work anywhere a constraint can be meaningfully imposed, meaning both of these should be possible: +It is reasonable to expect a `where` clause to work anywhere a constraint can be meaningfully imposed, meaning both of these structuring styles should be available to the user: ```swift struct Foo // 'Foo' can be any kind of nominal type declaration. For a protocol, 'T' would be an associatedtype. From ae1260c2634dbea3917357dc5ad8d1d78bda5b47 Mon Sep 17 00:00:00 2001 From: Anthony Latsis Date: Mon, 23 Sep 2019 16:37:35 +0300 Subject: [PATCH 09/14] Update 0000-where-on-contextually-generic.md --- proposals/0000-where-on-contextually-generic.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/proposals/0000-where-on-contextually-generic.md b/proposals/0000-where-on-contextually-generic.md index e4910a9e14..9c87cc4199 100644 --- a/proposals/0000-where-on-contextually-generic.md +++ b/proposals/0000-where-on-contextually-generic.md @@ -8,7 +8,7 @@ ## Introduction -The objective of the proposal is to lift the restriction on attaching `where` clauses to declarations that themselves +This proposal is about lifting the restriction on attaching `where` clauses to declarations that themselves do not introduce new generic parameters, but inherit the surrounding generic environment. Simply put, this means you no longer have to worry about the `'where' clause cannot be attached` error inside a generic context. ```swift From 21e8cef3549f24402bf9778590406219eef21800 Mon Sep 17 00:00:00 2001 From: Anthony Latsis Date: Fri, 27 Sep 2019 01:01:50 +0300 Subject: [PATCH 10/14] Update 0000-where-on-contextually-generic.md --- proposals/0000-where-on-contextually-generic.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/proposals/0000-where-on-contextually-generic.md b/proposals/0000-where-on-contextually-generic.md index 9c87cc4199..fb8d34434e 100644 --- a/proposals/0000-where-on-contextually-generic.md +++ b/proposals/0000-where-on-contextually-generic.md @@ -8,7 +8,7 @@ ## Introduction -This proposal is about lifting the restriction on attaching `where` clauses to declarations that themselves +This proposal aims to lift the (mostly artificial) restriction on attaching `where` clauses to declarations that themselves do not introduce new generic parameters, but inherit the surrounding generic environment. Simply put, this means you no longer have to worry about the `'where' clause cannot be attached` error inside a generic context. ```swift From ea8a617a8c26c81def735a857a8096926d2fcc1a Mon Sep 17 00:00:00 2001 From: Anthony Latsis Date: Fri, 27 Sep 2019 01:02:32 +0300 Subject: [PATCH 11/14] Update 0000-where-on-contextually-generic.md --- proposals/0000-where-on-contextually-generic.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/proposals/0000-where-on-contextually-generic.md b/proposals/0000-where-on-contextually-generic.md index fb8d34434e..bc53fbb895 100644 --- a/proposals/0000-where-on-contextually-generic.md +++ b/proposals/0000-where-on-contextually-generic.md @@ -9,7 +9,7 @@ ## Introduction This proposal aims to lift the (mostly artificial) restriction on attaching `where` clauses to declarations that themselves -do not introduce new generic parameters, but inherit the surrounding generic environment. Simply put, this means you no longer have to worry about the `'where' clause cannot be attached` error inside a generic context. +do not introduce new generic parameters, but inherit the surrounding generic environment. Simply put, this means you no longer have to worry about the `'where' clause cannot be attached` error inside most generic contexts. ```swift struct Box { From 69c8513541b76813a8326d9ebb08c93b5dc87fd2 Mon Sep 17 00:00:00 2001 From: Anthony Latsis Date: Fri, 27 Sep 2019 01:06:20 +0300 Subject: [PATCH 12/14] Update 0000-where-on-contextually-generic.md --- proposals/0000-where-on-contextually-generic.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/proposals/0000-where-on-contextually-generic.md b/proposals/0000-where-on-contextually-generic.md index bc53fbb895..8475da10ae 100644 --- a/proposals/0000-where-on-contextually-generic.md +++ b/proposals/0000-where-on-contextually-generic.md @@ -3,7 +3,7 @@ * Proposal: [SE-NNNN](NNNN-filename.md) * Authors: [Anthony Latsis](https://github.com/AnthonyLatsis) * Review Manager: TBD -* Status: **Ongoing Discussion** +* Status: **Awaiting a Review Manager** * Implementation: [apple/swift#23489](https://github.com/apple/swift/pull/23489) ## Introduction From 099e71b0550e51c0683b54d7f12ce1a2edafc7e5 Mon Sep 17 00:00:00 2001 From: Anthony Latsis Date: Fri, 11 Oct 2019 23:28:48 +0300 Subject: [PATCH 13/14] Update 0000-where-on-contextually-generic.md --- proposals/0000-where-on-contextually-generic.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/proposals/0000-where-on-contextually-generic.md b/proposals/0000-where-on-contextually-generic.md index 8475da10ae..bf1c2493d9 100644 --- a/proposals/0000-where-on-contextually-generic.md +++ b/proposals/0000-where-on-contextually-generic.md @@ -8,7 +8,7 @@ ## Introduction -This proposal aims to lift the (mostly artificial) restriction on attaching `where` clauses to declarations that themselves +This proposal aims to lift the mostly artificial restriction on attaching `where` clauses to declarations that themselves do not introduce new generic parameters, but inherit the surrounding generic environment. Simply put, this means you no longer have to worry about the `'where' clause cannot be attached` error inside most generic contexts. ```swift From 0ac14cc387df453207b3a6e48474722c56c0c443 Mon Sep 17 00:00:00 2001 From: Anthony Latsis Date: Fri, 11 Oct 2019 23:31:41 +0300 Subject: [PATCH 14/14] Update 0000-where-on-contextually-generic.md --- proposals/0000-where-on-contextually-generic.md | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/proposals/0000-where-on-contextually-generic.md b/proposals/0000-where-on-contextually-generic.md index bf1c2493d9..2e9863f638 100644 --- a/proposals/0000-where-on-contextually-generic.md +++ b/proposals/0000-where-on-contextually-generic.md @@ -8,8 +8,7 @@ ## Introduction -This proposal aims to lift the mostly artificial restriction on attaching `where` clauses to declarations that themselves -do not introduce new generic parameters, but inherit the surrounding generic environment. Simply put, this means you no longer have to worry about the `'where' clause cannot be attached` error inside most generic contexts. +This proposal aims to lift the mostly artificial restriction on attaching `where` clauses to declarations that reference only outer generic parameters. Simply put, this means you no longer have to worry about the `'where' clause cannot be attached` error inside most generic contexts. ```swift struct Box { @@ -59,7 +58,7 @@ extension Foo where T: Sequence, T.Element: Equatable { func specialCaseFoo() where T.Element == Character { ... } } ``` -A step towards "untying" generic parameter lists and `where` clauses is an obvious and farsighted improvement to the generics +A step towards generalizing `where` clause usage is an obvious and farsighted improvement to the generics system with numerous future applications, including [opaque types](https://github.com/apple/swift-evolution/blob/master/proposals/0244-opaque-result-types.md), [generalized existentials](https://github.com/apple/swift/blob/master/docs/GenericsManifesto.md#generalized-existentials) and constrained protocol requirements.