Project

General

Profile

Actions

Bug #15830

closed

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

Added by viko (Viko Viko) over 5 years ago. Updated about 5 years ago.

Status:
Closed
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

Updated by jeremyevans0 (Jeremy Evans) over 5 years 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.

Actions #2

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]

Actions

Also available in: Atom PDF

Like0
Like0Like0