Project

General

Profile

Bug #15830

SortedSet's lazy setup causes unpredictable behaviour in subclass's initialize

Added by viko (Viko Viko) 4 months ago. Updated 3 months ago.

Status:
Assigned
Priority:
Normal
Target version:
-
ruby -v:
ruby 2.6.3p62 (2019-04-16 revision 67580) [x86_64-darwin18]
[ruby-core:92563]

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

sorted-set-initialize.patch (944 Bytes) sorted-set-initialize.patch jeremyevans0 (Jeremy Evans), 06/05/2019 02:14 AM

History

Updated by jeremyevans0 (Jeremy Evans) 3 months ago

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.

Also available in: Atom PDF