Rethrows still doesn't cascade into inner closures?

I wrote:

extension Sequence {
    /// Calls a given closure on each element in iteration order while the
    /// released sequence still conforms to being sorted along the given
    /// ordering predicate, returning the post-cutoff elements in a separate
    /// sequence.
    func forEachSorted(
        stopsAtDuplicate: Bool,
        by areInIncreasingOrder: (Element, Element) throws -> Bool,
        do action: (Element) throws -> Void
    ) rethrows -> PrependedIteratorSequence<Iterator> {
        // Empty-sequence check
        var iterator = makeIterator(), count = underestimatedCount
        guard var previous = iterator.next() else {
            return PrependedIteratorSequence(base: iterator, first: nil,
                                     underestimatedCount: 0)
        }

        // Single-element-only check
        try action(previous)
        count -= 1
        guard var current = iterator.next() else {
            return PrependedIteratorSequence(base: iterator, first: nil,
                                     underestimatedCount: 0)
        }

        while stopsAtDuplicate
                ? try areInIncreasingOrder(previous, current)
                : try !areInIncreasingOrder(current, previous) {
            try action(current)
            if count > Int.min {
                count -= 1
            }
            guard let next = iterator.next() else {
                return PrependedIteratorSequence(base: iterator, first: nil,
                                         underestimatedCount: 0)
            }

            (previous, current) = (current, next)
        }
        return PrependedIteratorSequence(base: iterator, first: current,
                                         underestimatedCount: Swift.max(0,
                                                                        count))
    }
}

This is the implementation function for both a method that returns the sorted prefix of a sequence, and for the unsorted suffix of the sequence. (The algorithm naturally calculates both at the same time.) Note that the while loop needs to test for strongly increasing vs. weakly increasing each time. I wanted to do the calculation once, putting the result into a closure.

// I only half-remember what I had here.
let closure = stopsAtDuplicate ? { try areInIncreasingOrder(previous, current) } : { try !areInIncreasingOrder(current, previous) }

But calling the closure gives a "Call can throw, but the error is not handled; a function declared 'rethrows' may only throw if its parameter does" each time. This has been encountered before, and summarized into SR-680.

How easy is this to fix?

Terms of Service

Privacy Policy

Cookie Policy