Skip to content

[3.1] Fix source compatibility problems with conforming to multiple Collection axes at once. #7151

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Conversation

jckarter
Copy link
Contributor

Explanation: Improvements to the type checker and standard library in Swift 3.1 exposed the lack of default implementations for a SubSequence type and slicing operator when a type conformed to multiple axes of Collection simultaneously (Mutable vs non, RangeReplaceable vs non, and/or forward, Bidirectional or RandomAccess). Providing those default implementations then exposed remaining deficiencies in our handling of potential witnesses for associated type inference. This patch fixes these issues by constraining the type checker to only filter and compare witnesses by the constraints they require of the Self type, which are invariant of what associated types we end up inferring, and then filling in the missing default implementations in the standard library.

Scope: Many users writing custom collection types report this as a compatibility regression from 3.0.

Issue: rdar://problem/30228957

Risk: Moderate; there is a nonzero chance of knock-on effects. However, not taking this patch means that a large class of useful programs that compiled in 3.0 won't compile in 3.1 without boilerplatey source changes that get incorrectly rejected in 3.0, making it impossible to get code working in both versions. (See realm/realm-swift#4586 (comment) for an example.)

Testing: Swift CI; realm-swift project

…inference.

The associated type inference is a bit unusual, since we want to be able to infer associated types from protocol extension implementations that themselves depend on the types being inferred a certain way, e.g.:

```
protocol Runcible { associatedtype Spoon; func runce(_: Spoon) }
extension Runcible where Spoon == Hat {
  func runce(_ hat: Hat) {}
}
```

For this reason, we would collect potential witnesses from all possible extensions of the type without immediately checking the constraints on each extension. This could lead to an inconsistency where, when ranking potential witnesses, associated type inference would end up picking the "best" candidate as something that can't even be used by the type we're inferring the witness for, leading to incomprehensible behavior. The ranking criterion itself is also flawed, because `TC.compareDeclarations` is normally comparing candidates for the same well-typed function invocation, but during associated type inference we haven't even established the type system we're comparing candidates within. Witness candidates from extensions with mutually exclusive associated type constraints but otherwise more specific constraints would be unnecessarily dismissed as ambiguous because neither candidate's generic signature is a match for the other's.

Both problems can be mitigated by looking at only the constraints for protocol extensions that specifically constrain the `Self` type, since those conformances are always explicit in the source code and therefore independent of associated type inference. We can pre-filter witness candidates by rejecting candidates for which the conforming type doesn't match the extension's Self constraints. We can score multiple witness candidates by looking only at the relative constraints they put on `Self`, considering a witness from a context that more specifically constrains Self to be a better candidate; we should ignore the associated type constraints for this scoring because we don't even know if they apply given the solution we'll ultimately pick. There's probably a more systemic way to go about this, but targeted fixes for both of these problems, along with a following patch to the standard library, restores source compatibility for Collection conformers, fixing rdar://problem/30228957.
…ex>) for combinations of [Mutable][RangeReplaceable][Bidirectional|RandomAccess]Collection.

These were overlooked, and somehow code that attempted to make a minimal collection conform to RangeReplaceableCollection and RandomAccessCollection managed to compile successfully in Swift 3.0, but in Swift 3.1…*something* changed to reject a type that conforms to both due to the lack of a suitable default slicing subscript implementation in the stdlib that provided all the requirements. Fill in these missing implementations, fixing rdar://problem/30228957.
@jckarter
Copy link
Contributor Author

@swift-ci Please test

@swift-ci
Copy link
Contributor

Build failed
Jenkins build - Swift Test OS X Platform
Git Commit - d9d345f
Test requested by - @jckarter

@jckarter jckarter changed the title Fix source compatibility problems with conforming to multiple Collection axes at once. [3.1] Fix source compatibility problems with conforming to multiple Collection axes at once. Jan 30, 2017
@jckarter
Copy link
Contributor Author

@swift-ci Please clean test OS X

@tkremenek tkremenek merged commit 06dcf30 into swiftlang:swift-3.1-branch Jan 31, 2017
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants