Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[stdlib] Remove magnitude-based overload of abs(_:).
The standard library has two versions of the `abs(_:)` function: ``` func abs<T : SignedNumeric>(_ x: T) -> T where T.Magnitude == T func abs<T : SignedNumeric & Comparable>(_ x: T) -> T ``` The first is more specialized than the second because `T.Magnitude` is known to conform to `Comparable`. Indeed, it’s a more specialized implementation that returns `magnitude`. However, this overload behaves oddly: in the expression `abs(-8)`, the type checker will pick the first overload because it is more specialized. That’s a general guiding principle for overloading: pick the most specialized overload that works. However, to select that overload, it needs to pick a type for the literal “8” for which that overload works, and it chooses `Double`. The “obvious” answer, `Int`, doesn’t work because `Int.Magnitude == UInt`. There is a conflict between the two rules, here: we prefer more-specialized overloads (but we’ll fall back to less-specialized if those don’t work) and we prefer to use `Int` for integer literals (but we’ll fall back to `Double` if it doesn’t work). We have a few options from a type-checker perspective: 1. Consider the more-specialized-function rule to be more important 2. Consider the integer-literals-prefer-`Int` rule to be more important 3. Call the result ambiguous and make the user annotate it The type checker currently does #1, although at some point in the past it did #2. Moving forward, #1 is a better choice because it prunes the number of overloads that need to be considered: if the more-specialized overload succeeds its type-check, the others need not be considered. It’s also easier to reason about than the literal-scoring approach, because there can be a direct definition for “more specialized than” that can be reasoned about. I think we should dodge the issue by removing the more-specialized version of `abs(_:)`. Its use of `magnitude` seems unlikely to provide a significant performance benefit, and the presence of overloading either forces us to consider both overloads always (which is bad for type checker performance) or accept the regression that `abs(-8)` is `Double`. Better to eliminate the overloading and, if needed in the future, find a better way to introduce the more-specialized implementation without it being a separate signature. Fixes rdar://problem/42345366.
- Loading branch information