You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Given this code to switch between view edges using a trait collection:
import UIKit
publicprotocolViewEdgeConvertible{func fixedViewEdge(
using traitCollection:UITraitCollection?)->FixedViewEdgefunc directionalViewEdge(
using traitCollection:UITraitCollection?)->DirectionalViewEdge}publicfunc==(lhs:ViewEdgeConvertible, rhs:ViewEdgeConvertible)->Bool{return lhs.fixedViewEdge(using:nil)== rhs.fixedViewEdge(using:nil)}publicenumFixedViewEdge:Equatable{case top
case left
case right
case bottom
}extensionFixedViewEdge:ViewEdgeConvertible{publicfunc fixedViewEdge(
using traitCollection:UITraitCollection?)->FixedViewEdge{self}publicfunc directionalViewEdge(
using traitCollection:UITraitCollection?)->DirectionalViewEdge{
switch (self, traitCollection?.layoutDirection){case(.top, _):return.top
case(.left,.rightToLeft):return.trailing
case(.left, _):return.leading
case(.right,.rightToLeft):return.leading
case(.right, _):return.trailing
case(.bottom, _):return.bottom
}}}publicenumDirectionalViewEdge:Equatable{case top
case leading
case trailing
case bottom
}extensionDirectionalViewEdge:ViewEdgeConvertible{publicfunc fixedViewEdge(
using traitCollection:UITraitCollection?)->FixedViewEdge{
switch (self, traitCollection?.layoutDirection){case(.top, _):return.top
case(.leading,.rightToLeft):return.right
case(.leading, _):return.left
case(.trailing,.rightToLeft):return.left
case(.trailing, _):return.right
case(.bottom, _):return.bottom
}}publicfunc directionalViewEdge(
using traitCollection:UITraitCollection?)->DirectionalViewEdge{self}}
The == method produces this warning: “All paths through this function will call itself.” At runtime, this creates an infinite loop. I expected the == method to use the synthesized Equatable conformance of FixedViewEdge instead of the protocol method.
As a workaround, I can implement == directly on FixedViewEdge:
This semantics seems intended, if unfortunate given the set of protocol conformances here. Equatable is not a more specific protocol than ViewEdgeConvertible from the perspective of the witness matching algorithm. Others have noted on the forums that this should be expressed as a defaulted requirement in a protocol extension for ViewEdgeConvertible instead.
Yeah, unfortunately this is correct behavior. The reason is because == on Equatable is generic over Self, whereas the == that you've written here is not, and the compiler will always prefer non-generic overloads over generic ones. It works when you implement == for FixedViewEdge because that new overload is more specific than the one that takes in existential types, so lhs.fixedViewEdge(using: nil) == rhs.fixedViewEdge(using: nil) will choose that overload.
Environment
Xcode 11.6
macOS 10.15.6
Additional Detail from JIRA
md5: 789acddb3405b4be56cd1dd9b9b62cef
Issue Description:
Given this code to switch between view edges using a trait collection:
The == method produces this warning: “All paths through this function will call itself.” At runtime, this creates an infinite loop. I expected the == method to use the synthesized Equatable conformance of FixedViewEdge instead of the protocol method.
As a workaround, I can implement == directly on FixedViewEdge:
This avoids the issue.
The text was updated successfully, but these errors were encountered: