Skip to content

🐛 Fix SequenceSet#[] -> nil for invalid start - #777

Merged
nevans merged 3 commits into
masterfrom
sequence_set/fix-slice-empty-set-from-cardinality
Oct 10, 2026
Merged

nevans merged 3 commits into
masterfrom
sequence_set/fix-slice-empty-set-from-cardinality

Conversation

@nevans

@nevans nevans commented Oct 3, 2026 •

Copy link
Copy Markdown
Collaborator

This fixes SequenceSet#slice so it always returns nil when the starting offset is out-of-range, changing a couple situations where it previously returned an empty set: when an exclusive range end is zero, and when range.end is less than same-sign range.begin.

Note that starting at cardinality is not considered invalid, eg: set[cardinality, length] or set[cardinality..int] This intentionally mimics the behavior of Array#slice.

This can be refactored more, to simplify and reduce code duplication, and for performance.

This could be seen as a minor breaking change. But I'm treating it as a bug fix because:

  • SequenceSet#slice was always intended to mimic Array#slice.
  • The documented API doesn't change, it still returns nil or a set.
  • SequenceSet#slice already returns nil in other nearly identical situations.

So, I think it's unlikely there is much (or any) code that depends on this bug. And any code that does depend on it is (arguably) buggy already, and should be easy to fix.

@nevans nevans added the bug Something isn't working label Oct 3, 2026
Comment thread lib/net/imap/sequence_set.rb
@nevans nevans changed the title 🐛 Fix SequenceSet#slice -> nil for invalid start 🐛 Fix SequenceSet#slice -> nil for invalid start Oct 3, 2026
@nevans
nevans added this pull request to stack #775 October 3, 2026 00:38
@nevans
nevans force-pushed the sequence_set/fix-slice-empty-set-from-cardinality branch from da8d0f6 to 23dd26a Compare October 3, 2026 13:42
@nevans

nevans commented Oct 3, 2026 •

Copy link
Copy Markdown
Collaborator Author

This is a much less serious bug than the other two prior to it in the stack. And the naive implementation currently in this PR does come with a non-trivial extra performance cost. It might be better to pull the performance fix into this PR.

@nevans nevans changed the title 🐛 Fix SequenceSet#slice -> nil for invalid start 🐛 Fix SequenceSet#[] -> nil for invalid start Oct 3, 2026
nevans added 3 commits October 9, 2026 23:14
This merges together both `#slice_range` short-circuit cases where we
can immediately deduce that the range is empty.

NOTE that this refactoring does _not_ fix an existing bug: the same-sign
detection works for positive..positive and negative..negative, but it
messes up when beginning or ending with zero.  But fixing that bug
causes more scenarios to return empty when they should return nil`ZZ.
This fixes `SequenceSet#slice` so it always returns `nil` when the
starting offset is out-of-range, changing a couple situations where it
previously returned an empty set: when an exclusive range end is zero,
and when range.end is less than same-sign range.begin.

Note that `set[cardinality..]` is _not_ considered invalid.  This
intentionally mimics the behavior of `Array#slice`.

This can be refactored more, to simplify and reduce code duplication,
and for performance.
By short-circuiting the check that `offset.abs <= cardinality`, this is
a small performance improvement over the naive approach.

A future refactoring should combine this with the start offset scan
(`min = sorted_set_num_at`).
@nevans
nevans force-pushed the sequence_set/fix-slice-empty-set-from-cardinality branch from feeb0d6 to fd01186 Compare October 10, 2026 03:15
Base automatically changed from sequence_set/fix-slice-range-pos-to-out-of-range-neg to master October 10, 2026 03:25
@nevans
nevans merged commit fd01186 into master Oct 10, 2026
50 of 51 checks passed
@nevans
nevans deleted the sequence_set/fix-slice-empty-set-from-cardinality branch October 10, 2026 03:25
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant