Repository: apple/swift-nio
File: Sources/NIOPosix/PendingWritesManager.swift (Swift)

Code before:
            case .open:
                self.outboundCloseState = .readyForClose(promise)
                closeResult = .readyForClose(promise)
            case .readyForClose(var closePromise), .pending(var closePromise):
                closePromise.setOrCascade(to: promise)
                self.outboundCloseState = .readyForClose(closePromise)
                closeResult = .readyForClose(closePromise)
            case .closed:
                closeResult = .closed(promise)
            }

        } else {
            switch self.outboundCloseState {
            case .open:
                self.outboundCloseState = .pending(promise)
                closeResult = .pending
            case .pending(var closePromise):
                closePromise.setOrCascade(to: promise)
                self.outboundCloseState = .pending(closePromise)
                closeResult = .pending
            case .readyForClose:
                preconditionFailure(
                    "We are in .readyForClose state but we still have pending writes. This should never happen."
                )
            case .closed:
                preconditionFailure(
                    "We are in .closed state but we still have pending writes. This should never happen."
                )
            }

        }

        return closeResult
    }

    /// Signal that the `Channel` is closed.
    func closeComplete(_ error: Error? = nil) {
        assert(self.isOpen)
        assert(self.isEmpty)

        switch self.outboundCloseState {
        case .readyForClose(let closePromise):
            self.outboundCloseState = .closed
            if let error {
                closePromise?.fail(error)
            } else {
                closePromise?.succeed(())
            }
        case .closed:
            ()  // nothing to do
        case .open, .pending:

Review comment (bug):
I'm a touch nervous about these precondition failures. Can we come up with a logical behaviour here? Probably it's "fail the promise" and "assertionFailure to get crashes in debug".

Code after:
                )
                self = .errored(NIOReportedOpenAfterClose(), promise)
            case .pending:
                // `promise` has already been taken care of in the pending state for later completion
                self = .pending
            case .readyForClose(let closePromise):
                if isEmpty {
                    self = .readyForClose(closePromise)
                } else {
                    assertionFailure(
                        "We are in .readyForClose state but we still have pending writes. This should never happen."
                    )
                    // `promise` has already been cascaded off `closePromise`
                    self = .errored(NIOReportedPendingWritesInInvalidState(), closePromise)
                }
            case .closed:
                if isEmpty {
                    self = .closed(promise)
                } else {
                    assertionFailure(
                        "We are in .closed state but we still have pending writes. This should never happen."
                    )
                    self = .errored(NIOReportedPendingWritesInInvalidState(), promise)
                }
            }
        }
    }

    /// Signal the intention to close. Takes a promise which will be returned for completing when pending writes are dealt with
    ///
    /// - Parameters:
    ///   - promise: Optionally an `EventLoopPromise` which is stored and is returned to be completed by the caller once
    ///              all outstanding writes have been dealt with or an error condition is encountered.
    func closeOutbound(_ promise: EventLoopPromise<Void>?) -> CloseOutboundResult {
        assert(self.isOpen)

        // Update our internal state
        switch self.outboundCloseState {
        case .open:
            if self.isEmpty {
                self.outboundCloseState = .readyForClose(promise)
            } else {
                self.outboundCloseState = .pending(promise)
            }
        case .readyForClose(var closePromise):
            closePromise.setOrCascade(to: promise)
            self.outboundCloseState = .readyForClose(closePromise)
        case .pending(var closePromise):
            closePromise.setOrCascade(to: promise)
            if self.isEmpty {
                self.outboundCloseState = .readyForClose(closePromise)