From 3fcdcb4a2e02378213b4d3d34c5dc435bc0f57c7 Mon Sep 17 00:00:00 2001 From: David Hart Date: Fri, 4 Mar 2016 18:03:21 +0100 Subject: [PATCH 01/40] new proposal for objectve-c keypahts --- proposals/XXXX-objc-keypaths.md | 63 +++++++++++++++++++++++++++++++++ 1 file changed, 63 insertions(+) create mode 100644 proposals/XXXX-objc-keypaths.md diff --git a/proposals/XXXX-objc-keypaths.md b/proposals/XXXX-objc-keypaths.md new file mode 100644 index 0000000000..a59f7176ce --- /dev/null +++ b/proposals/XXXX-objc-keypaths.md @@ -0,0 +1,63 @@ +# Referencing Objective-C key-paths + +* Proposal: [SE-XXXX](https://github.com/apple/swift-evolution/blob/master/proposals/XXXX-objc-keypaths.md) +* Author(s): [David Hart](https://github.com/hartbit) +* Status: TBD +* Review manager: TBD + +## Introduction + +In Objective-C and Swift, key-paths used by KVC and KVO are represented as string literals (e.g., `"friend.address.streetName"`). This proposal seeks to improve the safety and resilience to modification of code using key-paths by introducing a compiler-checked expression. + +## Motivation + +The use of string literals for key paths is extremely error-prone: there is no checking that the string corresponds to a valid key-path. In a similar manner to the proposal for the Objective-C selector expression [SE-0022](https://github.com/apple/swift-evolution/blob/master/proposals/0022-objc-selectors.md), this proposal introduces a syntax for referencing compiler-checked key-paths. When the referenced properties and methods are renamed or deleted, the programmer will be notified by a compiler error. + +## Proposed solution + +Introduce a new expression `#keypath` that allows one to build a `String` from a key-path: + +```swift +class Person: NSObject { + dynamic var firstName: String = "" + dynamic var lastName: String = "" + dynamic var friends: [Person] = [] + dynamic var bestFriend: Person? + + init(firstName: String, lastName: String) { + self.firstName = firstName + self.lastName = lastName + } +} + +let chris = Person(firstName: "Chris", lastName: "Lattner") +let joe = Person(firstName: "Joe", lastName: "Groff") +let douglas = Person(firstName: "Douglas", lastName: "Gregor") +chris.friends = [joe, douglas] +chris.bestFriend = joe + + +#keypath(Person.firstName) // => "firstName" +chris.valueForKey(#keypath(Person.firstName)) // => Chris +#keypath(Person.bestFriend.lastName) // => "bestFriend.lastName" +chris.valueForKeyPath(#keypath(Person.bestFriend.lastName)) // => Groff +#keypath(Person.friends.firstName) // => "friends.firstName" +chris.valueForKeyPath(#keypath(Person.friends.firstName)) // => ["Joe", "Douglas"] + +``` + +By having the `#keypath` expression do the work to form the Objective-C key-path string, we free the developer from having to do the manual typing and get static checking that the key-path exists and is exposed to Objective-C. + +## Impact on existing code + +The introduction of the `#keypath` expression has no impact on existing code as it returns a `String`. It is simply a modification-safe alternative to using literal strings for referencing key-paths. + +## Alternatives considered + +One aspect of the design which seems potentially complicated is the reference to key-paths which include an collection in the middle of the path. + +```swift +chris.valueForKeyPath(#keypath(Person.friends.firstName)) +``` + + The above example is potentially harder to implement because the argument of `#keypath` is not a valid Swift expression, compared to the other two examples. An alternative would be to remove the ability to reference those key-paths, making the proposal less useful, but easier to implement. From a9efebb16775006ec87357b62079e7e031bc6226 Mon Sep 17 00:00:00 2001 From: David Hart Date: Thu, 10 Mar 2016 08:50:26 +0100 Subject: [PATCH 02/40] added ability to use value expressions --- proposals/XXXX-objc-keypaths.md | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/proposals/XXXX-objc-keypaths.md b/proposals/XXXX-objc-keypaths.md index a59f7176ce..088a9ba785 100644 --- a/proposals/XXXX-objc-keypaths.md +++ b/proposals/XXXX-objc-keypaths.md @@ -15,7 +15,7 @@ The use of string literals for key paths is extremely error-prone: there is no c ## Proposed solution -Introduce a new expression `#keypath` that allows one to build a `String` from a key-path: +Introduce a new expression `#keypath` that allows one to build a compile-time string literal from a key-path (to allow it be used as `StaticString` and `StringLiteralConvertible`): ```swift class Person: NSObject { @@ -48,9 +48,19 @@ chris.valueForKeyPath(#keypath(Person.friends.firstName)) // => ["Joe", "Douglas By having the `#keypath` expression do the work to form the Objective-C key-path string, we free the developer from having to do the manual typing and get static checking that the key-path exists and is exposed to Objective-C. +It would also be very convenient for the `#keypath` to accept value (instead of static) expressions: + +``` +extension Person { + class func find(name: String) -> [Person] { + return DB.find("SELECT * FROM Person WHERE \(#keypath(firstName)) LIKE '%\(name)%' OR \(#keypath(lastName)) LIKE '%\(name)%'") + } +} +``` + ## Impact on existing code -The introduction of the `#keypath` expression has no impact on existing code as it returns a `String`. It is simply a modification-safe alternative to using literal strings for referencing key-paths. +The introduction of the `#keypath` expression has no impact on existing code as it returns a literal string. It is simply a modification-safe alternative to using literal strings directly for referencing key-paths. ## Alternatives considered From f2bfdd499809a173e9dbf26036d13df91f8dadb9 Mon Sep 17 00:00:00 2001 From: David Hart Date: Sat, 12 Mar 2016 22:31:45 +0100 Subject: [PATCH 03/40] more detail on collection operators --- proposals/XXXX-objc-keypaths.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/proposals/XXXX-objc-keypaths.md b/proposals/XXXX-objc-keypaths.md index 088a9ba785..a9383a6ad9 100644 --- a/proposals/XXXX-objc-keypaths.md +++ b/proposals/XXXX-objc-keypaths.md @@ -58,6 +58,10 @@ extension Person { } ``` +## Collection Operators + +This proposal purposely does not attempt to implement Collection Operators as the current functionality stands on its own and is useful even without the Objective-C runtime (as can be seen in the previous example). On the contrary, collection operators will require more design, and are only useable with `valueForKeyPath:` which is not available on Linux. + ## Impact on existing code The introduction of the `#keypath` expression has no impact on existing code as it returns a literal string. It is simply a modification-safe alternative to using literal strings directly for referencing key-paths. From 441ba7cfd72b08bdd97552251be4c8b36711d09f Mon Sep 17 00:00:00 2001 From: David Hart Date: Thu, 17 Mar 2016 08:13:26 +0100 Subject: [PATCH 04/40] Clarified collection keypaths and naming disucssion --- proposals/XXXX-objc-keypaths.md | 24 +++++++++++++++++------- 1 file changed, 17 insertions(+), 7 deletions(-) diff --git a/proposals/XXXX-objc-keypaths.md b/proposals/XXXX-objc-keypaths.md index a9383a6ad9..c8d7144894 100644 --- a/proposals/XXXX-objc-keypaths.md +++ b/proposals/XXXX-objc-keypaths.md @@ -58,6 +58,22 @@ extension Person { } ``` +## Collection Keypaths + +One aspect of the design which seems potentially problematic is the reference to key-paths into collections. As Foundation types are not strongly-typed, paths that reference: + +* a type conforming to `SequenceType` are allowed to add a key to reference properties on that type and properties on the `Element` type +* a type conforming to `NSArray`, `NSDictionary`, `NSSet` are allowed to add a key to reference properties on that type but not on the contained objects + +```swift +let swiftArray = ["Chris", "Joe", "Douglas"] +let nsArray = NSArray(array: swiftArray) +swiftArray.valueForKeyPath(#keypath(swiftArray.count)) // => 3 +swiftArray.valueForKeyPath(#keypath(swiftArray.uppercaseString)) // => ["CHRIS", "JOE", "DOUGLAS"] +swiftArray.valueForKeyPath(#keypath(nsArray.count)) // => 3 +swiftArray.valueForKeyPath(#keypath(nsArray.uppercaseString)) // compiler error +``` + ## Collection Operators This proposal purposely does not attempt to implement Collection Operators as the current functionality stands on its own and is useful even without the Objective-C runtime (as can be seen in the previous example). On the contrary, collection operators will require more design, and are only useable with `valueForKeyPath:` which is not available on Linux. @@ -68,10 +84,4 @@ The introduction of the `#keypath` expression has no impact on existing code as ## Alternatives considered -One aspect of the design which seems potentially complicated is the reference to key-paths which include an collection in the middle of the path. - -```swift -chris.valueForKeyPath(#keypath(Person.friends.firstName)) -``` - - The above example is potentially harder to implement because the argument of `#keypath` is not a valid Swift expression, compared to the other two examples. An alternative would be to remove the ability to reference those key-paths, making the proposal less useful, but easier to implement. +There does not seem to be any obvious alternatives. The only point of discussion was on the name of the expression. `#key` was proposed: it is shorted but does not seem to express that the expression accepts paths. \ No newline at end of file From 4361d3209b84685f7f552f13e84f8e6949b144cd Mon Sep 17 00:00:00 2001 From: David Hart Date: Sat, 19 Mar 2016 18:57:22 +0100 Subject: [PATCH 05/40] Minor modifications to make the text and examples read better --- proposals/XXXX-objc-keypaths.md | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/proposals/XXXX-objc-keypaths.md b/proposals/XXXX-objc-keypaths.md index c8d7144894..f4031bdeaa 100644 --- a/proposals/XXXX-objc-keypaths.md +++ b/proposals/XXXX-objc-keypaths.md @@ -11,11 +11,11 @@ In Objective-C and Swift, key-paths used by KVC and KVO are represented as strin ## Motivation -The use of string literals for key paths is extremely error-prone: there is no checking that the string corresponds to a valid key-path. In a similar manner to the proposal for the Objective-C selector expression [SE-0022](https://github.com/apple/swift-evolution/blob/master/proposals/0022-objc-selectors.md), this proposal introduces a syntax for referencing compiler-checked key-paths. When the referenced properties and methods are renamed or deleted, the programmer will be notified by a compiler error. +The use of string literals for key paths is extremely error-prone: there is no compile-time assurance that the string corresponds to a valid key-path. In a similar manner to the proposal for the Objective-C selector expression [SE-0022](https://github.com/apple/swift-evolution/blob/master/proposals/0022-objc-selectors.md), this proposal introduces syntax for referencing compiler-checked key-paths. When the referenced properties and methods are renamed or deleted, the programmer will be notified by a compiler error. ## Proposed solution -Introduce a new expression `#keypath` that allows one to build a compile-time string literal from a key-path (to allow it be used as `StaticString` and `StringLiteralConvertible`): +Introduce a new expression `#keypath()` that allows one to build a compile-time valid key-path string literal (to allow it be used as `StaticString` and `StringLiteralConvertible`): ```swift class Person: NSObject { @@ -43,7 +43,6 @@ chris.valueForKey(#keypath(Person.firstName)) // => Chris chris.valueForKeyPath(#keypath(Person.bestFriend.lastName)) // => Groff #keypath(Person.friends.firstName) // => "friends.firstName" chris.valueForKeyPath(#keypath(Person.friends.firstName)) // => ["Joe", "Douglas"] - ``` By having the `#keypath` expression do the work to form the Objective-C key-path string, we free the developer from having to do the manual typing and get static checking that the key-path exists and is exposed to Objective-C. @@ -53,14 +52,16 @@ It would also be very convenient for the `#keypath` to accept value (instead of ``` extension Person { class func find(name: String) -> [Person] { - return DB.find("SELECT * FROM Person WHERE \(#keypath(firstName)) LIKE '%\(name)%' OR \(#keypath(lastName)) LIKE '%\(name)%'") + return DB.execute("SELECT * FROM Person WHERE \(#keypath(firstName)) LIKE '%\(name)%'") } } ``` +In this case, `#keypath(firstName)` is understood to represent `#keypath(Person.firstName)`. + ## Collection Keypaths -One aspect of the design which seems potentially problematic is the reference to key-paths into collections. As Foundation types are not strongly-typed, paths that reference: +One aspect of the design which seems potentially problematic is the reference to key-paths into collections. As Foundation types are not strongly-typed, keys-paths that reference: * a type conforming to `SequenceType` are allowed to add a key to reference properties on that type and properties on the `Element` type * a type conforming to `NSArray`, `NSDictionary`, `NSSet` are allowed to add a key to reference properties on that type but not on the contained objects @@ -80,7 +81,7 @@ This proposal purposely does not attempt to implement Collection Operators as th ## Impact on existing code -The introduction of the `#keypath` expression has no impact on existing code as it returns a literal string. It is simply a modification-safe alternative to using literal strings directly for referencing key-paths. +The introduction of the `#keypath` expression has no impact on existing code, and is simply a modification-safe alternative to using strings literal for referencing key-paths. ## Alternatives considered From 91ef556c2abd6a0670889008f665c19cd97ae7b7 Mon Sep 17 00:00:00 2001 From: David Hart Date: Sat, 19 Mar 2016 19:13:03 +0100 Subject: [PATCH 06/40] Final writeup of the property selector proposal --- proposals/XXXX-property-selectors.md | 55 ++++++++++++++++++++++++++++ 1 file changed, 55 insertions(+) create mode 100644 proposals/XXXX-property-selectors.md diff --git a/proposals/XXXX-property-selectors.md b/proposals/XXXX-property-selectors.md new file mode 100644 index 0000000000..eaab23ec57 --- /dev/null +++ b/proposals/XXXX-property-selectors.md @@ -0,0 +1,55 @@ +# Referencing the Objective-C selector of property getters and setters + +* Proposal: SE-XXXX +* Author(s): [David Hart](https://github.com/hartbit) +* Status: TBD +* Review manager: TBD + +## Introduction + +Proposal [SE-0022](https://github.com/apple/swift-evolution/blob/master/proposals/0022-objc-selectors.md) was accepted and implemented to provide a `#selector` expression to reference Objective-C method selectors. Unfortunately, it does not allow referencing the getter and setter methods of properties. This proposal seeks to provide a design to reference those methods for the Swift 3.0 timeframe. + +[Original swift-evolution thread](http://article.gmane.org/gmane.comp.lang.swift.evolution/7614) +[Follow-up swift-evolution thread](http://thread.gmane.org/gmane.comp.lang.swift.evolution/7780) + +## Motivation + +The `#selector` expression is very useful but does not yet cover all cases. Accessing property getter and setters requires to drop down to the string syntax and forgo type-safety. This proposal supports this special case without introducing new syntax, but by introducing new overloads to the `#selector` compiler expression. + +## Proposed solution + +Introduce two new overrides to the `#selector` expression that allows building a selector which points to the getter or the setter of a property. + +```swift +class Person: NSObject { + dynamic var firstName: String + dynamic let lastName: String + dynamic var fullName: String { + return "\(firstName) \(lastName)" + } + + init(firstName: String, lastName: String) { + self.firstName = firstName + self.lastName = lastName + } +} + +let firstNameGetter = #selector(getter: Person.firstName) +let firstNameSetter = #selector(setter: Person.firstName) +``` + +Both overrides expect a property and the setter requires a variable property. For example, the following line of code would produce an error because the lastName property is defined with let. + +``` +let lastNameSetter = #selector(setter: Person.lastName) +// Argument of #selector(setter:) must refer to a variable property +``` + +## Impact on existing code + +The introduction of the new `#selector` overrides has no impact on existing code and could improve the string-literal-as-selector to `#selector` migrator. + +## Alternatives considered + +A long term alternive could arrise from the design of lenses in Swift. But as this is purely hypothetical and out of scope for Swift 3, this proposal fixes the need for referencing property selectors in a type-safe way straight-away. + From 9cb3f3bba19790dc14615e6cc1876284ba3f8c42 Mon Sep 17 00:00:00 2001 From: David Hart Date: Thu, 24 Mar 2016 08:21:55 +0100 Subject: [PATCH 07/40] added remarks from Douglas Gregor --- proposals/XXXX-objc-keypaths.md | 40 ++++++++++++++++----------------- 1 file changed, 19 insertions(+), 21 deletions(-) diff --git a/proposals/XXXX-objc-keypaths.md b/proposals/XXXX-objc-keypaths.md index f4031bdeaa..34006fb033 100644 --- a/proposals/XXXX-objc-keypaths.md +++ b/proposals/XXXX-objc-keypaths.md @@ -15,7 +15,7 @@ The use of string literals for key paths is extremely error-prone: there is no c ## Proposed solution -Introduce a new expression `#keypath()` that allows one to build a compile-time valid key-path string literal (to allow it be used as `StaticString` and `StringLiteralConvertible`): +Introduce a new expression `#keyPath()` that allows one to build a compile-time valid key-path string literal (to allow it be used as `StaticString` and `StringLiteralConvertible`): ```swift class Person: NSObject { @@ -37,43 +37,41 @@ chris.friends = [joe, douglas] chris.bestFriend = joe -#keypath(Person.firstName) // => "firstName" -chris.valueForKey(#keypath(Person.firstName)) // => Chris -#keypath(Person.bestFriend.lastName) // => "bestFriend.lastName" -chris.valueForKeyPath(#keypath(Person.bestFriend.lastName)) // => Groff -#keypath(Person.friends.firstName) // => "friends.firstName" -chris.valueForKeyPath(#keypath(Person.friends.firstName)) // => ["Joe", "Douglas"] +#keyPath(Person.firstName) // => "firstName" +chris.valueForKey(#keyPath(Person.firstName)) // => Chris +#keyPath(Person.bestFriend.lastName) // => "bestFriend.lastName" +chris.valueForKeyPath(#keyPath(Person.bestFriend.lastName)) // => Groff +#keyPath(Person.friends.firstName) // => "friends.firstName" +chris.valueForKeyPath(#keyPath(Person.friends.firstName)) // => ["Joe", "Douglas"] ``` -By having the `#keypath` expression do the work to form the Objective-C key-path string, we free the developer from having to do the manual typing and get static checking that the key-path exists and is exposed to Objective-C. +By having the `#keyPath` expression do the work to form the Objective-C key-path string, we free the developer from having to do the manual typing and get static checking that the key-path exists and is exposed to Objective-C. -It would also be very convenient for the `#keypath` to accept value (instead of static) expressions: +It would also be very convenient for the `#keyPath` to accept value (instead of static) expressions: ``` extension Person { class func find(name: String) -> [Person] { - return DB.execute("SELECT * FROM Person WHERE \(#keypath(firstName)) LIKE '%\(name)%'") + return DB.execute("SELECT * FROM Person WHERE \(#keyPath(firstName)) LIKE '%\(name)%'") } } ``` -In this case, `#keypath(firstName)` is understood to represent `#keypath(Person.firstName)`. +In this case, `#keyPath(firstName)` is understood to represent `#keyPath(Person.firstName)`. ## Collection Keypaths -One aspect of the design which seems potentially problematic is the reference to key-paths into collections. As Foundation types are not strongly-typed, keys-paths that reference: - -* a type conforming to `SequenceType` are allowed to add a key to reference properties on that type and properties on the `Element` type -* a type conforming to `NSArray`, `NSDictionary`, `NSSet` are allowed to add a key to reference properties on that type but not on the contained objects +As Foundation types are not strongly-typed, the key-path expression should only accept traversing `SequenceType` conforming types: ```swift let swiftArray = ["Chris", "Joe", "Douglas"] let nsArray = NSArray(array: swiftArray) -swiftArray.valueForKeyPath(#keypath(swiftArray.count)) // => 3 -swiftArray.valueForKeyPath(#keypath(swiftArray.uppercaseString)) // => ["CHRIS", "JOE", "DOUGLAS"] -swiftArray.valueForKeyPath(#keypath(nsArray.count)) // => 3 -swiftArray.valueForKeyPath(#keypath(nsArray.uppercaseString)) // compiler error +swiftArray.valueForKeyPath(#keyPath(swiftArray.count)) // => 3 +swiftArray.valueForKeyPath(#keyPath(swiftArray.uppercased)) // => ["CHRIS", "JOE", "DOUGLAS"] +swiftArray.valueForKeyPath(#keyPath(nsArray.count)) // => 3 +swiftArray.valueForKeyPath(#keyPath(nsArray.uppercaseString)) // compiler error ``` +There is some implicit bridging going on here that could use some detailed design. If I refer to `Person.lastName.uppercased`, that's a method on the value type `String`. At runtime, we're depending on getting the `uppercaseString` method on `NSString`. This may be as simple as saying that we follow the `_ObjectiveCBridgeable` conformance for any value type encountered along the way. ## Collection Operators @@ -81,8 +79,8 @@ This proposal purposely does not attempt to implement Collection Operators as th ## Impact on existing code -The introduction of the `#keypath` expression has no impact on existing code, and is simply a modification-safe alternative to using strings literal for referencing key-paths. +The introduction of the `#keyPath` expression has no impact on existing code, and is simply a modification-safe alternative to using strings literal for referencing key-paths. ## Alternatives considered -There does not seem to be any obvious alternatives. The only point of discussion was on the name of the expression. `#key` was proposed: it is shorted but does not seem to express that the expression accepts paths. \ No newline at end of file +There does not seem to be any obvious alternatives. The only point of discussion was on the name of the expression. `#key` was proposed: it is shorter but does not seem to express that the expression accepts paths. \ No newline at end of file From 308ab787267adfd4ff4c4979f09ca01ba7abb197 Mon Sep 17 00:00:00 2001 From: Max Howell Date: Wed, 16 Mar 2016 17:33:01 -0700 Subject: [PATCH 08/40] Proposal: SwiftPM System Module Search Paths --- ...NNNN-swiftpm-system-module-search-paths.md | 207 ++++++++++++++++++ 1 file changed, 207 insertions(+) create mode 100644 proposals/NNNN-swiftpm-system-module-search-paths.md diff --git a/proposals/NNNN-swiftpm-system-module-search-paths.md b/proposals/NNNN-swiftpm-system-module-search-paths.md new file mode 100644 index 0000000000..ce0ec44e48 --- /dev/null +++ b/proposals/NNNN-swiftpm-system-module-search-paths.md @@ -0,0 +1,207 @@ +# SwiftPM System Module Search Paths + +* Proposal: [SE-NNNN](https://github.com/apple/swift-evolution/blob/master/proposals/NNNN-swiftpm-system-module-search-paths.md) +* Author: [Max Howell](https://github.com/mxcl) +* Status: **Awaiting review** +* Review manager: Anders Bertelrud + + +## Introduction + +Swift is able to `import` C libraries in the same manner as Swift libraries. + +For this to occur the library must be represented by a clang module-map file. + +The current system for using these module-map files with SwiftPM works, but with +a number of caveats that must be addressed. + + +[swift-evolution thread](https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20160321/013201.html) + +## Terminology + +* **Swift Package**: A package consumed by SwiftPM that comes with sources that SwiftPM builds into modules +* **Swift System Package**: A package consumed by SwiftPM that refers to a modular system library not installed by SwiftPM + + +## Motivation + +The current implementation of Swift System Packages have a number of problems: + + 1. Install locations vary across platforms and `.modulemap` files require absolute paths + 2. `/usr/lib:/usr/local/lib` is not always a sufficient `-L` linker search path + 3. `/usr/include:/usr/local/include` is not always a sufficient `-I` C compiler search path + 4. Installing the system library is left up to the end-user to figure out + +For example to import a module map representing the GTK library, the include search +path must be supplemented with `-I/usr/include/gtk` so that a number of includes in +the `gtk.h` header can be sourced for the complete modular definition of GTK. + +For example to import a module map representing the GTK library a user must first have +a copy of GTK and its headers installed. On Debian based systems the install name for +this system package is `libgtk-3-0-dev` which is not entirely intuitive. + +For example, Homebrew and MacPorts on OS X install to prefixes other than `/usr`. +`.modulemap` files must specify headers with absolute paths. The standard we +encourage with modulemaps is for the headers to be specified with an assumed +prefix of `/usr`, but you will not find eg. `jpeglib.h` at `/usr/include/jpeglib.h` +if it is installed with Homebrew or MacPorts. + + +## Proposed Solution + +We propose that SwiftPM gains the ability to read `.pc` files written for the +cross-platform `pkg-config` tool. These files describe the missing search paths +that SwiftPM requires. + +We propose that SwiftPM gains the ability to read `.pc` files written for the +cross-platform `pkg-config` tool. These files specify the install location of +system libraries and will allow SwiftPM to preprocess the modulemap changing +the specified header prefixes. + +We propose that `Package.swift` is supplemented with metadata that provides the +package-install-name for specific platforms. + + +## Detailed Design + +### Solving Path/Flags Issues + +A system library should provide a pkg-config file (`.pc`) which describes: + + 1. Its install location + 2. Supplementary flags that should be used when compiling against this library + 3. Supplementary flags that should be used when linking against this library + +If SwiftPM read the `.pc` file that comes with packages, this solves problems 1 through 3. + +Of the tickets we currently have open describing issues using Swift-system-module-packages, +reading the `.pc` file would fix all of them. + +It is a convention to name the `.pc` file after the library link-name, so we can determine +which `.pc` file to ask `pkg-config` for by parsing the `.modulemap` file in the Swift +package. However sometimes this is not true, (eg. GTK-3 on Ubuntu), so we will allow an +override in the `Package.swift` file, for example: + +```swift +let package = Package( + name: "CFoo", + pkgConfigName: "gtk-3" +) +``` + +Thus we would search for a filename: `gtk-3.pc`. + +We don’t want to depend on `pkg-config`, so we will implement the reading of `.pc` files +according to the pkg-config specification, including: + + 1. Obeying the correct search .pc file search paths + 2. Following overrides due to any `PKG_CONFIG_PATH` environment variable + + +### Providing Package Install Names + +`Package.swift` would be supplemented like so: + +```swift +let package = Package( + name: "CFoo", + pkgConfigName: "foo", + providers: [ + .Brew(installName: "foo"), + .Apt(installName: "libfoo-dev"), + ], +) +``` + +Thus, in the event of build failure for modules that depend on this +package we would provide additional help to the user: + +``` +error: failed to build module `bar' +note: you may need to install `foo' using your system-packager: + + apt-get install libfoo-dev +``` + +Since the syntax to provide this information uses an explicit enum we can +add code for each enum to detect which system packagers should be +recommended. The community will need to write the code for their own +platforms. It also means that if a specific packager requires additional +parameters, they can be added on a per enum basis. + +#### Install-names are not standard + +`apt` is used across multiple distirbutions and the install-names for +tools vary. Even for the same distribution install-names may vary +across releases (eg. from Ubuntu 15.04 to Ubuntu 15.10) or even on +ocassion at finer granularity. + +We will not add explicit handling for this, but one can imagine the +enums for different system packagers could be supplemented in a backwards +compatible way to provide specific handling as real-world uses emerge, eg: + +```swift +case Apt(installName: String) + +// …could be adapted to: + +struct Debian: Linux {} +struct Ubuntu: Debian { + enum Variant { + case Gubuntu + case Kubuntu(Version) + } + enum Version { + case v1510 + case v1504 + } +} +case Apt(installName: String, distribution: Linux? = nil) +``` + +## Impact on Existing Code + +There will be no impact on existing code as this feature simply improves +an existing feature making new code possible. + + +## Alternatives Considered + +A clear alternative is allowing additional flags to be specified in a system-module package’s `Package.swift`. + +However since these paths and flags will vary by platform this would because a large matrix that is quite a maintenance burden. Really this information is recorded already, in the system package itself, and in fact almost all packages nowadays provide it in a `.pc` `pkg-config` file. + +Also we do not want to allow arbitrary flags to be specified in `Package.swift`, this allows packages too much power +to break a large dependency graph with bad compiles. The only entity that understands the whole graph and can manage +the build without breakage is SwiftPM, and allowing packages themselves to add arbitrary flags prevents SwiftPM from +being able to understand and control the build ensuring reliability and preventing “Dependency Hell”. + + +## Unsolved Problems + +Some (usually more legacy) system libraries do not provide `.pc` files instead they may provide +a tool named eg. `foo-config` that can be queried for compile and link flags. We do not yet +support these tools, and would prefer to take a wait and see approach to determine how +important supporting them may be. + +Some libraries on OS X do not come with `.pc` files. Again we'd like to see which libraries +are affected before potentially offering a solution here. + + +## Future Directions + +The build system could be made more reliable by having the specific packager provide the information that this +proposal garners from `pkg-config`. For example, Homebrew installs everything into independent directories, using these +directories instead of more general POSIX search paths means there is no danger of edge-case search path collisions and the wrong libraries being picked up. + +If this was done `pkg-config` could become just one option for providing this data, and be used only as a fallback. + +--- + +We do not wish to provide a flag to automatically install dependencies via the +system packager. We feel this opens us up to security implications beyond the +scope of this tool. + +Instead we can provide JSON output that can be parsed and executed by some +other tooling developed outside of Apple. From deb0686f0e840d3853ba9e900ec4efb5f353afa1 Mon Sep 17 00:00:00 2001 From: Max Howell Date: Fri, 1 Apr 2016 16:56:57 -0700 Subject: [PATCH 09/40] Revisions from internal feedback --- ...NNNN-swiftpm-system-module-search-paths.md | 37 ++++++++++--------- 1 file changed, 20 insertions(+), 17 deletions(-) diff --git a/proposals/NNNN-swiftpm-system-module-search-paths.md b/proposals/NNNN-swiftpm-system-module-search-paths.md index ce0ec44e48..5d7eae7f9e 100644 --- a/proposals/NNNN-swiftpm-system-module-search-paths.md +++ b/proposals/NNNN-swiftpm-system-module-search-paths.md @@ -18,15 +18,18 @@ a number of caveats that must be addressed. [swift-evolution thread](https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20160321/013201.html) + ## Terminology -* **Swift Package**: A package consumed by SwiftPM that comes with sources that SwiftPM builds into modules -* **Swift System Package**: A package consumed by SwiftPM that refers to a modular system library not installed by SwiftPM +* **SwiftPM Source Package**: A package consumed by SwiftPM that comes with sources that SwiftPM builds into modules +* **SwiftPM System Package**: A package consumed by SwiftPM that refers to a modular system library not installed by SwiftPM +* **System Package**: A package provided by a system packager like, eg. `apt`, `pacman` or `brew`. +* **System Packager**: A system package manager like, eg. `apt`, `pacman` or `brew`. ## Motivation -The current implementation of Swift System Packages have a number of problems: +The current implementation of SwiftPM System Packages have a number of problems: 1. Install locations vary across platforms and `.modulemap` files require absolute paths 2. `/usr/lib:/usr/local/lib` is not always a sufficient `-L` linker search path @@ -39,7 +42,7 @@ the `gtk.h` header can be sourced for the complete modular definition of GTK. For example to import a module map representing the GTK library a user must first have a copy of GTK and its headers installed. On Debian based systems the install name for -this system package is `libgtk-3-0-dev` which is not entirely intuitive. +this System Package is `libgtk-3-0-dev` which is not entirely intuitive. For example, Homebrew and MacPorts on OS X install to prefixes other than `/usr`. `.modulemap` files must specify headers with absolute paths. The standard we @@ -73,15 +76,15 @@ A system library should provide a pkg-config file (`.pc`) which describes: 2. Supplementary flags that should be used when compiling against this library 3. Supplementary flags that should be used when linking against this library -If SwiftPM read the `.pc` file that comes with packages, this solves problems 1 through 3. +If SwiftPM read the `.pc` file that comes with System Packages, this solves problems 1 through 3. -Of the tickets we currently have open describing issues using Swift-system-module-packages, +Of the tickets we currently have open describing issues using SwiftPM System Packages, reading the `.pc` file would fix all of them. It is a convention to name the `.pc` file after the library link-name, so we can determine -which `.pc` file to ask `pkg-config` for by parsing the `.modulemap` file in the Swift -package. However sometimes this is not true, (eg. GTK-3 on Ubuntu), so we will allow an -override in the `Package.swift` file, for example: +which `.pc` file to ask `pkg-config` for by parsing the `.modulemap` file in the SwiftPM Package. +However sometimes this is not true, (eg. GTK-3 on Ubuntu), so we will allow an override in +the `Package.swift` file, for example: ```swift let package = Package( @@ -92,14 +95,14 @@ let package = Package( Thus we would search for a filename: `gtk-3.pc`. -We don’t want to depend on `pkg-config`, so we will implement the reading of `.pc` files -according to the pkg-config specification, including: +We don’t want to introduce a new dependency (on `pkg-config`) to Swift, so we will +implement the reading of `.pc` files according to the pkg-config specification, including: 1. Obeying the correct search .pc file search paths 2. Following overrides due to any `PKG_CONFIG_PATH` environment variable -### Providing Package Install Names +### Hinting At System-Package Install-Names `Package.swift` would be supplemented like so: @@ -115,7 +118,7 @@ let package = Package( ``` Thus, in the event of build failure for modules that depend on this -package we would provide additional help to the user: +SwiftPM Package we would output additional help to the user: ``` error: failed to build module `bar' @@ -127,7 +130,7 @@ note: you may need to install `foo' using your system-packager: Since the syntax to provide this information uses an explicit enum we can add code for each enum to detect which system packagers should be recommended. The community will need to write the code for their own -platforms. It also means that if a specific packager requires additional +platforms. It also means that if a specific system-packager requires additional parameters, they can be added on a per enum basis. #### Install-names are not standard @@ -168,9 +171,9 @@ an existing feature making new code possible. ## Alternatives Considered -A clear alternative is allowing additional flags to be specified in a system-module package’s `Package.swift`. +A clear alternative is allowing additional flags to be specified in a SwiftPM System Package’s `Package.swift`. -However since these paths and flags will vary by platform this would because a large matrix that is quite a maintenance burden. Really this information is recorded already, in the system package itself, and in fact almost all packages nowadays provide it in a `.pc` `pkg-config` file. +However since these paths and flags will vary by platform this would because a large matrix that is quite a maintenance burden. Really this information is recorded already, in the System Package itself, and in fact almost all System Packages nowadays provide it in a `.pc` `pkg-config` file. Also we do not want to allow arbitrary flags to be specified in `Package.swift`, this allows packages too much power to break a large dependency graph with bad compiles. The only entity that understands the whole graph and can manage @@ -191,7 +194,7 @@ are affected before potentially offering a solution here. ## Future Directions -The build system could be made more reliable by having the specific packager provide the information that this +The build system could be made more reliable by having the specific system packager provide the information that this proposal garners from `pkg-config`. For example, Homebrew installs everything into independent directories, using these directories instead of more general POSIX search paths means there is no danger of edge-case search path collisions and the wrong libraries being picked up. From 800df5101e9139fa89ee0ed0727e3874f1241712 Mon Sep 17 00:00:00 2001 From: Erica Sadun Date: Wed, 6 Apr 2016 10:49:55 -0600 Subject: [PATCH 10/40] Expanding Swift Self to class members and value types --- proposals/00XX-universal-Self.md | 59 ++++++++++++++++++++++++++++++++ 1 file changed, 59 insertions(+) create mode 100644 proposals/00XX-universal-Self.md diff --git a/proposals/00XX-universal-Self.md b/proposals/00XX-universal-Self.md new file mode 100644 index 0000000000..def98fa8c9 --- /dev/null +++ b/proposals/00XX-universal-Self.md @@ -0,0 +1,59 @@ +# Expanding Swift `Self` to class members and value types + +* Proposal: [SE-XXXX](https://gist.github.com/erica/5a26d523f3d6ffb74e34d179740596f7) +* Author(s): [Erica Sadun](http://github.com/erica) +* Status: TBD +* Review manager: TBD + +## Introduction + +Within a class scope, `Self` means "the dynamic class of `self`". This proposal extends that courtesy to value types, where dynamic `Self` will match a construct's static type, and to the bodies of class members, where it may not. It also introduces a static variation, `#Self` that expands to static type of the code it appears within. + +This proposal was discussed on the Swift Evolution list in the [\[Pitch\] Adding a Self type name shortcut for static member access](http://thread.gmane.org/gmane.comp.lang.swift.evolution/13708/focus=13712) thread. + +## Motivation + +It is common in Swift to reference an instance's type, whether for accessing +a static member or passing a type for an unsafe bitcast, among other uses. +At this time, you can either fully specify a type by name or use `self.dynamicType` +to access an instance's dynamic runtime type as a value. + +``` +struct MyStruct { + static func staticMethod() { ... } + func instanceMethod() { + MyStruct.staticMethod() + self.dynamicType.staticMethod() + } +} +``` + +Introducing `Self` addresses the following issues: + +* As type names grow large, readability suffers. `MyExtremelyLargeTypeName.staticMember` is unwieldy to type and read. +* Code using hardwired type names is less portable than code that automatically knows its type. +* Renaming a type means updating any `TypeName` references in code. +* Using `self.dynamicType` fights against Swift's goals of concision and clarity in that it is both noisy and esoteric. +* `self.dynamicType.classMember` and `TypeName.classMember` may not be synonyms in class types with non-final members. + +## Detail Design + +This proposal introduces `Self` and `#Self`. + +* `Self` equates to the dynamic type of `self` and only the +dynamic type of `self`. You will continue to specify full type +names for any other use. Joe Groff writes, "I don't think it's all +that onerous to have to write `ClassName.foo` if that's really what +you specifically mean." + +* `#Self` expands to the static type of the code it is +declared within. In value types, this is always the same as `Self`. +`#Self` will offer a literal textual replacement just like `#file`, etc. + +## Alternatives Considered + +Not at this time + +## Acknowlegements + +Thanks Sean Heber, Kevin Ballard, Joe Groff, Timothy Wood, Brent Royal-Gordon, Andrey Tarantsov, Austin Zheng \ No newline at end of file From a7a7d93c609dc344869a08a784ca740589a39ca1 Mon Sep 17 00:00:00 2001 From: Erica Sadun Date: Wed, 6 Apr 2016 19:34:25 -0600 Subject: [PATCH 11/40] Added discussion thread link for SE-0009 --- proposals/0009-require-self-for-accessing-instance-members.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/proposals/0009-require-self-for-accessing-instance-members.md b/proposals/0009-require-self-for-accessing-instance-members.md index e36cbbc62d..c2c185862e 100644 --- a/proposals/0009-require-self-for-accessing-instance-members.md +++ b/proposals/0009-require-self-for-accessing-instance-members.md @@ -9,6 +9,8 @@ The current version of Swift (2.1) requires using `self` when accessing instance members in closures. The proposal suggests extending this to all member accesses (as is intrinsically the case in Objective-C). It has the benefit of documenting instance properties vs local variables and instance functions vs local functions or closures. +[Swift Evolution Discussion Thread](http://thread.gmane.org/gmane.comp.lang.swift.evolution/9526) + ## Motivation This proposal makes it obvious which are instance properties vs local variables, as well as which are instance functions vs local functions/closures. This has several advantages: From 735550f44056e0aab45d27f1109b498ac255fe3d Mon Sep 17 00:00:00 2001 From: Erica Sadun Date: Wed, 6 Apr 2016 19:37:18 -0600 Subject: [PATCH 12/40] Added discussion thread link for SE-0010 --- proposals/0010-add-staticstring-unicodescalarview.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/proposals/0010-add-staticstring-unicodescalarview.md b/proposals/0010-add-staticstring-unicodescalarview.md index 79ca3b17c4..87e1279442 100644 --- a/proposals/0010-add-staticstring-unicodescalarview.md +++ b/proposals/0010-add-staticstring-unicodescalarview.md @@ -10,6 +10,8 @@ There is no way to create a substring of a `StaticString` that is still typed as `StaticString`. There should be. +[Swift Evolution Discussion Thread](http://thread.gmane.org/gmane.comp.lang.swift.evolution/9366/focus=9368) + ## Motivation It is occasionally useful to be able to produce a substring of a `StaticString` From 378a1939dfce9f7b4d93dbd8779f9bd32b7aed6c Mon Sep 17 00:00:00 2001 From: Erica Sadun Date: Wed, 6 Apr 2016 19:39:26 -0600 Subject: [PATCH 13/40] Added discussion thread link for SE-0011 --- proposals/0011-replace-typealias-associated.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/proposals/0011-replace-typealias-associated.md b/proposals/0011-replace-typealias-associated.md index 00b3f34ba4..a55b8297c0 100644 --- a/proposals/0011-replace-typealias-associated.md +++ b/proposals/0011-replace-typealias-associated.md @@ -18,6 +18,8 @@ confusion surrounding the use of associated types. The proposed new keyword is `associatedtype`. +[Swift Evolution Discussion Thread](http://thread.gmane.org/gmane.comp.lang.swift.evolution/9301/focus=9405) + ## Motivation Re-using `typealias` for associated type declarations is confusing in many ways. From 87e57761b724e581ed26fd56f2204ddfd0ff9be3 Mon Sep 17 00:00:00 2001 From: Erica Sadun Date: Wed, 6 Apr 2016 19:41:22 -0600 Subject: [PATCH 14/40] Added discussion thread link for SE-0012 --- proposals/0012-add-noescape-to-public-library-api.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/proposals/0012-add-noescape-to-public-library-api.md b/proposals/0012-add-noescape-to-public-library-api.md index 2beb382a3d..83c2fef125 100644 --- a/proposals/0012-add-noescape-to-public-library-api.md +++ b/proposals/0012-add-noescape-to-public-library-api.md @@ -17,6 +17,8 @@ * We propose exposing this attribute in CF and Foundation as `CF_NOESCAPE` and `NS_NOESCAPE` * We also propose applying this declaration to a number of closure-taking APIs in CF and Foundation +[Swift Evolution Discussion Thread](http://thread.gmane.org/gmane.comp.lang.swift.corelibs/53) + ## Introduction ### `@noescape` From bd75dea261b200342e9f3f0ef3bc8b4721093d4c Mon Sep 17 00:00:00 2001 From: Erica Sadun Date: Wed, 6 Apr 2016 19:43:20 -0600 Subject: [PATCH 15/40] Added discussion thread link for SE-0013 --- proposals/0013-remove-partial-application-super.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/proposals/0013-remove-partial-application-super.md b/proposals/0013-remove-partial-application-super.md index 110645c2ee..f65f5d17ac 100644 --- a/proposals/0013-remove-partial-application-super.md +++ b/proposals/0013-remove-partial-application-super.md @@ -22,6 +22,8 @@ those mechanisms, I propose that we disallow partial application of non-final methods through `super`, except where the `self` parameter is implicitly captured. +[Swift Evolution Discussion Thread](http://thread.gmane.org/gmane.comp.lang.swift.evolution/9778) + ## Motivation The motivation of this change is partially motivated by implementation From 8aa41aa620eadddfffb04b05a47ad8f964c8f3b2 Mon Sep 17 00:00:00 2001 From: Erica Sadun Date: Wed, 6 Apr 2016 19:46:13 -0600 Subject: [PATCH 16/40] Added review thread link for SE-0010 --- proposals/0010-add-staticstring-unicodescalarview.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/proposals/0010-add-staticstring-unicodescalarview.md b/proposals/0010-add-staticstring-unicodescalarview.md index 87e1279442..5b7b5af41f 100644 --- a/proposals/0010-add-staticstring-unicodescalarview.md +++ b/proposals/0010-add-staticstring-unicodescalarview.md @@ -10,7 +10,7 @@ There is no way to create a substring of a `StaticString` that is still typed as `StaticString`. There should be. -[Swift Evolution Discussion Thread](http://thread.gmane.org/gmane.comp.lang.swift.evolution/9366/focus=9368) +[Swift Evolution Discussion Thread](http://thread.gmane.org/gmane.comp.lang.swift.evolution/9366), [Review](http://thread.gmane.org/gmane.comp.lang.swift.evolution/2434) ## Motivation From 09b0a5bc0163d175eca22d3183c84eb8f717a85c Mon Sep 17 00:00:00 2001 From: Erica Sadun Date: Wed, 6 Apr 2016 19:48:53 -0600 Subject: [PATCH 17/40] Removed focus from SE-0011 discussion thread link --- proposals/0011-replace-typealias-associated.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/proposals/0011-replace-typealias-associated.md b/proposals/0011-replace-typealias-associated.md index a55b8297c0..8c5d9947d8 100644 --- a/proposals/0011-replace-typealias-associated.md +++ b/proposals/0011-replace-typealias-associated.md @@ -18,7 +18,7 @@ confusion surrounding the use of associated types. The proposed new keyword is `associatedtype`. -[Swift Evolution Discussion Thread](http://thread.gmane.org/gmane.comp.lang.swift.evolution/9301/focus=9405) +[Swift Evolution Discussion Thread](http://thread.gmane.org/gmane.comp.lang.swift.evolution/9301) ## Motivation From 04bbf3ddc466a3f40c947100857621236847d74d Mon Sep 17 00:00:00 2001 From: Erica Sadun Date: Wed, 6 Apr 2016 19:50:28 -0600 Subject: [PATCH 18/40] Updated SE-0013 with link to review discussion --- proposals/0013-remove-partial-application-super.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/proposals/0013-remove-partial-application-super.md b/proposals/0013-remove-partial-application-super.md index f65f5d17ac..b59df5316d 100644 --- a/proposals/0013-remove-partial-application-super.md +++ b/proposals/0013-remove-partial-application-super.md @@ -22,7 +22,7 @@ those mechanisms, I propose that we disallow partial application of non-final methods through `super`, except where the `self` parameter is implicitly captured. -[Swift Evolution Discussion Thread](http://thread.gmane.org/gmane.comp.lang.swift.evolution/9778) +[Swift Evolution Discussion Thread](http://thread.gmane.org/gmane.comp.lang.swift.evolution/9778), [Review](http://thread.gmane.org/gmane.comp.lang.swift.evolution/2880) ## Motivation From 5176994f11a06a8f9efab23be5a90ac0b7f2ded0 Mon Sep 17 00:00:00 2001 From: Doug Gregor Date: Thu, 7 Apr 2016 09:47:49 -0700 Subject: [PATCH 19/40] Start review of SE-0062 "Referencing Objective-C key-paths". --- proposals/{XXXX-objc-keypaths.md => 0062-objc-keypaths.md} | 6 +++--- schedule.md | 1 + 2 files changed, 4 insertions(+), 3 deletions(-) rename proposals/{XXXX-objc-keypaths.md => 0062-objc-keypaths.md} (95%) diff --git a/proposals/XXXX-objc-keypaths.md b/proposals/0062-objc-keypaths.md similarity index 95% rename from proposals/XXXX-objc-keypaths.md rename to proposals/0062-objc-keypaths.md index 34006fb033..a7513e2f65 100644 --- a/proposals/XXXX-objc-keypaths.md +++ b/proposals/0062-objc-keypaths.md @@ -1,9 +1,9 @@ # Referencing Objective-C key-paths -* Proposal: [SE-XXXX](https://github.com/apple/swift-evolution/blob/master/proposals/XXXX-objc-keypaths.md) +* Proposal: [SE-0062](https://github.com/apple/swift-evolution/blob/master/proposals/0062-objc-keypaths.md) * Author(s): [David Hart](https://github.com/hartbit) -* Status: TBD -* Review manager: TBD +* Status: **Under review** (April 6...12, 2016) +* Review manager: [Doug Gregor](https://github.com/DougGregor) ## Introduction diff --git a/schedule.md b/schedule.md index c9cf5108e9..0260d3399d 100644 --- a/schedule.md +++ b/schedule.md @@ -13,6 +13,7 @@ proposals in that process. * March 31...April 5, 2016 [SE-0036: Requiring Leading Dot Prefixes for Enum Instance Member Implementations](proposals/0036-enum-dot.md) * March 31...April 5, 2016 [SE-0059: Update API Naming Guidelines and Rewrite Set APIs Accordingly](proposals/0059-updated-set-apis.md) * April 4...11, 2016 [SE-0058: Allow Swift types to provide custom Objective-C representations](proposals/0058-objectivecbridgeable.md) +* April 6...12, 2016 [SE-0062: Referencing Objective-C key-paths](proposals/0062-objc-keypaths.md) ## Upcoming reviews From 2b706658896d61657dc194545e63d83b78b0758e Mon Sep 17 00:00:00 2001 From: Anders Bertelrud Date: Thu, 7 Apr 2016 13:06:03 -0700 Subject: [PATCH 20/40] Start review of SE-0063: SwiftPM System Module Search Paths --- ...-paths.md => 0063-swiftpm-system-module-search-paths.md} | 6 +++--- schedule.md | 1 + 2 files changed, 4 insertions(+), 3 deletions(-) rename proposals/{NNNN-swiftpm-system-module-search-paths.md => 0063-swiftpm-system-module-search-paths.md} (97%) diff --git a/proposals/NNNN-swiftpm-system-module-search-paths.md b/proposals/0063-swiftpm-system-module-search-paths.md similarity index 97% rename from proposals/NNNN-swiftpm-system-module-search-paths.md rename to proposals/0063-swiftpm-system-module-search-paths.md index 5d7eae7f9e..bf97c87f77 100644 --- a/proposals/NNNN-swiftpm-system-module-search-paths.md +++ b/proposals/0063-swiftpm-system-module-search-paths.md @@ -1,9 +1,9 @@ # SwiftPM System Module Search Paths -* Proposal: [SE-NNNN](https://github.com/apple/swift-evolution/blob/master/proposals/NNNN-swiftpm-system-module-search-paths.md) +* Proposal: [SE-0063](https://github.com/apple/swift-evolution/blob/master/proposals/0063-swiftpm-system-module-search-paths.md) * Author: [Max Howell](https://github.com/mxcl) -* Status: **Awaiting review** -* Review manager: Anders Bertelrud +* Status: **Under review** (April 7...13, 2016) +* Review manager: [Anders Bertelrud](https://github.com/abertelrud) ## Introduction diff --git a/schedule.md b/schedule.md index 0260d3399d..7160fab1c5 100644 --- a/schedule.md +++ b/schedule.md @@ -14,6 +14,7 @@ proposals in that process. * March 31...April 5, 2016 [SE-0059: Update API Naming Guidelines and Rewrite Set APIs Accordingly](proposals/0059-updated-set-apis.md) * April 4...11, 2016 [SE-0058: Allow Swift types to provide custom Objective-C representations](proposals/0058-objectivecbridgeable.md) * April 6...12, 2016 [SE-0062: Referencing Objective-C key-paths](proposals/0062-objc-keypaths.md) +* April 7...13, 2016 [SE-0063: SwiftPM System Module Search Paths](proposals/0063-swiftpm-system-module-search-paths.md) ## Upcoming reviews From 6822e9863e50fa2b4b63958f4b47025eccc198ca Mon Sep 17 00:00:00 2001 From: Doug Gregor Date: Thu, 7 Apr 2016 13:56:38 -0700 Subject: [PATCH 21/40] Initiate SE-0064 review --- proposals/0062-objc-keypaths.md | 2 +- ...XXX-property-selectors.md => 0064-property-selectors.md} | 6 +++--- schedule.md | 3 ++- 3 files changed, 6 insertions(+), 5 deletions(-) rename proposals/{XXXX-property-selectors.md => 0064-property-selectors.md} (91%) diff --git a/proposals/0062-objc-keypaths.md b/proposals/0062-objc-keypaths.md index a7513e2f65..e2578a2aa6 100644 --- a/proposals/0062-objc-keypaths.md +++ b/proposals/0062-objc-keypaths.md @@ -2,7 +2,7 @@ * Proposal: [SE-0062](https://github.com/apple/swift-evolution/blob/master/proposals/0062-objc-keypaths.md) * Author(s): [David Hart](https://github.com/hartbit) -* Status: **Under review** (April 6...12, 2016) +* Status: **Under review** (April 7...12, 2016) * Review manager: [Doug Gregor](https://github.com/DougGregor) ## Introduction diff --git a/proposals/XXXX-property-selectors.md b/proposals/0064-property-selectors.md similarity index 91% rename from proposals/XXXX-property-selectors.md rename to proposals/0064-property-selectors.md index eaab23ec57..0fe06cf50d 100644 --- a/proposals/XXXX-property-selectors.md +++ b/proposals/0064-property-selectors.md @@ -1,9 +1,9 @@ # Referencing the Objective-C selector of property getters and setters -* Proposal: SE-XXXX +* Proposal: [SE-0064](https://github.com/apple/swift-evolution/blob/master/proposals/0064-property-selectors.md) * Author(s): [David Hart](https://github.com/hartbit) -* Status: TBD -* Review manager: TBD +* Status: **Under review** (April 7...12, 2016) +* Review manager: [Doug Gregor](https://github.com/DougGregor) ## Introduction diff --git a/schedule.md b/schedule.md index 7160fab1c5..8a124c87bd 100644 --- a/schedule.md +++ b/schedule.md @@ -13,8 +13,9 @@ proposals in that process. * March 31...April 5, 2016 [SE-0036: Requiring Leading Dot Prefixes for Enum Instance Member Implementations](proposals/0036-enum-dot.md) * March 31...April 5, 2016 [SE-0059: Update API Naming Guidelines and Rewrite Set APIs Accordingly](proposals/0059-updated-set-apis.md) * April 4...11, 2016 [SE-0058: Allow Swift types to provide custom Objective-C representations](proposals/0058-objectivecbridgeable.md) -* April 6...12, 2016 [SE-0062: Referencing Objective-C key-paths](proposals/0062-objc-keypaths.md) +* April 7...12, 2016 [SE-0062: Referencing Objective-C key-paths](proposals/0062-objc-keypaths.md) * April 7...13, 2016 [SE-0063: SwiftPM System Module Search Paths](proposals/0063-swiftpm-system-module-search-paths.md) +* April 7...12, 2016 [SE-0064: Referencing the Objective-C selector of property getters and setters](proposals/0064-property-selectors.md) ## Upcoming reviews From 08338831e07c75ab177ce211912f19f5be1732a9 Mon Sep 17 00:00:00 2001 From: Parker Wightman Date: Thu, 7 Apr 2016 15:44:39 -0600 Subject: [PATCH 22/40] Remove redundant paragraph from 0063-swiftpm-system-module-search-paths.md (#249) --- proposals/0063-swiftpm-system-module-search-paths.md | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/proposals/0063-swiftpm-system-module-search-paths.md b/proposals/0063-swiftpm-system-module-search-paths.md index bf97c87f77..99ab9726ef 100644 --- a/proposals/0063-swiftpm-system-module-search-paths.md +++ b/proposals/0063-swiftpm-system-module-search-paths.md @@ -54,13 +54,10 @@ if it is installed with Homebrew or MacPorts. ## Proposed Solution We propose that SwiftPM gains the ability to read `.pc` files written for the -cross-platform `pkg-config` tool. These files describe the missing search paths -that SwiftPM requires. - -We propose that SwiftPM gains the ability to read `.pc` files written for the -cross-platform `pkg-config` tool. These files specify the install location of -system libraries and will allow SwiftPM to preprocess the modulemap changing -the specified header prefixes. +cross-platform `pkg-config` tool. These files describe the missing search paths +that SwiftPM requires. They also specify the install location of system libraries +and will allow SwiftPM to preprocess the modulemap changing the specified header +prefixes. We propose that `Package.swift` is supplemented with metadata that provides the package-install-name for specific platforms. From 8ca4f16d84c0ba8b5dc785517c438fa243e6286a Mon Sep 17 00:00:00 2001 From: Manav Gabhawala Date: Sat, 9 Apr 2016 04:55:16 -0400 Subject: [PATCH 23/40] Update README to move SE-0046 to implemented --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 913019c993..eb7ad8b8d8 100644 --- a/README.md +++ b/README.md @@ -112,6 +112,7 @@ sampling of potentially good ideas that are not in scope for Swift * [SE-0037: Clarify interaction between comments & operators](proposals/0037-clarify-comments-and-operators.md) * [SE-0040: Replacing Equal Signs with Colons For Attribute Arguments](proposals/0040-attributecolons.md) * [SE-0043: Declare variables in 'case' labels with multiple patterns](proposals/0043-declare-variables-in-case-labels-with-multiple-patterns.md) +* [SE-0046: Establish consistent label behavior across all parameters including first labels](proposals/0046-first-label.md) * [SE-0053: Remove explicit use of `let` from Function Parameters](proposals/0053-remove-let-from-function-parameters.md) ### Accepted proposals for Swift 3.0 @@ -127,7 +128,6 @@ sampling of potentially good ideas that are not in scope for Swift * [SE-0039: Modernizing Playground Literals](proposals/0039-playgroundliterals.md) * [SE-0042: Flattening the function type of unapplied method references](proposals/0042-flatten-method-types.md) * [SE-0044: Import as Member](proposals/0044-import-as-member.md) -* [SE-0046: Establish consistent label behavior across all parameters including first labels](proposals/0046-first-label.md) * [SE-0047: Defaulting non-Void functions so they warn on unused results](proposals/0047-nonvoid-warn.md) * [SE-0054: Abolish `ImplicitlyUnwrappedOptional` type](proposals/0054-abolish-iuo.md) * [SE-0055: Make unsafe pointer nullability explicit using Optional](proposals/0055-optional-unsafe-pointers.md) From 4fcdc0428d86d41975cb649e99a6070f431820af Mon Sep 17 00:00:00 2001 From: Erica Sadun Date: Sun, 10 Apr 2016 12:39:29 -0600 Subject: [PATCH 24/40] Added discussion link to SE-0014 --- proposals/0014-constrained-AnySequence.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/proposals/0014-constrained-AnySequence.md b/proposals/0014-constrained-AnySequence.md index 6ba2ba2056..85bbb399a0 100644 --- a/proposals/0014-constrained-AnySequence.md +++ b/proposals/0014-constrained-AnySequence.md @@ -10,6 +10,8 @@ In order to allow `AnySequence` delegate calls to the underlying sequence, its initializer should have extra constraints. +[Swift Evolution Discussion](http://thread.gmane.org/gmane.comp.lang.swift.evolution/1893) + ## Motivation At the moment `AnySequence` does not delegate calls to `SequenceType` protocol From 9fde5d573a30e23e4ae130bc6ce7528838221d78 Mon Sep 17 00:00:00 2001 From: Erica Sadun Date: Sun, 10 Apr 2016 12:44:22 -0600 Subject: [PATCH 25/40] Added links for SE-0015. Note: The review was initially started on the wrong thread with the wrong title and subsequently corrected. --- proposals/0015-tuple-comparison-operators.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/proposals/0015-tuple-comparison-operators.md b/proposals/0015-tuple-comparison-operators.md index 78c608fd34..631dac2289 100644 --- a/proposals/0015-tuple-comparison-operators.md +++ b/proposals/0015-tuple-comparison-operators.md @@ -9,6 +9,10 @@ Implement comparison operators on tuples up to some arity. +[Initial Discussion](http://article.gmane.org/gmane.comp.lang.swift.evolution/980/match=tuple+comparison), [General Discussion](http://thread.gmane.org/gmane.comp.lang.swift.evolution/9723), [Review](http://thread.gmane.org/gmane.comp.lang.swift.evolution/11423/focus=732) + +Note: The review was initially started on the wrong thread with the wrong title and subsequently corrected. + ## Motivation It's annoying to try and compare tuples of comparable values and discover that From ae2d7c24fff7cbdff754d9a4339e4fb02df5c690 Mon Sep 17 00:00:00 2001 From: Erica Sadun Date: Sun, 10 Apr 2016 12:46:37 -0600 Subject: [PATCH 26/40] Added discussion and review links for SE-0016 --- .../0016-initializers-for-converting-unsafe-pointers-to-ints.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/proposals/0016-initializers-for-converting-unsafe-pointers-to-ints.md b/proposals/0016-initializers-for-converting-unsafe-pointers-to-ints.md index 3ff4cf0cb8..947c3993cc 100644 --- a/proposals/0016-initializers-for-converting-unsafe-pointers-to-ints.md +++ b/proposals/0016-initializers-for-converting-unsafe-pointers-to-ints.md @@ -13,6 +13,8 @@ allow users to call C functions with `intptr_t` and `uintptr_t` parameters, and allow users to perform more advanced pointer arithmetic than is allowed by `UnsafePointer`s. +[Swift Evolution Discussion](http://thread.gmane.org/gmane.comp.lang.swift.evolution/10044), [Review](http://thread.gmane.org/gmane.comp.lang.swift.evolution/12696) + ## Motivation ## Swift currently lacks the ability to perform many complex operations on From 98d564770c82204f546f9a2a6d73357fbf061835 Mon Sep 17 00:00:00 2001 From: Erica Sadun Date: Sun, 10 Apr 2016 12:49:12 -0600 Subject: [PATCH 27/40] Added discussion and proposed rewrite links for SE-0017 --- proposals/0017-convert-unmanaged-to-use-unsafepointer.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/proposals/0017-convert-unmanaged-to-use-unsafepointer.md b/proposals/0017-convert-unmanaged-to-use-unsafepointer.md index 141df29ca8..ba1ff7a8ed 100644 --- a/proposals/0017-convert-unmanaged-to-use-unsafepointer.md +++ b/proposals/0017-convert-unmanaged-to-use-unsafepointer.md @@ -9,6 +9,8 @@ The standard library [`Unmanaged` struct](https://github.com/apple/swift/blob/master/stdlib/public/core/Unmanaged.swift) provides a type-safe object wrapper that does not participate in ARC; it allows the user to make manual retain/release calls. +[Swift Evolution Discussion](http://thread.gmane.org/gmane.comp.lang.swift.evolution/9877), [Proposed Rewrite Discussion](http://thread.gmane.org/gmane.comp.lang.swift.evolution/68/) + ## Motivation The following methods are provided for converting to/from Unmanaged: From 30cc2df52bbda7d6b98c8a84315a995f801fa98a Mon Sep 17 00:00:00 2001 From: Erica Sadun Date: Sun, 10 Apr 2016 12:52:17 -0600 Subject: [PATCH 28/40] Added SE Review link for Build Dev proposal SE-0019 --- proposals/0019-package-manager-testing.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/proposals/0019-package-manager-testing.md b/proposals/0019-package-manager-testing.md index c41106ee03..7c91ed6a29 100644 --- a/proposals/0019-package-manager-testing.md +++ b/proposals/0019-package-manager-testing.md @@ -13,6 +13,8 @@ Testing is an essential part of modern software development. Tight integration of testing into the Swift Package Manager will help ensure a stable and reliable packaging ecosystem. +[SE Review Link](http://thread.gmane.org/gmane.comp.lang.swift.evolution/3583) + ## Proposed Solution We propose to extend our conventional package directory layout From 3e063ec0393f015d9320a5eac1d9e19068a10f3d Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Sun, 10 Apr 2016 12:37:55 -0700 Subject: [PATCH 29/40] A New Model for Collections and Indices (#251) --- proposals/NNNN-collections-move-indices.md | 672 +++++++++++++++++++++ 1 file changed, 672 insertions(+) create mode 100644 proposals/NNNN-collections-move-indices.md diff --git a/proposals/NNNN-collections-move-indices.md b/proposals/NNNN-collections-move-indices.md new file mode 100644 index 0000000000..56db714cbe --- /dev/null +++ b/proposals/NNNN-collections-move-indices.md @@ -0,0 +1,672 @@ +# A New Model for Collections and Indices + +* Proposal: [SE-NNNN](https://github.com/apple/swift-evolution/blob/master/proposals/NNNN-collections-move-indices.md) +* Author(s): [Dmitri Gribenko](https://github.com/gribozavr), + [Dave Abrahams](https://github.com/dabrahams), + [Maxim Moiseev](https://github.com/moiseev) +* [Swift-evolution thread](http://news.gmane.org/find-root.php?message_id=CA%2bY5xYfqKR6yC2Q%2dG7D9N7FeY%3dxs1x3frq%3d%3dsyGoqYpOcL9yrw%40mail.gmail.com) +* Status: **Awaiting review** +* Review manager: TBD + +## Summary + +We propose a new model for `Collection`s wherein responsibility for +index traversal is moved from the index to the collection itself. For +example, instead of writing `i.successor()`, one would write +`c.successor(i)`. We also propose the following changes as a +consequence of the new model: + +* A collection's `Index` can be any `Comparable` type. +* The distinction between intervals and ranges disappears, leaving + only ranges. +* A closed range that includes the maximal value of its `Bound` type + is now representable and does not trap. +* Make existing “private” in-place index traversal methods available + publicly. + +## Motivation + +In collections that don't support random access, (string views, sets, +dictionaries, trees, etc.) it's very common that deriving one index +value from another requires somehow inspecting the collection's data. +For example, you could represent an index into a hash table as an +offset into the underlying storage, except that one needs to actually +look at *structure* of the hash table to reach the next bucket. In +the current model, supporting `i.successor()` means that the index +must additionally store not just an offset, but a reference to the +collection's structure. + +The consequences for performance aren't pretty: + +* Code that handles indices has to perform atomic reference counting, + which has significant overhead and can prevent the optimizer from + making other improvements. + +* Additional references to a collections storage block the + library-level copy-on-write optimization: in-place mutation of + uniquely-referenced data. A live index makes underlying storage + non-uniquely referenced, forcing unnecessary copies when the + collection is mutated. In the standard library, `Dictionary` and + `Set` use a double-indirection trick to work around this issue. + Unfortunately, even this trick is not a solution, because (as we + have recently realized) it isn't threadsafe. [^1] + +By giving responsibility for traversal to the collection, we ensure +that operations that need the collection's structure always have it, +without the costs of holding references in indices. + +## Other Benefits + +Although this change is primarily motivated by performance, it has +other significant benefits: + +* Simplifies implementation of non-trivial indices. +* Allows us to eliminate the `Range`/`Interval` distinction. +* Making traversal a direct property of the `Collection` protocol, + rather than its associated `Index` type, is closer to most peoples' + mental model for collections, and simplifies the writing of many + generic constraints. +* Makes it feasible to fix existing concurrency issues in `Set` and + `Dictionary` indices. +* Allows `String` views to share a single index type, letting us + eliminate the need for cumbersome index conversion functions (not + part of this proposal, but planned). + +## Out of Scope + +This proposal intentionally does not: + +* Expand the set of concrete collections provided by the standard + library. +* Expand the set of collection protocols to provide functionality + beyond what is already provided (for example, protocols for sorted + collections, queues etc.) Discussing how other concrete collections + fit into the current protocol hierarchy is in scope, though. + +## Limitations of the Model + +Ideally, our collection model would allow us to implement every +interesting data structure with memory safety, optimal performance, +value semantics, and a variety of other useful properties such as +minimal invalidation of indexes upon mutation. In practice, these +goals and the Swift language model interact in complicated ways, +preventing some designs altogether, and suggesting a variety of +implementation strategies for others that can be selected based on +one's priorities. We've done some in-depth investigation of these +implications, but presenting and explaining them is well beyond the +scope of this proposal. + +We can, however, be fairly sure that this change does not regress our +ability to build any Collections that could have been built in Swift +2.2. After all, it is still *possible* to implement indices that store +references and have the old traversal methods (the collection's +traversal methods would simply forward to those of the index), so we +haven't lost the ability to express anything. + +## Overview of Type And Protocol Changes + +This section covers the proposed structural changes to the library at +a high level. Details such as protocols introduced purely to work +around compiler limitations (e.g. `Indexable` or `IndexableBase`) have +been omitted. For a complete view of the the code +and documentation changes implementing this proposal, please see this +[pull request](https://github.com/apple/swift/pull/2108). + +### Collection Protocol Hierarchy + +In the proposed model, indices don't have any requirements beyond +`Comparable`, so the `ForwardIndex`, `BidirectionalIndex`, and +`RandomAccessIndex` protocols are eliminated. Instead, we introduce +`BidirectionalCollection` and `RandomAccessCollection` to provide the +same traversal distinctions, as shown here: + +``` + +--------+ + |Sequence| + +---+----+ + | + +----+-----+ + |Collection| + +----+-----+ + | + +--------------+-------------+ + | | | + | +--------+--------+ | + | |MutableCollection| | + | +-----------------+ | + | | ++---------+-------------+ +---------+----------------+ +|BidirectionalCollection| |RangeReplaceableCollection| ++---------+-------------+ +--------------------------+ + | + +--------+-------------+ + |RandomAccessCollection| + +----------------------+ +``` + +These protocols compose naturally with the existing protocols +`MutableCollection` and `RangeReplaceableCollection` to describe a +collection's capabilities, e.g. + +```swift +struct Array + : RandomAccessCollection, + MutableCollection, + RangeReplaceableCollection { ... } + +struct UnicodeScalarView : BidirectionalCollection { ... } +``` + +### Range Protocols and Types + +The proposal adds several new types and protocols to support ranges: + +``` + +-------------+ + |RangeProtocol| + +------+------+ + | + +------------+---------------------+ + | | ++---------+-----------+ +----------+--------+ +|HalfOpenRangeProtocol| |ClosedRangeProtocol| ++----+------+---------+ : +-------+------+----+ + | | : | | ++----+---+ | +...........+...........+ | +---+----------+ +|Range| | : RandomAccessCollection: | |ClosedRange| ++========+ | +....+...............+..+ | +==============+ + | | | | + +----+-------+----+ +--+-----+--------------+ + |CountableRange| |CountableClosedRange| + +=================+ +=======================+ +``` + +* The old `Range`, `ClosedInterval`, and + `OpenInterval` are replaced with four new generic range types: + + * Two for general ranges (whose bounds are `Comparable`): `Range` + and `ClosedRange`. Having a separate `ClosedRange` type allows + us to address the vexing inability of the old `Range` to represent + a range containing the maximal value of its bound. + + * Two for ranges that additionally conform to + `RandomAccessCollection` (requiring bounds that are `Strideable` + with `Stride` conforming to `Integer`): `CountableRange` and + `CountableClosedRange`. These types can be folded into + `Range` and `ClosedRange` when Swift acquires conditional + conformance capability. + +We also introduce three new protocols: + +* `RangeProtocol` +* `HalfOpenRangeProtocol` +* `ClosedRangeProtocol` + +These protocols mostly exist facilitate implementation-sharing among +the range types, and would seldom need to be implemented outside the +standard library. + +### The Associated `Indices` Type + +The following code iterates over the indices of all elements in +`collection`: + +```swift +for index in collection.indices { ... } +``` + +In Swift 2, `collection.indices` returned a `Range`, but +because a range is a simple pair of indices and indices can no longer +be advanced on their own, `Range` is no longer iterable. + +In order to keep code like the above working, `Collection` has +acquired an associated `Indices` type that is always iterable, and +three generic types were introduced to provide a default `Indices` for +each `Collection` traversal category: `DefaultIndices`, +`DefaultBidirectionalIndices`, and `DefaultRandomAccessIndices`. +These types store the underlying collection as a means of traversal. +Collections like `Array` whose `Indices` don't need the collection +simply use `typealias Indices = CountableRange`. + +### Expanded Default Slice Types + +Because Swift doesn't support conditional protocol conformances and +the three traversal distinctions have been moved into the `Collection` +hierarchy, the four generic types `Slice`, `MutableSlice`, +`RangeReplaceableSlice`, and `MutableRangeReplaceableSlice` have +become twelve, with the addition of variations such as +`RangeReplaceableBidirectionalSlice`. + +### The `Comparable` Requirement on Indices + +In this model indices store the minimal amount of information required +to describe an element's position. Usually an index can be +represented with one or two `Int`s that efficiently encode the path to +the element from the root of a data structure. Since one is free to +choose the encoding of the “path”, we think it is possible to choose +it in such a way that indices are cheaply comparable. That has been +the case for all of the indices required to implement the standard +library, and a few others we investigated while researching this +change. + +It's worth noting that this requirement isn't strictly +necessary. Without it, though, indices would have no requirements +beyond `Equatable`, and creation of a `Range` would have to be +allowed for any `T` conforming to `Equatable`. As a consequence, most +interesting range operations, such as containment checks, would be +unavailable unless `T` were also `Comparable`, and we'd be unable to +provide comple bounds-checking in the general case. + +That said, the requirement has real benefits. For example, it allows +us to support distance measurement between arbitrary indices, even in +collections without random access traversal. In the old model, +`x.distance(to: y)` for these collections had the undetectable +precondition that `x` precede `y`, with unpredictable consequences for +violation in the general case. + +## Detailed API Changes + +This section describes changes to methods, properties, and associated +types at a high level. Details related to working around compiler +limitations have been omitted. For a complete view of the the code +and documentation changes implementing this proposal, please see this +[pull request](https://github.com/apple/swift/pull/2108). + +### `Collection`s + +The following APIs were added: + +```swift +protocol Collection { + ... + /// A type that can represent the number of steps between pairs of + /// `Index` values where one value is reachable from the other. + /// + /// Reachability is defined by the ability to produce one value from + /// the other via zero or more applications of `successor(of:)`. + associatedtype IndexDistance : SignedInteger = Int + + /// A collection type whose elements are the indices of `self` that + /// are valid for subscripting, in ascending order. + associatedtype Indices : Collection = DefaultIndices + + /// The indices that are valid for subscripting `self`, in ascending order. + /// + /// - Note: `indices` can hold a strong reference to the collection itself, + /// causing the collection to be non-uniquely referenced. If you need to + /// mutate the collection while iterating over its indices, use the + /// `successor(of:)` method starting with `startIndex` to produce indices + /// instead. + /// + /// ``` + /// var c = [10, 20, 30, 40, 50] + /// var i = c.startIndex + /// while i != c.endIndex { + /// c[i] /= 5 + /// i = c.successor(of: i) + /// } + /// // c == [2, 4, 6, 8, 10] + /// ``` + var indices: Indices { get } + + /// Returns the position immediately after `i`. + /// + /// - Precondition: `(startIndex.. Index + + /// Replaces `i` with its successor. + func formSuccessor(i: inout Index) + + /// Returns the result of advancing `i` by `n` positions. + /// + /// - Returns: + /// - If `n > 0`, the `n`th successor of `i`. + /// - If `n < 0`, the `n`th predecessor of `i`. + /// - Otherwise, `i` unmodified. + /// + /// - Precondition: `n >= 0` unless `Self` conforms to + /// `BidirectionalCollection`. + /// - Precondition: + /// - If `n > 0`, `n <= self.distance(from: i, to: self.endIndex)` + /// - If `n < 0`, `n >= self.distance(from: i, to: self.startIndex)` + /// + /// - Complexity: + /// - O(1) if `Self` conforms to `RandomAccessCollection`. + /// - O(`abs(n)`) otherwise. + func index(n: IndexDistance, stepsFrom i: Index) -> Index + + /// Returns the result of advancing `i` by `n` positions, or until it + /// equals `limit`. + /// + /// - Returns: + /// - If `n > 0`, the `n`th successor of `i` or `limit`, whichever + /// is reached first. + /// - If `n < 0`, the `n`th predecessor of `i` or `limit`, whichever + /// is reached first. + /// - Otherwise, `i` unmodified. + /// + /// - Precondition: `n >= 0` unless `Self` conforms to + /// `BidirectionalCollection`. + /// + /// - Complexity: + /// - O(1) if `Self` conforms to `RandomAccessCollection`. + /// - O(`abs(n)`) otherwise. + func index( + n: IndexDistance, stepsFrom i: Index, limitedBy limit: Index + ) -> Index + + /// Advances `i` by `n` positions. + /// + /// - Precondition: `n >= 0` unless `Self` conforms to + /// `BidirectionalCollection`. + /// - Precondition: + /// - If `n > 0`, `n <= self.distance(from: i, to: self.endIndex)` + /// - If `n < 0`, `n >= self.distance(from: i, to: self.startIndex)` + /// + /// - Complexity: + /// - O(1) if `Self` conforms to `RandomAccessCollection`. + /// - O(`abs(n)`) otherwise. + func formIndex(n: IndexDistance, stepsFrom i: inout Index) + + /// Advances `i` by `n` positions, or until it equals `limit`. + /// + /// - Precondition: `n >= 0` unless `Self` conforms to + /// `BidirectionalCollection`. + /// + /// - Complexity: + /// - O(1) if `Self` conforms to `RandomAccessCollection`. + /// - O(`abs(n)`) otherwise. + func formIndex( + n: IndexDistance, stepsFrom i: inout Index, limitedBy limit: Index + ) + + /// Returns the distance between `start` and `end`. + /// + /// - Precondition: `start <= end` unless `Self` conforms to + /// `BidirectionalCollection`. + /// - Complexity: + /// - O(1) if `Self` conforms to `RandomAccessCollection`. + /// - O(`n`) otherwise, where `n` is the method's result. + func distance(from start: Index, to end: Index) -> IndexDistance +} + +protocol BidirectionalCollection { + /// Returns the position immediately preceding `i`. + /// + /// - Precondition: `i > startIndex && i <= endIndex` + func predecessor(of i: Index) -> Index + + /// Replaces `i` with its predecessor. + /// + /// - Precondition: `i > startIndex && i <= endIndex` + func formPredecessor(i: inout Index) +} +``` + +Note: + +* The mutating `formSuccessor`, `formPredecessor`, and the `formIndex` + overloads essentially enshrine the previously-hidden + `_successorInPlace` et al., which can be important for performance + when handling the rare heavyweight index type such as `AnyIndex`. + +* `RandomAccessCollection` does not add any *syntactic* requirements + beyond those of `BidirectionalCollection`. Instead, it places + tighter performance bounds on operations such as `c.index(n, + stepsFrom: i)` (O(1) instead of O(`n`)). + +## `Range`s + +The `RangeProtocol` shown below, along with the description of +[Range Protocols and Types](#range-protocols-and-types) above, provide +a complete picture of the changes to ranges. + +```swift +/// A type that represents a contiguous range of any comparable value. +/// +/// A range contains at least every value `x` where `lowerBound < x` and +/// `x < upperBound`. Individual types that conform to `RangeProtocol` must +/// specify their containment rules for the bounds of the range. +/// +/// The standard library defines two kinds of ranges: closed ranges, +/// represented by `ClosedRangeProtocol`, and half-open ranges, represented by +/// `HalfOpenRangeProtocol`. A closed range contains both its lower and upper +/// bounds, and therefore cannot be empty. A half-open range, on the other +/// hand, contains its lower bound when nonempty but never its upper bound. +/// +/// let closed: ClosedRange = 5...10 +/// closed.contains(5) // true +/// closed.contains(10) // true +/// +/// let halfOpen: Range = 5..<10 +/// halfOpen.contains(5) // true +/// halfOpen.contains(10) // false +/// +/// Not all empty ranges are equal; the bounds of two empty ranges must also be +/// equal for the ranges to be equal. +public protocol RangeProtocol : Equatable { + + /// The representation of the range's endpoints and the values + /// contained in it. + associatedtype Bound : Comparable + + /// Creates an instance with the given bounds. + /// + /// - Note: As this initializer does not check its precondition, it + /// should be used as an optimization only, when one is absolutely + /// certain that `lower <= upper`. In general, the `..<` and `...` + /// operators are to be preferred for forming ranges. + /// + /// - Precondition: `lower <= upper` + init(uncheckedBounds: (lower: Bound, upper: Bound)) + + /// Returns `true` if the range contains the `value`. + /// + /// Any type of range contains every value `x` where + /// `lowerBound < x < upperBound`. `RangeProtocol` makes no requirement as + /// to whether individual range types must contain either their lower or + /// upper bound. + func contains(value: Bound) -> Bool + + /// Returns `true` iff `self` and `other` contain a value in common. + /// + /// Any type of range contains every value `x` where + /// `lowerBound < x < upperBound`. `RangeProtocol` makes no requirement as + /// to whether individual range types must contain either their lower or + /// upper bound. + func overlaps(other: Self) -> Bool + + /// Returns `true` iff `self.contains(x)` is `false` for all values of `x`. + var isEmpty: Bool { get } + + // Note: When the range is also a collection, it is crucial to + // enforce the invariant that lowerBound <= upperBound, or it may be + // empty with startIndex != endIndex. + + /// The range's lower bound. + /// + /// Depending on the concrete type of the range, `lowerBound` may or may not + /// be contained in the range. + var lowerBound: Bound { get } + + /// The range's upper bound. + /// + /// Depending on the concrete type of the range, `upperBound` may or may not + /// be contained in the range. + var upperBound: Bound { get } + + /// Returns `self` clamped to `limits`. + /// + /// The bounds of the result, even if it is empty, are always + /// limited to the bounds of `limits`. + func clamped(to limits: Self) -> Self +} +``` + +Note in particular: + +* In `Range`, `T` is `Comparable` rather than an index + type that can be advanced, so a generalized range is no longer a + `Collection`, and `startIndex`/`endIndex` have become + `lowerBound`/`upperBound`. +* The semantic order of `Interval`'s `clamp` method, which was + unclear at its use-site, has been inverted and updated with a + preposition for clarity. + +## Downsides + +The proposed approach has several disadvantages, which we explore here +in the interest of full disclosure: + +* In Swift 2, `RandomAccessIndex` has operations like `+` that provide + easy access to arbitrary position offsets in some collections. That + could also be seen as discouragement from trying to do random access + operations with less-refined index protocols, because in those cases + one has to resort to constructs like `i.advancedBy(n)`. In this + proposal, there is only `c.index(n, stepsFrom: i)`, which makes + random access equally (in)convenient for all collections, and there + is no particular syntactic penalty for doing things that might turn + out to be inefficient. + +* Index movement is more complex in principle, since it now involves + not only the index, but the collection as well. The impact of this + complexity is limited somewhat because it's very common that code + moving indices occurs in a method of the collection type, where + “implicit `self`” kicks in. The net result is that index + manipulations end up looking like free function calls: + + ```swift + let j = successor(i) // self.successor(i) + let k = index(5, stepsFrom: j) // self.index(5, stepsFrom: j) + ``` + +* The + [new index manipulation methods](https://github.com/apple/swift/blob/swift-3-indexing-model/stdlib/public/core/Collection.swift#L135) + increase the API surface area of `Collection`, which is already + quite large since algorithms are implemented as extensions. + +* Because Swift is unable to express conditional protocol + conformances, implementing this change has required us to create a + great deal of complexity in the standard library API. Aside from + the two excess “`Countable`” range types, there are new overloads + for slicing and twelve distinct slice types that capture all the + combinations of traversal, mutability, and range-replaceability. + While these costs are probably temporary, they are very real in the + meantime. + +* The API complexity mentioned above stresses the type checker, + requiring + [several](https://github.com/apple/swift/commit/1a875cb922fa0c98d51689002df8e202993db2d3) + [changes](https://github.com/apple/swift/commit/6c56af5c1bc319825872a25041ec33ab0092db05) + just to get our test code to type-check in reasonable time. Again, + an ostensibly temporary—but still real—cost. + +## Impact on existing code + +Code that **does not need to change**: + +* Code that works with `Array`, `ArraySlice`, `ContiguousArray`, and + their indices. + +* Code that operates on arbitrary collections and indices (on concrete + instances or in generic context), but does no index traversal. + +* Iteration over collection's indices with `c.indices` does not change. + +* APIs of high-level collection algorithms don't change, even for + algorithms that accept indices as parameters or return indices (e.g., + `index(of:)`, `min()`, `sort()`, `prefix()`, `prefix(upTo:)` etc.) + +Code that **needs to change**: + +* Code that advances indices (`i.successor()`, `i.predecessor()`, + `i.advanced(by:)` etc.) or calculates distances between indices + (`i.distance(to:)`) now needs to call a method on the collection + instead. + + ```swift + // Before: + var i = c.indexOf { $0 % 2 == 0 } + let j = i.successor() + print(c[j]) + + // After: + var i = c.indexOf { $0 % 2 == 0 } // No change in algorithm API. + let j = c.successor(i) // Advancing an index requires a collection instance. + print(c[j]) // No change in subscripting. + ``` + + The transformation from `i.successor()` to `c.successor(i)` is + non-trivial. Performing it correctly requires knowing how to get + the corresponding collection. In general, it is not possible to + perform this migration automatically. A very sophisticated migrator + could handle some easy cases. + +* Custom collection implementations need to change. A simple fix would + be to just move the the methods from indices to collections to satisfy + new protocol requirements. This is a more or less mechanical fix that + does not require design work. This fix would allow the code to + compile and run. + + In order to take advantage of performance improvements in + the new model, and remove reference-counted stored properties from + indices, the representation of the index might need to be redesigned. + + Implementing custom collections, as compared to using collections, is + a niche case. We believe that for custom collection types it is + sufficient to provide clear steps for manual migration that don't + require a redesign. Implementing this in an automated migrator might + be possible, but would be a heroic migration for a rare case. + +## Implementation Status + +[This pull request](https://github.com/apple/swift/pull/2108) contains +a complete implementation. + +## Alternatives considered + +We considered index-less models, for example, [D's +std.range](https://dlang.org/library/std/range.html) (see also [On +Iteration by Andrei +Alexandrescu](http://www.informit.com/articles/printerfriendly/1407357)). +Ranges work well for reference-typed collections, but it is not clear +how to adjust the concept of D's range (similar to `Slice` in Swift) for +mutable value-typed collections. In D, you process a collection by +repeatedly slicing off elements. Once you have found an element that +you would like to mutate, it is not clear how to actually change the +original collection, if the collection and its slice are value types. + +---- + +[^1]: `Dictionary` and `Set` use a double-indirection trick to avoid +disturbing the reference count of the storage with indices. + +``` + +--+ class struct + |RC|---------+ +-----------------+ + +--+ Storage |<---------| DictionaryIndex | + | | | value | + +----------+ +-----------------+ + ^ + +--+ | class struct + |RC|-------------+ +------------+ + +--+ Indirection |<-------| Dictionary | + | ("owner") | | value | + +--------------+ +------------+ +``` + +Instances of `Dictionary` point to an indirection, while +instances of `DictionaryIndex` point to the storage itself. +This allows us to have two separate reference counts. One of +the refcounts tracks just the live `Dictionary` instances, which +allows us to perform precise uniqueness checks. + +The issue that we were previously unaware of is that this scheme +is not thread-safe. When uniquely-referenced storage is being +mutated in place, indices can be concurrently being incremented +(on a different thread). This would be a read/write data race. + +Fixing this data race (to provide memory safety) would require +locking dictionary storage on every access, which would be an +unacceptable performance penalty. From 634be570dcfdb36e2383fc71420964d7f9842dd2 Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Sun, 10 Apr 2016 12:40:23 -0700 Subject: [PATCH 30/40] Assign proposal number SE-0065 --- ...ections-move-indices.md => 0065-collections-move-indices.md} | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) rename proposals/{NNNN-collections-move-indices.md => 0065-collections-move-indices.md} (99%) diff --git a/proposals/NNNN-collections-move-indices.md b/proposals/0065-collections-move-indices.md similarity index 99% rename from proposals/NNNN-collections-move-indices.md rename to proposals/0065-collections-move-indices.md index 56db714cbe..61b7bc867d 100644 --- a/proposals/NNNN-collections-move-indices.md +++ b/proposals/0065-collections-move-indices.md @@ -1,6 +1,6 @@ # A New Model for Collections and Indices -* Proposal: [SE-NNNN](https://github.com/apple/swift-evolution/blob/master/proposals/NNNN-collections-move-indices.md) +* Proposal: [SE-0065](https://github.com/apple/swift-evolution/blob/master/proposals/0065-collections-move-indices.md) * Author(s): [Dmitri Gribenko](https://github.com/gribozavr), [Dave Abrahams](https://github.com/dabrahams), [Maxim Moiseev](https://github.com/moiseev) From 2f5f6bc9072e763b2802c6e0773a5062f4214c77 Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Sun, 10 Apr 2016 12:42:35 -0700 Subject: [PATCH 31/40] Add SE-0065 to schedule.md as unscheduled --- schedule.md | 1 + 1 file changed, 1 insertion(+) diff --git a/schedule.md b/schedule.md index 8a124c87bd..56b53c79bf 100644 --- a/schedule.md +++ b/schedule.md @@ -32,6 +32,7 @@ proposals in that process. * [SE-0052: Change IteratorType post-nil guarantee](proposals/0052-iterator-post-nil-guarantee.md) * [SE-0060: Enforcing order of defaulted parameters](proposals/0060-defaulted-parameter-order.md) * [SE-0061: Add Generic Result and Error Handling to autoreleasepool()](proposals/0061-autoreleasepool-signature.md) +* [SE-0065: A New Model For Collections and Indices)](proposals/0065-collections-move-indices.md) [evolution-process]: process.md "The Swift evolution process" From bacb67d85d38006cf92a8f94f9a5ccd528c91b57 Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Sun, 10 Apr 2016 12:42:59 -0700 Subject: [PATCH 32/40] fix typo --- schedule.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/schedule.md b/schedule.md index 56b53c79bf..964726ef96 100644 --- a/schedule.md +++ b/schedule.md @@ -32,7 +32,7 @@ proposals in that process. * [SE-0052: Change IteratorType post-nil guarantee](proposals/0052-iterator-post-nil-guarantee.md) * [SE-0060: Enforcing order of defaulted parameters](proposals/0060-defaulted-parameter-order.md) * [SE-0061: Add Generic Result and Error Handling to autoreleasepool()](proposals/0061-autoreleasepool-signature.md) -* [SE-0065: A New Model For Collections and Indices)](proposals/0065-collections-move-indices.md) +* [SE-0065: A New Model For Collections and Indices](proposals/0065-collections-move-indices.md) [evolution-process]: process.md "The Swift evolution process" From 1ed28954d54131a4a900567d23bc653e1690b39a Mon Sep 17 00:00:00 2001 From: Chris Lattner Date: Sun, 10 Apr 2016 14:39:08 -0700 Subject: [PATCH 33/40] lets kick off 0065 --- proposals/0065-collections-move-indices.md | 4 ++-- schedule.md | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/proposals/0065-collections-move-indices.md b/proposals/0065-collections-move-indices.md index 61b7bc867d..85d39292fd 100644 --- a/proposals/0065-collections-move-indices.md +++ b/proposals/0065-collections-move-indices.md @@ -5,8 +5,8 @@ [Dave Abrahams](https://github.com/dabrahams), [Maxim Moiseev](https://github.com/moiseev) * [Swift-evolution thread](http://news.gmane.org/find-root.php?message_id=CA%2bY5xYfqKR6yC2Q%2dG7D9N7FeY%3dxs1x3frq%3d%3dsyGoqYpOcL9yrw%40mail.gmail.com) -* Status: **Awaiting review** -* Review manager: TBD +* Status: **Under Active review** April 10...18, 2016 +* Review manager: [Chris Lattner](https://github.com/lattner) ## Summary diff --git a/schedule.md b/schedule.md index 964726ef96..7e3ad8c7b3 100644 --- a/schedule.md +++ b/schedule.md @@ -16,6 +16,7 @@ proposals in that process. * April 7...12, 2016 [SE-0062: Referencing Objective-C key-paths](proposals/0062-objc-keypaths.md) * April 7...13, 2016 [SE-0063: SwiftPM System Module Search Paths](proposals/0063-swiftpm-system-module-search-paths.md) * April 7...12, 2016 [SE-0064: Referencing the Objective-C selector of property getters and setters](proposals/0064-property-selectors.md) +* April 10...18, 2016 [SE-0065: A New Model For Collections and Indices](proposals/0065-collections-move-indices.md) ## Upcoming reviews @@ -32,7 +33,6 @@ proposals in that process. * [SE-0052: Change IteratorType post-nil guarantee](proposals/0052-iterator-post-nil-guarantee.md) * [SE-0060: Enforcing order of defaulted parameters](proposals/0060-defaulted-parameter-order.md) * [SE-0061: Add Generic Result and Error Handling to autoreleasepool()](proposals/0061-autoreleasepool-signature.md) -* [SE-0065: A New Model For Collections and Indices](proposals/0065-collections-move-indices.md) [evolution-process]: process.md "The Swift evolution process" From 8f2599826e0d9ec6ad5ab5287d49cf11823d759f Mon Sep 17 00:00:00 2001 From: Nate Cook Date: Sun, 10 Apr 2016 17:21:41 -0500 Subject: [PATCH 34/40] Minor edits to 'collections move indices' proposal --- proposals/0065-collections-move-indices.md | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/proposals/0065-collections-move-indices.md b/proposals/0065-collections-move-indices.md index 85d39292fd..cba585fe1f 100644 --- a/proposals/0065-collections-move-indices.md +++ b/proposals/0065-collections-move-indices.md @@ -13,7 +13,7 @@ We propose a new model for `Collection`s wherein responsibility for index traversal is moved from the index to the collection itself. For example, instead of writing `i.successor()`, one would write -`c.successor(i)`. We also propose the following changes as a +`c.successor(of: i)`. We also propose the following changes as a consequence of the new model: * A collection's `Index` can be any `Comparable` type. @@ -21,7 +21,7 @@ consequence of the new model: only ranges. * A closed range that includes the maximal value of its `Bound` type is now representable and does not trap. -* Make existing “private” in-place index traversal methods available +* Existing “private” in-place index traversal methods are now available publicly. ## Motivation @@ -255,7 +255,7 @@ beyond `Equatable`, and creation of a `Range` would have to be allowed for any `T` conforming to `Equatable`. As a consequence, most interesting range operations, such as containment checks, would be unavailable unless `T` were also `Comparable`, and we'd be unable to -provide comple bounds-checking in the general case. +provide bounds-checking in the general case. That said, the requirement has real benefits. For example, it allows us to support distance measurement between arbitrary indices, even in @@ -537,7 +537,7 @@ in the interest of full disclosure: manipulations end up looking like free function calls: ```swift - let j = successor(i) // self.successor(i) + let j = successor(of: i) // self.successor(of: i) let k = index(5, stepsFrom: j) // self.index(5, stepsFrom: j) ``` @@ -572,7 +572,7 @@ Code that **does not need to change**: * Code that operates on arbitrary collections and indices (on concrete instances or in generic context), but does no index traversal. -* Iteration over collection's indices with `c.indices` does not change. +* Iteration over collections' indices with `c.indices` does not change. * APIs of high-level collection algorithms don't change, even for algorithms that accept indices as parameters or return indices (e.g., @@ -587,17 +587,17 @@ Code that **needs to change**: ```swift // Before: - var i = c.indexOf { $0 % 2 == 0 } + var i = c.index { $0 % 2 == 0 } let j = i.successor() print(c[j]) // After: - var i = c.indexOf { $0 % 2 == 0 } // No change in algorithm API. - let j = c.successor(i) // Advancing an index requires a collection instance. + var i = c.index { $0 % 2 == 0 } // No change in algorithm API. + let j = c.successor(of: i) // Advancing an index requires a collection instance. print(c[j]) // No change in subscripting. ``` - The transformation from `i.successor()` to `c.successor(i)` is + The transformation from `i.successor()` to `c.successor(of: i)` is non-trivial. Performing it correctly requires knowing how to get the corresponding collection. In general, it is not possible to perform this migration automatically. A very sophisticated migrator From 21fac2e8034e79e4f44c1c8799808fc8cba83395 Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Sun, 10 Apr 2016 15:28:22 -0700 Subject: [PATCH 35/40] Add missed apostrophe --- proposals/0065-collections-move-indices.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/proposals/0065-collections-move-indices.md b/proposals/0065-collections-move-indices.md index cba585fe1f..7579f7c1dd 100644 --- a/proposals/0065-collections-move-indices.md +++ b/proposals/0065-collections-move-indices.md @@ -42,7 +42,7 @@ The consequences for performance aren't pretty: which has significant overhead and can prevent the optimizer from making other improvements. -* Additional references to a collections storage block the +* Additional references to a collection's storage block the library-level copy-on-write optimization: in-place mutation of uniquely-referenced data. A live index makes underlying storage non-uniquely referenced, forcing unnecessary copies when the From daa28b131ee14e30577cbeb752685155aee15e64 Mon Sep 17 00:00:00 2001 From: Joe Groff Date: Wed, 13 Apr 2016 10:30:40 -0700 Subject: [PATCH 36/40] SE-0058 has been deferred. --- README.md | 1 + proposals/0058-objectivecbridgeable.md | 21 ++++++++++++++++++++- schedule.md | 1 - 3 files changed, 21 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index eb7ad8b8d8..d2fd7c21c5 100644 --- a/README.md +++ b/README.md @@ -180,3 +180,4 @@ sooner. ### Deferred for Future Discussion * [SE-0026: Abstract classes and methods](proposals/0026-abstract-classes-and-methods.md) +* [SE-0058: Allow Swift types to provide custom Objective-C representations](proposals/0058-objectivecbridgeable.md) diff --git a/proposals/0058-objectivecbridgeable.md b/proposals/0058-objectivecbridgeable.md index 68959c9806..622d11f7a6 100644 --- a/proposals/0058-objectivecbridgeable.md +++ b/proposals/0058-objectivecbridgeable.md @@ -2,7 +2,7 @@ * Proposal: SE-0058 * Author(s): [Russ Bishop](https://github.com/russbishop), [Doug Gregor](https://github.com/DougGregor) -* Status: **Review** +* Status: **[Deferred](#rationale)** * Review manager: [Joe Groff](https://github.com/jckarter) @@ -243,3 +243,22 @@ This can always be implemented in the future if it is desired. It is intended that when and if Swift 3 adopts conditional protocol conformance that the standard library types such as `Array` and `Dictionary` will declare conditional conformance to `ObjectiveCBridgeable` if their element types are `ObjectiveCBridgeable` (with explicitly declared conformance for built-ins like `Int`). +------------------------------------------------------------------------------- + +# Rationale + +On April 12, 2016, the core team decided to **defer** this proposal from +Swift 3. We agree that it would be valuable to give library authors the +ability to bridge their own types from Objective-C into Swift using the +same mechanisms as Foundation. However, we lack the confidence and +implementation experience to commit to `_ObjectiveCBridgeable` in its +current form as public API. In its current form, as its name suggests, the +protocol was designed to accommodate the specific needs of bridging +Objective-C object types to Swift value types. In the future, we may +want to bridge with other platforms, including C++ value types or +other object systems such as COM, GObject, JVM, or CLR. It isn't clear at +this point whether these would be served by a generalization of the existing +mechanism, or by bespoke bridging protocols tailored to each case. This +is a valuable area to explore, but we feel that it is too early at this +point to accept our current design as public API. + diff --git a/schedule.md b/schedule.md index 7e3ad8c7b3..1a66033533 100644 --- a/schedule.md +++ b/schedule.md @@ -12,7 +12,6 @@ proposals in that process. * March 31...April 5, 2016 [SE-0056: Allow trailing closures in `guard` conditions](proposals/0056-trailing-closures-in-guard.md) * March 31...April 5, 2016 [SE-0036: Requiring Leading Dot Prefixes for Enum Instance Member Implementations](proposals/0036-enum-dot.md) * March 31...April 5, 2016 [SE-0059: Update API Naming Guidelines and Rewrite Set APIs Accordingly](proposals/0059-updated-set-apis.md) -* April 4...11, 2016 [SE-0058: Allow Swift types to provide custom Objective-C representations](proposals/0058-objectivecbridgeable.md) * April 7...12, 2016 [SE-0062: Referencing Objective-C key-paths](proposals/0062-objc-keypaths.md) * April 7...13, 2016 [SE-0063: SwiftPM System Module Search Paths](proposals/0063-swiftpm-system-module-search-paths.md) * April 7...12, 2016 [SE-0064: Referencing the Objective-C selector of property getters and setters](proposals/0064-property-selectors.md) From a26ae2475cc3838f3285040d926bea2e8ad434a6 Mon Sep 17 00:00:00 2001 From: Joe Groff Date: Wed, 13 Apr 2016 10:36:40 -0700 Subject: [PATCH 37/40] Add "Rationale" section to proposal template. When the core team makes a decision regarding a proposal, we will start adding it to the proposal here. --- 0000-template.md | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/0000-template.md b/0000-template.md index 014fc590f0..816b171b6f 100644 --- a/0000-template.md +++ b/0000-template.md @@ -2,7 +2,7 @@ * Proposal: [SE-NNNN](https://github.com/apple/swift-evolution/blob/master/proposals/NNNN-name.md) * Author(s): [Swift Developer](https://github.com/swiftdev) -* Status: **Awaiting review** +* Status: **[Awaiting review](#rationale)** * Review manager: TBD ## Introduction @@ -50,3 +50,10 @@ automatically? Describe alternative approaches to addressing the same problem, and why you chose this approach instead. +------------------------------------------------------------------------------- + +# Rationale + +On Smarch 13, 20XX, the core team decided to **(TBD)** this proposal. +When the core team makes a decision regarding this proposal, +their rationale for the decision will be written here. From 1a821cf7ccbdf1d7566e9ce2e991bdd835ba3b7d Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Wed, 13 Apr 2016 16:14:54 -0700 Subject: [PATCH 38/40] Add missing generic conversion between ranges (#255) --- proposals/0065-collections-move-indices.md | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/proposals/0065-collections-move-indices.md b/proposals/0065-collections-move-indices.md index 7579f7c1dd..fdbff18709 100644 --- a/proposals/0065-collections-move-indices.md +++ b/proposals/0065-collections-move-indices.md @@ -7,6 +7,10 @@ * [Swift-evolution thread](http://news.gmane.org/find-root.php?message_id=CA%2bY5xYfqKR6yC2Q%2dG7D9N7FeY%3dxs1x3frq%3d%3dsyGoqYpOcL9yrw%40mail.gmail.com) * Status: **Under Active review** April 10...18, 2016 * Review manager: [Chris Lattner](https://github.com/lattner) +* Revision: 2 +* Previous Revisions: + [1](https://github.com/apple/swift-evolution/blob/21fac2e8034e79e4f44c1c8799808fc8cba83395/proposals/0065-collections-move-indices.md) + (as submitted) ## Summary @@ -502,6 +506,18 @@ public protocol RangeProtocol : Equatable { /// limited to the bounds of `limits`. func clamped(to limits: Self) -> Self } + +/// Conversion from one range to another. +extension RangeProtocol where Bound : Strideable, Bound.Stride : Integer { + /// Creates an instance equivalent to `other`. + /// + /// - Precondition: an equivalent range is representable as an + /// instance of `Self`. For example, `Range(0...Int.max)` + /// violates this precondition because an equivalent `Range` + /// would need an `upperBound` equal to `Int.max + 1`, which + /// is unrepresentable as an `Int`. + public init(_ other: Other) +} ``` Note in particular: From 76f63a71911d657bfc7b3c333c1ff3d8feb31366 Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Wed, 13 Apr 2016 16:28:07 -0700 Subject: [PATCH 39/40] Drop asymmetrical prepositions in mutating/nonmutating pairs --- proposals/0065-collections-move-indices.md | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/proposals/0065-collections-move-indices.md b/proposals/0065-collections-move-indices.md index fdbff18709..3050038385 100644 --- a/proposals/0065-collections-move-indices.md +++ b/proposals/0065-collections-move-indices.md @@ -17,7 +17,7 @@ We propose a new model for `Collection`s wherein responsibility for index traversal is moved from the index to the collection itself. For example, instead of writing `i.successor()`, one would write -`c.successor(of: i)`. We also propose the following changes as a +`c.successor(i)`. We also propose the following changes as a consequence of the new model: * A collection's `Index` can be any `Comparable` type. @@ -287,7 +287,7 @@ protocol Collection { /// `Index` values where one value is reachable from the other. /// /// Reachability is defined by the ability to produce one value from - /// the other via zero or more applications of `successor(of:)`. + /// the other via zero or more applications of `successor(_)`. associatedtype IndexDistance : SignedInteger = Int /// A collection type whose elements are the indices of `self` that @@ -299,7 +299,7 @@ protocol Collection { /// - Note: `indices` can hold a strong reference to the collection itself, /// causing the collection to be non-uniquely referenced. If you need to /// mutate the collection while iterating over its indices, use the - /// `successor(of:)` method starting with `startIndex` to produce indices + /// `successor(_)` method starting with `startIndex` to produce indices /// instead. /// /// ``` @@ -307,7 +307,7 @@ protocol Collection { /// var i = c.startIndex /// while i != c.endIndex { /// c[i] /= 5 - /// i = c.successor(of: i) + /// i = c.successor(i) /// } /// // c == [2, 4, 6, 8, 10] /// ``` @@ -317,7 +317,7 @@ protocol Collection { /// /// - Precondition: `(startIndex.. Index + func successor(_ i: Index) -> Index /// Replaces `i` with its successor. func formSuccessor(i: inout Index) @@ -399,7 +399,7 @@ protocol BidirectionalCollection { /// Returns the position immediately preceding `i`. /// /// - Precondition: `i > startIndex && i <= endIndex` - func predecessor(of i: Index) -> Index + func predecessor(_ i: Index) -> Index /// Replaces `i` with its predecessor. /// @@ -553,7 +553,7 @@ in the interest of full disclosure: manipulations end up looking like free function calls: ```swift - let j = successor(of: i) // self.successor(of: i) + let j = successor(i) // self.successor(i) let k = index(5, stepsFrom: j) // self.index(5, stepsFrom: j) ``` @@ -609,11 +609,11 @@ Code that **needs to change**: // After: var i = c.index { $0 % 2 == 0 } // No change in algorithm API. - let j = c.successor(of: i) // Advancing an index requires a collection instance. + let j = c.successor(i) // Advancing an index requires a collection instance. print(c[j]) // No change in subscripting. ``` - The transformation from `i.successor()` to `c.successor(of: i)` is + The transformation from `i.successor()` to `c.successor(i)` is non-trivial. Performing it correctly requires knowing how to get the corresponding collection. In general, it is not possible to perform this migration automatically. A very sophisticated migrator From d44c3e7c189ba39ddf8a914ae8b78b71f88fdcdf Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Wed, 13 Apr 2016 16:36:24 -0700 Subject: [PATCH 40/40] Rewrite the `index` methods as `location`... per http://news.gmane.org/find-root.php?message_id=m2a8kx2kdm.fsf%40fripp.apple.com --- proposals/0065-collections-move-indices.md | 27 +++++++++++----------- 1 file changed, 13 insertions(+), 14 deletions(-) diff --git a/proposals/0065-collections-move-indices.md b/proposals/0065-collections-move-indices.md index 3050038385..0135833a2c 100644 --- a/proposals/0065-collections-move-indices.md +++ b/proposals/0065-collections-move-indices.md @@ -7,10 +7,11 @@ * [Swift-evolution thread](http://news.gmane.org/find-root.php?message_id=CA%2bY5xYfqKR6yC2Q%2dG7D9N7FeY%3dxs1x3frq%3d%3dsyGoqYpOcL9yrw%40mail.gmail.com) * Status: **Under Active review** April 10...18, 2016 * Review manager: [Chris Lattner](https://github.com/lattner) -* Revision: 2 +* Revision: 3 * Previous Revisions: [1](https://github.com/apple/swift-evolution/blob/21fac2e8034e79e4f44c1c8799808fc8cba83395/proposals/0065-collections-move-indices.md) - (as submitted) + (as submitted), + [2](https://github.com/apple/swift-evolution/blob/1a821cf7ccbdf1d7566e9ce2e991bdd835ba3b7d/proposals/0065-collections-move-indices.md) ## Summary @@ -338,7 +339,7 @@ protocol Collection { /// - Complexity: /// - O(1) if `Self` conforms to `RandomAccessCollection`. /// - O(`abs(n)`) otherwise. - func index(n: IndexDistance, stepsFrom i: Index) -> Index + func location(i: Index, offsetBy n: IndexDistance) -> Index /// Returns the result of advancing `i` by `n` positions, or until it /// equals `limit`. @@ -356,9 +357,8 @@ protocol Collection { /// - Complexity: /// - O(1) if `Self` conforms to `RandomAccessCollection`. /// - O(`abs(n)`) otherwise. - func index( - n: IndexDistance, stepsFrom i: Index, limitedBy limit: Index - ) -> Index + func location( + i: Index, offsetBy n: IndexDistance, limitedBy limit: Index) -> Index /// Advances `i` by `n` positions. /// @@ -371,7 +371,7 @@ protocol Collection { /// - Complexity: /// - O(1) if `Self` conforms to `RandomAccessCollection`. /// - O(`abs(n)`) otherwise. - func formIndex(n: IndexDistance, stepsFrom i: inout Index) + func formLocation(i: inout Index, offsetBy n: IndexDistance) /// Advances `i` by `n` positions, or until it equals `limit`. /// @@ -381,9 +381,8 @@ protocol Collection { /// - Complexity: /// - O(1) if `Self` conforms to `RandomAccessCollection`. /// - O(`abs(n)`) otherwise. - func formIndex( - n: IndexDistance, stepsFrom i: inout Index, limitedBy limit: Index - ) + func formLocation( + i: inout Index, offsetBy n: IndexDistance, limitedBy limit: Index) /// Returns the distance between `start` and `end`. /// @@ -417,8 +416,8 @@ Note: * `RandomAccessCollection` does not add any *syntactic* requirements beyond those of `BidirectionalCollection`. Instead, it places - tighter performance bounds on operations such as `c.index(n, - stepsFrom: i)` (O(1) instead of O(`n`)). + tighter performance bounds on operations such as `c.location(i, + offsetBy: n)` (O(1) instead of O(`n`)). ## `Range`s @@ -540,7 +539,7 @@ in the interest of full disclosure: could also be seen as discouragement from trying to do random access operations with less-refined index protocols, because in those cases one has to resort to constructs like `i.advancedBy(n)`. In this - proposal, there is only `c.index(n, stepsFrom: i)`, which makes + proposal, there is only `c.location(i, offsetBy: n)`, which makes random access equally (in)convenient for all collections, and there is no particular syntactic penalty for doing things that might turn out to be inefficient. @@ -554,7 +553,7 @@ in the interest of full disclosure: ```swift let j = successor(i) // self.successor(i) - let k = index(5, stepsFrom: j) // self.index(5, stepsFrom: j) + let k = location(j, offsetBy: 5) // self.location(j, offsetBy: 5) ``` * The