Bug #15830
closedSortedSet's lazy setup causes unpredictable behaviour in subclass's initialize
Description
require 'set'
class SortedSetWithoutLowest < SortedSet
def initialize contents=[]
puts "initialize, #{contents}"
super
lowest = to_a[0]
puts "lowest from #{contents} is #{lowest}, removing"
delete lowest
puts "done initializing #{contents} to #{self}"
end
end
3.times { SortedSetWithoutLowest[1,2,3,4,5] }
initialize, [1, 2, 3, 4, 5]
initialize, [1, 2, 3, 4, 5]
lowest from [1, 2, 3, 4, 5] is 1, removing
done initializing [1, 2, 3, 4, 5] to #<SortedSetWithoutLowest: {2, 3, 4, 5}>
lowest from [1, 2, 3, 4, 5] is 2, removing
done initializing [1, 2, 3, 4, 5] to #<SortedSetWithoutLowest: {3, 4, 5}>
initialize, [1, 2, 3, 4, 5]
lowest from [1, 2, 3, 4, 5] is 1, removing
done initializing [1, 2, 3, 4, 5] to #<SortedSetWithoutLowest: {2, 3, 4, 5}>
initialize, [1, 2, 3, 4, 5]
lowest from [1, 2, 3, 4, 5] is 1, removing
done initializing [1, 2, 3, 4, 5] to #<SortedSetWithoutLowest: {2, 3, 4, 5}>
The first such set created ends up with only [3, 4, 5], because SortedSet does some setup and then re-calls initialize (set.rb
line 807). All further such sets are fine. All the sets are fine if any SortedSet has been made before, so calling SortedSet.new
in the subclass's initialize
and discarding the result is a viable workaround.
Files
Updated by jeremyevans0 (Jeremy Evans) over 5 years ago
- File sorted-set-initialize.patch sorted-set-initialize.patch added
- Status changed from Open to Assigned
- Assignee set to knu (Akinori MUSHA)
I agree this is a bug and the easiest way to fix it is to inline the SortedSet#initialize
implementation defined by SortedSet.setup
into the default implementation of SortedSet#initialize
. Attached is a patch that implements that.
Updated by jeremyevans (Jeremy Evans) about 5 years ago
- Status changed from Assigned to Closed
Applied in changeset git|258843106f343d05732499dd1832958eb1bf64f0.
Fix SortedSet subclasses that override initialize
The first time SortedSet#initialize is called, it overwrites
itself, then recalls #initialize, which results in calling the
subclass's initialize, not the current initialize.
Just inline the default initialize behavior to avoid this issue.
No test for this as it can only be triggered the very first time
that SortedSet#initialize is called.
Fixes [Bug #15830]