Potential Effects of SE-0286 on ReactiveSwift
grantjbutler opened this issue · 8 comments
I've recently updated to Xcode 12 beta 5. Since doing this, I've noticed in a number of places where I'm doing Signal.merge
across a number of Signal
instances that I've started getting errors such as Cannot convert value of type 'Signal<AnalyticData, Never>' to expected argument type 'Signal<(ConversationContext, String) -> AnalyticData, Never>'
. After doing some investigation, my best guess is that this is the result of SE-0286 being added in Xcode 12 beta 5. When I have something like intSignal.map { String($0) }
, in some cases the compiler chooses map(value:)
over the map
that takes a closure. I'm not entirely sure on what all causes the compiler to make that decision, but the end result is that I have a Signal<(Int) -> String, Error>
instead of a Signal<String, Error>
.
I've attached a sample project that demonstrates a few of the cases where I've run into this. I'm not sure exactly what the right outcome of this is. That is, if the fix for this is to make a change to ReactiveSwift, or if the fix is to report this back to the Swift team about the impact of SE-0286. At the very least, I'm creating this ticket to document this behavior and make you (the maintainers of ReactiveSwift) aware of it.
Same here. Based on this I think Apple should roll back multiple trailing closure syntax. Sugar should never be a breaking change...
That overload resolution bug in the compiler had happened before but was resolved. Seems like it is time to file it again.
Also related, there's a recent bug open: https://bugs.swift.org/browse/SR-13415
I filed https://bugs.swift.org/browse/SR-13453, although what I reproduced doesn't seem to manifest the same way as described by OP.
We could mitigate this by applying @_disfavoredOverload
, although I don't know if it would have any undesired side effect.
I've found that I can work around this in most cases by explicitly ignoring the closure argument, for example changing:
/// Compiler sees as `Signal<() -> User?, Never>`
.map { AppEnvironment.current.currentUser }
to:
/// Compiler sees as `Signal<User?, Never>`
.map { _ in AppEnvironment.current.currentUser }
This is a little risky though because the compiler actually sometimes builds both of these successfully but the behaviour is different/unexpected so I'm not sure how to be sure that I've managed to catch all of the instances where this is happening.
Are there any better workarounds perhaps?
Hello. 👋 Thanks for opening this issue. Due to inactivity, we will soft close the issue. If you feel that it should remain open, please let us know. 😄