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
[SR-3166] Sequence.first(where:) shouldn't use throw internally for success #45754
Comments
Comment by Florent Pillet (JIRA) Link to the relevant piece of code in standard library: Sequence.first implementation |
Comment by Russ Bishop (JIRA) IIRC I did it this way to avoid allocating an iterator for types where that is expensive; the type itself may have a more optimal implementation of forEach since it can guarantee nothing escapes... the throwing is just a way to jump out of the forEach and has minimal overhead. Can you explain why you think this should be changed? |
Comment by Russ Bishop (JIRA) My originally implementation used a for loop; I'm not opposed to changing it back. The original change was at @gribozavr's request IIRC so you might ask him |
Comment by Florent Pillet (JIRA) Hi Russ thanks for your answer. When you run your application with Xcode, you have the option to set it to break on `throw` so as to be able to catch throws early in your code, and examine what's wrong. Since you are using `throw` for a case that is not an error, I get a break in debugger every time I use `first` and it is successful. This is highly inconvenient when you use `first` a lot and you get Xcode debugger pausing your app for nothing. In my case I had to rewrite a `first` implementation that doesn't use `throw` because I use this function a lot. |
I have a fix for this issue at the link below, but there's some question about whether this is best handled in the stdlib or should be addressed in Xcode. (I don't think we want to adopt a "no throwing in stdlib code" policy.) I also haven't been able to reproduce this behavior in my latest version of Xcode, so it may be a moot point. I'm going to close the PR for now—fpillet (JIRA User), can you check if you're still able to reproduce this in the latest Xcode? |
@natecook1000 just confirming that I'm still seeing this (really annoying) behaviour in the latest public release of Xcode (8.2.1). I don't think "no throwing in stdlib" is at issue - what I'm reading is that there's some contention about using throw for non-error related purposes. How would Xcode differentiate between a "good" throw that's not an error, and a real throw? I guess it's up to the two teams to coordinate as to the correct place to fix this issue, but this is impacting my use of Swift/Xcode now. |
I feel it's worth noting that performance can be a concern here, although only for a large number (in the order of millions) of repeated applications of first(where:) (one example of this bottleneck was encountered here: http://codereview.stackexchange.com/q/158798/104723). Although I'm unsure of whether this is a good justification for changing the implementation back to using a for-in loop, given the potential benefits from allowing custom sequences to provide a custom forEach(_:) implementation. |
What about introducing a standard flow control Error type that bypasses the swift_willThrow() breakpoint? I have historically implemented similar "no-error" errors myself (and then refactored to remove them due to the debugging issue), so maybe this is a useful pattern that is worth supporting? |
As far as I can see, `first(where:)` does not throw an error for flow control anymore, so this can be closed? |
Additional Detail from JIRA
md5: 542fdb4ae8d528fadb931fcece9b2e86
Issue Description:
The implementation for the new `Sequence.first(where:)` function in Swift 3 internally uses a `throw _StopIteratop.stop` to exit a `forEach` loop on success.
While merits of this approach can be discussed, the immediate impact on developers is that Xcode breaks every time an item is found when using the Break on Swift Errors debugger breakpoint.
Since Xcode internally breaks on `swift_willThrow()` when you ask it to break on Swift Errors, the standard library should refrain from internally using `throw` for regular control flow until tooling can support filtering of false positives.
One way or the other, the current state of things should change. One solution would be that swiftc does not emit the call to `swift_willThrow()` in certain known internal cases.
The text was updated successfully, but these errors were encountered: