GithubHelp home page GithubHelp logo

sorted_set's Introduction

SortedSet

SortedSet implements a Set whose elements are sorted in ascending order (according to the return values of their <=> methods) when iterating over them.

Every element in SortedSet must be mutually comparable to every other: comparison with <=> must not return nil for any pair of elements. Otherwise ArgumentError will be raised.

Currently this library does nothing for JRuby, as it has its own version of Set and SortedSet.

Installation

Add this line to your application's Gemfile:

gem 'sorted_set'

And then execute:

$ bundle install

Or install it yourself as:

$ gem install sorted_set

Usage

require "sorted_set"

set = SortedSet.new([2, 1, 5, 6, 4, 5, 3, 3, 3])
ary = []

set.each do |obj|
  ary << obj
end

p ary # => [1, 2, 3, 4, 5, 6]

set2 = SortedSet.new([1, 2, "3"])
set2.each { |obj| } # => raises ArgumentError: comparison of Fixnum with String failed

Development

After checking out the repo, run bin/setup to install dependencies. Then, run rake test to run the tests. You can also run bin/console for an interactive prompt that will allow you to experiment.

Contributing

Bug reports and pull requests are welcome on GitHub at https://github.com/knu/sorted_set.

License

The gem is available as open source under either the terms of the 2-Clause BSD License.

sorted_set's People

Contributors

knu avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar

sorted_set's Issues

Does SortedSet support ceiling/floor method or similiar?

Hi,

I was wondering how SortedSet can help achieve the same functionality that Java TreeSet implementing ceiling/floor method? Let's take ceiling for example, it accepts a object as parameter, and tries to find if the current set has a matching element first. If the element exists in set, then return; otherwise, return the next element in the set that is larger than this parameter. If it exists return, otherwise return null.

Below are some test cases.

[1,2,3,4,5]
ceiling(3) => 3
[1,2,3,5]
ceiling(4) => 5
[1,2,3,4,5]
ceiling(6) => null

In Java, since it's using a red-black tree, it can utilise the balancing property to find out this ceiling/floor value very efficiently. However, in Ruby I've no idea how to do it effectively. Would appreciate if you can share any thoughts/comments on this. Many thanks!

#delete compatibility with from SortedSet from Stdlib

Hi,

I run in the following issue using SortedSet as drop in replacement:

3.0.2 :001 > str = "foo";ss = SortedSet.new; ss << str; hsh = { enabled: ss}; hsh[:enabled].delete(nil)
/home/me/.rvm/gems/ruby-3.0.2/gems/set-1.0.2/lib/set.rb:540:in `delete': comparison of NilClass with String failed (ArgumentError)
  from /home/me/.rvm/gems/ruby-3.0.2/gems/set-1.0.2/lib/set.rb:540:in `delete'
  from (irb):1:in `<main>'
  from /home/me/.rvm/rubies/ruby-3.0.2/lib/ruby/gems/3.0.0/gems/irb-1.3.5/exe/irb:11:in `<top (required)>'
  from /home/me/.rvm/rubies/ruby-3.0.2/bin/irb:23:in `load'
  from /home/me/.rvm/rubies/ruby-3.0.2/bin/irb:23:in `<main>'

While with ruby 2.7.4:

2.7.4 :001 > str = "foo";ss = SortedSet.new; ss << str; hsh = { enabled: ss}; hsh[:enabled].delete(nil)
 => #<SortedSet: {"foo"}> 

If I debugged it correctly this is due to RBTree:

3.0.2 :002 >  rb = RBTree["", ""]; rb.delete(0)
(irb):4:in `delete': comparison of Integer with String failed (ArgumentError)
  from (irb):4:in `<main>'
  from /home/me/.rvm/rubies/ruby-3.0.2/lib/ruby/gems/3.0.0/gems/irb-1.3.5/exe/irb:11:in `<top (required)>'
  from /home/me/.rvm/rubies/ruby-3.0.2/bin/irb:23:in `load'
  from /home/me/.rvm/rubies/ruby-3.0.2/bin/irb:23:in `<main>'

Is this mismatch in functionality generally accepted or is it smth that should get solved in sorted_set?

Thanks and cheers!

JRuby support that is not a no-op

JRuby would like to support this gem directly (rather than passively), but currently it has a dependency on the rbtree gem which has a C extension.

First off, thanks very much for thinking of JRuby and releasing -java versions of the gem that do not have the rbtree dependency and that just utilize our existing SortedSet implementation! We appreciate your consideration!

We do, however, want to match CRuby and stop shipping our own implementation of SortedSet, so I see two options going forward:

  • Include our Java implementation of SortedSet inside the -java version of the sorted_set gem.
  • Release a -java version of the rbtree gem and enable your version of SortedSet on JRuby.

We would prefer to do the latter, for ease of maintenance, but I thought we should start the discussion here.

There may be performance considerations... the existing JRuby SortedSet is based on the JDK's TreeSet class, which has been optimized for this purpose.

Copying @kares as he did the native port of the set library in JRuby.

Clang 15 installation failure

Hello.

Trying to install sorted_set with clang 15 and getting the following error.

As a workaround:

gem install rbtree -- --with-cflags="-Wno-int-conversion"
Error
current directory: /Users/vladimirtemnikov/.asdf/installs/ruby/3.1.3/lib/ruby/gems/3.1.0/gems/rbtree-0.4.5
/Users/vladimirtemnikov/.asdf/installs/ruby/3.1.3/bin/ruby -I /Users/vladimirtemnikov/.asdf/installs/ruby/3.1.3/lib/ruby/3.1.0 extconf.rb
checking for rb_exec_recursive() in ruby.h... yes
checking for rb_exec_recursive_paired() in ruby.h... yes
checking for rb_proc_lambda_p() in ruby.h... yes
checking for rb_ary_resize() in ruby.h... yes
checking for rb_obj_hide() in ruby.h... yes
checking for rb_safe_level() in ruby.h... no
checking for rb_cData() in ruby.h... yes
creating Makefile

current directory: /Users/vladimirtemnikov/.asdf/installs/ruby/3.1.3/lib/ruby/gems/3.1.0/gems/rbtree-0.4.5
make DESTDIR\= sitearchdir\=./.gem.20221125-54755-inhzlg sitelibdir\=./.gem.20221125-54755-inhzlg clean

current directory: /Users/vladimirtemnikov/.asdf/installs/ruby/3.1.3/lib/ruby/gems/3.1.0/gems/rbtree-0.4.5
make DESTDIR\= sitearchdir\=./.gem.20221125-54755-inhzlg sitelibdir\=./.gem.20221125-54755-inhzlg
compiling dict.c
compiling rbtree.c
rbtree.c:137:14: error: incompatible pointer to integer conversion passing 'const void *' to parameter of type 'VALUE' (aka 'unsigned long') [-Wint-conversion]
    if (TYPE(key1) == T_STRING && TYPE(key2) == T_STRING)
             ^~~~
/Users/vladimirtemnikov/.asdf/installs/ruby/3.1.3/include/ruby-3.1.0/ruby/internal/value_type.h:107:52: note: expanded from macro 'TYPE'
#define TYPE(_)           RBIMPL_CAST((int)rb_type(_))
                                                   ^
/Users/vladimirtemnikov/.asdf/installs/ruby/3.1.3/include/ruby-3.1.0/ruby/internal/cast.h:31:29: note: expanded from macro 'RBIMPL_CAST'
# define RBIMPL_CAST(expr) (expr)
                            ^~~~
/Users/vladimirtemnikov/.asdf/installs/ruby/3.1.3/include/ruby-3.1.0/ruby/internal/value_type.h:224:15: note: passing argument to parameter 'obj' here
rb_type(VALUE obj)
              ^
rbtree.c:137:40: error: incompatible pointer to integer conversion passing 'const void *' to parameter of type 'VALUE' (aka 'unsigned long') [-Wint-conversion]
    if (TYPE(key1) == T_STRING && TYPE(key2) == T_STRING)
                                       ^~~~
/Users/vladimirtemnikov/.asdf/installs/ruby/3.1.3/include/ruby-3.1.0/ruby/internal/value_type.h:107:52: note: expanded from macro 'TYPE'
#define TYPE(_)           RBIMPL_CAST((int)rb_type(_))
                                                   ^
/Users/vladimirtemnikov/.asdf/installs/ruby/3.1.3/include/ruby-3.1.0/ruby/internal/cast.h:31:29: note: expanded from macro 'RBIMPL_CAST'
# define RBIMPL_CAST(expr) (expr)
                            ^~~~
/Users/vladimirtemnikov/.asdf/installs/ruby/3.1.3/include/ruby-3.1.0/ruby/internal/value_type.h:224:15: note: passing argument to parameter 'obj' here
rb_type(VALUE obj)
              ^
rbtree.c:168:24: warning: incompatible function pointer types passing 'VALUE (VALUE *)' (aka 'unsigned long (unsigned long *)') to parameter of type 'VALUE (*)(VALUE)' (aka 'unsigned long (*)(unsigned long)') [-Wincompatible-function-pointer-types]
    result = rb_ensure(rbtree_user_cmp_body, (VALUE)&args,
                       ^~~~~~~~~~~~~~~~~~~~
/Users/vladimirtemnikov/.asdf/installs/ruby/3.1.3/include/ruby-3.1.0/ruby/internal/iterator.h:425:25: note: passing argument to parameter 'b_proc' here
VALUE rb_ensure(VALUE (*b_proc)(VALUE), VALUE data1, VALUE (*e_proc)(VALUE), VALUE data2);
                        ^
rbtree.c:169:24: warning: incompatible function pointer types passing 'VALUE (rbtree_t *)' (aka 'unsigned long (rbtree_t *)') to parameter of type 'VALUE (*)(VALUE)' (aka 'unsigned long (*)(unsigned long)') [-Wincompatible-function-pointer-types]
                       rbtree_user_cmp_ensure, (VALUE)rbtree);
                       ^~~~~~~~~~~~~~~~~~~~~~
/Users/vladimirtemnikov/.asdf/installs/ruby/3.1.3/include/ruby-3.1.0/ruby/internal/iterator.h:425:62: note: passing argument to parameter 'e_proc' here
VALUE rb_ensure(VALUE (*b_proc)(VALUE), VALUE data1, VALUE (*e_proc)(VALUE), VALUE data2);
                                                             ^
rbtree.c:376:15: warning: incompatible function pointer types passing 'VALUE (rbtree_insert_arg_t *)' (aka 'unsigned long (rbtree_insert_arg_t *)') to parameter of type 'VALUE (*)(VALUE)' (aka 'unsigned long (*)(unsigned long)') [-Wincompatible-function-pointer-types]
    rb_ensure(insert_node_body, (VALUE)&arg,
              ^~~~~~~~~~~~~~~~
/Users/vladimirtemnikov/.asdf/installs/ruby/3.1.3/include/ruby-3.1.0/ruby/internal/iterator.h:425:25: note: passing argument to parameter 'b_proc' here
VALUE rb_ensure(VALUE (*b_proc)(VALUE), VALUE data1, VALUE (*e_proc)(VALUE), VALUE data2);
                        ^
rbtree.c:377:15: warning: incompatible function pointer types passing 'VALUE (rbtree_insert_arg_t *)' (aka 'unsigned long (rbtree_insert_arg_t *)') to parameter of type 'VALUE (*)(VALUE)' (aka 'unsigned long (*)(unsigned long)') [-Wincompatible-function-pointer-types]
              insert_node_ensure, (VALUE)&arg);
              ^~~~~~~~~~~~~~~~~~
/Users/vladimirtemnikov/.asdf/installs/ruby/3.1.3/include/ruby-3.1.0/ruby/internal/iterator.h:425:62: note: passing argument to parameter 'e_proc' here
VALUE rb_ensure(VALUE (*b_proc)(VALUE), VALUE data1, VALUE (*e_proc)(VALUE), VALUE data2);
                                                             ^
rbtree.c:632:22: warning: incompatible function pointer types passing 'VALUE (rbtree_each_arg_t *)' (aka 'unsigned long (rbtree_each_arg_t *)') to parameter of type 'VALUE (*)(VALUE)' (aka 'unsigned long (*)(unsigned long)') [-Wincompatible-function-pointer-types]
    return rb_ensure(rbtree_each_body, (VALUE)&each_arg,
                     ^~~~~~~~~~~~~~~~
/Users/vladimirtemnikov/.asdf/installs/ruby/3.1.3/include/ruby-3.1.0/ruby/internal/iterator.h:425:25: note: passing argument to parameter 'b_proc' here
VALUE rb_ensure(VALUE (*b_proc)(VALUE), VALUE data1, VALUE (*e_proc)(VALUE), VALUE data2);
                        ^
rbtree.c:644:22: warning: incompatible function pointer types passing 'VALUE (rbtree_each_arg_t *)' (aka 'unsigned long (rbtree_each_arg_t *)') to parameter of type 'VALUE (*)(VALUE)' (aka 'unsigned long (*)(unsigned long)') [-Wincompatible-function-pointer-types]
    return rb_ensure(rbtree_each_body, (VALUE)&each_arg,
                     ^~~~~~~~~~~~~~~~
/Users/vladimirtemnikov/.asdf/installs/ruby/3.1.3/include/ruby-3.1.0/ruby/internal/iterator.h:425:25: note: passing argument to parameter 'b_proc' here
VALUE rb_ensure(VALUE (*b_proc)(VALUE), VALUE data1, VALUE (*e_proc)(VALUE), VALUE data2);
                        ^
rbtree.c:768:5: warning: 'rb_gc_force_recycle' is deprecated: this is now a no-op function [-Wdeprecated-declarations]
    rb_gc_force_recycle(temp);
    ^
/Users/vladimirtemnikov/.asdf/installs/ruby/3.1.3/include/ruby-3.1.0/ruby/internal/intern/gc.h:213:1: note: 'rb_gc_force_recycle' has been explicitly marked deprecated here
RBIMPL_ATTR_DEPRECATED(("this is now a no-op function"))
^
/Users/vladimirtemnikov/.asdf/installs/ruby/3.1.3/include/ruby-3.1.0/ruby/internal/attr/deprecated.h:36:53: note: expanded from macro 'RBIMPL_ATTR_DEPRECATED'
# define RBIMPL_ATTR_DEPRECATED(msg) __attribute__((__deprecated__ msg))
                                                    ^
rbtree.c:948:22: warning: incompatible function pointer types passing 'VALUE (rbtree_remove_if_arg_t *)' (aka 'unsigned long (rbtree_remove_if_arg_t *)') to parameter of type 'VALUE (*)(VALUE)' (aka 'unsigned long (*)(unsigned long)') [-Wincompatible-function-pointer-types]
    return rb_ensure(rbtree_remove_if_body, (VALUE)&arg,
                     ^~~~~~~~~~~~~~~~~~~~~
/Users/vladimirtemnikov/.asdf/installs/ruby/3.1.3/include/ruby-3.1.0/ruby/internal/iterator.h:425:25: note: passing argument to parameter 'b_proc' here
VALUE rb_ensure(VALUE (*b_proc)(VALUE), VALUE data1, VALUE (*e_proc)(VALUE), VALUE data2);
                        ^
rbtree.c:949:22: warning: incompatible function pointer types passing 'VALUE (rbtree_remove_if_arg_t *)' (aka 'unsigned long (rbtree_remove_if_arg_t *)') to parameter of type 'VALUE (*)(VALUE)' (aka 'unsigned long (*)(unsigned long)') [-Wincompatible-function-pointer-types]
                     rbtree_remove_if_ensure, (VALUE)&arg);
                     ^~~~~~~~~~~~~~~~~~~~~~~
/Users/vladimirtemnikov/.asdf/installs/ruby/3.1.3/include/ruby-3.1.0/ruby/internal/iterator.h:425:62: note: passing argument to parameter 'e_proc' here
VALUE rb_ensure(VALUE (*b_proc)(VALUE), VALUE data1, VALUE (*e_proc)(VALUE), VALUE data2);
                                                             ^
rbtree.c:1280:5: warning: 'RB_OBJ_INFECT' is deprecated: taintedness turned out to be a wrong idea. [-Wdeprecated-declarations]
    OBJ_INFECT(ary, self);
    ^
/Users/vladimirtemnikov/.asdf/installs/ruby/3.1.3/include/ruby-3.1.0/ruby/internal/fl_type.h:147:25: note: expanded from macro 'OBJ_INFECT'
#define OBJ_INFECT      RB_OBJ_INFECT      /**< @old{RB_OBJ_INFECT} */
                        ^
/Users/vladimirtemnikov/.asdf/installs/ruby/3.1.3/include/ruby-3.1.0/ruby/internal/fl_type.h:114:30: note: expanded from macro 'RB_OBJ_INFECT'
#define RB_OBJ_INFECT        RB_OBJ_INFECT
                             ^
/Users/vladimirtemnikov/.asdf/installs/ruby/3.1.3/include/ruby-3.1.0/ruby/internal/fl_type.h:880:1: note: 'RB_OBJ_INFECT' has been explicitly marked deprecated here
RBIMPL_ATTR_DEPRECATED(("taintedness turned out to be a wrong idea."))
^
/Users/vladimirtemnikov/.asdf/installs/ruby/3.1.3/include/ruby-3.1.0/ruby/internal/attr/deprecated.h:36:53: note: expanded from macro 'RBIMPL_ATTR_DEPRECATED'
# define RBIMPL_ATTR_DEPRECATED(msg) __attribute__((__deprecated__ msg))
                                                    ^
rbtree.c:1306:5: warning: 'RB_OBJ_INFECT' is deprecated: taintedness turned out to be a wrong idea. [-Wdeprecated-declarations]
    OBJ_INFECT(hash, self);
    ^
/Users/vladimirtemnikov/.asdf/installs/ruby/3.1.3/include/ruby-3.1.0/ruby/internal/fl_type.h:147:25: note: expanded from macro 'OBJ_INFECT'
#define OBJ_INFECT      RB_OBJ_INFECT      /**< @old{RB_OBJ_INFECT} */
                        ^
/Users/vladimirtemnikov/.asdf/installs/ruby/3.1.3/include/ruby-3.1.0/ruby/internal/fl_type.h:114:30: note: expanded from macro 'RB_OBJ_INFECT'
#define RB_OBJ_INFECT        RB_OBJ_INFECT
                             ^
/Users/vladimirtemnikov/.asdf/installs/ruby/3.1.3/include/ruby-3.1.0/ruby/internal/fl_type.h:880:1: note: 'RB_OBJ_INFECT' has been explicitly marked deprecated here
RBIMPL_ATTR_DEPRECATED(("taintedness turned out to be a wrong idea."))
^
/Users/vladimirtemnikov/.asdf/installs/ruby/3.1.3/include/ruby-3.1.0/ruby/internal/attr/deprecated.h:36:53: note: expanded from macro 'RBIMPL_ATTR_DEPRECATED'
# define RBIMPL_ATTR_DEPRECATED(msg) __attribute__((__deprecated__ msg))
                                                    ^
rbtree.c:1341:5: warning: 'RB_OBJ_INFECT' is deprecated: taintedness turned out to be a wrong idea. [-Wdeprecated-declarations]
    OBJ_INFECT(result, str);
    ^
/Users/vladimirtemnikov/.asdf/installs/ruby/3.1.3/include/ruby-3.1.0/ruby/internal/fl_type.h:147:25: note: expanded from macro 'OBJ_INFECT'
#define OBJ_INFECT      RB_OBJ_INFECT      /**< @old{RB_OBJ_INFECT} */
                        ^
/Users/vladimirtemnikov/.asdf/installs/ruby/3.1.3/include/ruby-3.1.0/ruby/internal/fl_type.h:114:30: note: expanded from macro 'RB_OBJ_INFECT'
#define RB_OBJ_INFECT        RB_OBJ_INFECT
                             ^
/Users/vladimirtemnikov/.asdf/installs/ruby/3.1.3/include/ruby-3.1.0/ruby/internal/fl_type.h:880:1: note: 'RB_OBJ_INFECT' has been explicitly marked deprecated here
RBIMPL_ATTR_DEPRECATED(("taintedness turned out to be a wrong idea."))
^
/Users/vladimirtemnikov/.asdf/installs/ruby/3.1.3/include/ruby-3.1.0/ruby/internal/attr/deprecated.h:36:53: note: expanded from macro 'RBIMPL_ATTR_DEPRECATED'
# define RBIMPL_ATTR_DEPRECATED(msg) __attribute__((__deprecated__ msg))
                                                    ^
rbtree.c:1347:5: warning: 'RB_OBJ_INFECT' is deprecated: taintedness turned out to be a wrong idea. [-Wdeprecated-declarations]
    OBJ_INFECT(result, str);
    ^
/Users/vladimirtemnikov/.asdf/installs/ruby/3.1.3/include/ruby-3.1.0/ruby/internal/fl_type.h:147:25: note: expanded from macro 'OBJ_INFECT'
#define OBJ_INFECT      RB_OBJ_INFECT      /**< @old{RB_OBJ_INFECT} */
                        ^
/Users/vladimirtemnikov/.asdf/installs/ruby/3.1.3/include/ruby-3.1.0/ruby/internal/fl_type.h:114:30: note: expanded from macro 'RB_OBJ_INFECT'
#define RB_OBJ_INFECT        RB_OBJ_INFECT
                             ^
/Users/vladimirtemnikov/.asdf/installs/ruby/3.1.3/include/ruby-3.1.0/ruby/internal/fl_type.h:880:1: note: 'RB_OBJ_INFECT' has been explicitly marked deprecated here
RBIMPL_ATTR_DEPRECATED(("taintedness turned out to be a wrong idea."))
^
/Users/vladimirtemnikov/.asdf/installs/ruby/3.1.3/include/ruby-3.1.0/ruby/internal/attr/deprecated.h:36:53: note: expanded from macro 'RBIMPL_ATTR_DEPRECATED'
# define RBIMPL_ATTR_DEPRECATED(msg) __attribute__((__deprecated__ msg))
                                                    ^
rbtree.c:1366:5: warning: 'RB_OBJ_INFECT' is deprecated: taintedness turned out to be a wrong idea. [-Wdeprecated-declarations]
    OBJ_INFECT(result, str);
    ^
/Users/vladimirtemnikov/.asdf/installs/ruby/3.1.3/include/ruby-3.1.0/ruby/internal/fl_type.h:147:25: note: expanded from macro 'OBJ_INFECT'
#define OBJ_INFECT      RB_OBJ_INFECT      /**< @old{RB_OBJ_INFECT} */
                        ^
/Users/vladimirtemnikov/.asdf/installs/ruby/3.1.3/include/ruby-3.1.0/ruby/internal/fl_type.h:114:30: note: expanded from macro 'RB_OBJ_INFECT'
#define RB_OBJ_INFECT        RB_OBJ_INFECT
                             ^
/Users/vladimirtemnikov/.asdf/installs/ruby/3.1.3/include/ruby-3.1.0/ruby/internal/fl_type.h:880:1: note: 'RB_OBJ_INFECT' has been explicitly marked deprecated here
RBIMPL_ATTR_DEPRECATED(("taintedness turned out to be a wrong idea."))
^
/Users/vladimirtemnikov/.asdf/installs/ruby/3.1.3/include/ruby-3.1.0/ruby/internal/attr/deprecated.h:36:53: note: expanded from macro 'RBIMPL_ATTR_DEPRECATED'
# define RBIMPL_ATTR_DEPRECATED(msg) __attribute__((__deprecated__ msg))
                                                    ^
rbtree.c:1371:5: warning: 'RB_OBJ_INFECT' is deprecated: taintedness turned out to be a wrong idea. [-Wdeprecated-declarations]
    OBJ_INFECT(result, str);
    ^
/Users/vladimirtemnikov/.asdf/installs/ruby/3.1.3/include/ruby-3.1.0/ruby/internal/fl_type.h:147:25: note: expanded from macro 'OBJ_INFECT'
#define OBJ_INFECT      RB_OBJ_INFECT      /**< @old{RB_OBJ_INFECT} */
                        ^
/Users/vladimirtemnikov/.asdf/installs/ruby/3.1.3/include/ruby-3.1.0/ruby/internal/fl_type.h:114:30: note: expanded from macro 'RB_OBJ_INFECT'
#define RB_OBJ_INFECT        RB_OBJ_INFECT
                             ^
/Users/vladimirtemnikov/.asdf/installs/ruby/3.1.3/include/ruby-3.1.0/ruby/internal/fl_type.h:880:1: note: 'RB_OBJ_INFECT' has been explicitly marked deprecated here
RBIMPL_ATTR_DEPRECATED(("taintedness turned out to be a wrong idea."))
^
/Users/vladimirtemnikov/.asdf/installs/ruby/3.1.3/include/ruby-3.1.0/ruby/internal/attr/deprecated.h:36:53: note: expanded from macro 'RBIMPL_ATTR_DEPRECATED'
# define RBIMPL_ATTR_DEPRECATED(msg) __attribute__((__deprecated__ msg))
                                                    ^
rbtree.c:1374:5: warning: 'RB_OBJ_INFECT' is deprecated: taintedness turned out to be a wrong idea. [-Wdeprecated-declarations]
    OBJ_INFECT(result, self);
    ^
/Users/vladimirtemnikov/.asdf/installs/ruby/3.1.3/include/ruby-3.1.0/ruby/internal/fl_type.h:147:25: note: expanded from macro 'OBJ_INFECT'
#define OBJ_INFECT      RB_OBJ_INFECT      /**< @old{RB_OBJ_INFECT} */
                        ^
/Users/vladimirtemnikov/.asdf/installs/ruby/3.1.3/include/ruby-3.1.0/ruby/internal/fl_type.h:114:30: note: expanded from macro 'RB_OBJ_INFECT'
#define RB_OBJ_INFECT        RB_OBJ_INFECT
                             ^
/Users/vladimirtemnikov/.asdf/installs/ruby/3.1.3/include/ruby-3.1.0/ruby/internal/fl_type.h:880:1: note: 'RB_OBJ_INFECT' has been explicitly marked deprecated here
RBIMPL_ATTR_DEPRECATED(("taintedness turned out to be a wrong idea."))
^
/Users/vladimirtemnikov/.asdf/installs/ruby/3.1.3/include/ruby-3.1.0/ruby/internal/attr/deprecated.h:36:53: note: expanded from macro 'RBIMPL_ATTR_DEPRECATED'
# define RBIMPL_ATTR_DEPRECATED(msg) __attribute__((__deprecated__ msg))
                                                    ^
rbtree.c:1569:26: warning: incompatible function pointer types passing 'VALUE (rbtree_bound_arg_t *)' (aka 'unsigned long (rbtree_bound_arg_t *)') to parameter of type 'VALUE (*)(VALUE)' (aka 'unsigned long (*)(unsigned long)') [-Wincompatible-function-pointer-types]
        return rb_ensure(rbtree_bound_body, (VALUE)&arg,
                         ^~~~~~~~~~~~~~~~~
/Users/vladimirtemnikov/.asdf/installs/ruby/3.1.3/include/ruby-3.1.0/ruby/internal/iterator.h:425:25: note: passing argument to parameter 'b_proc' here
VALUE rb_ensure(VALUE (*b_proc)(VALUE), VALUE data1, VALUE (*e_proc)(VALUE), VALUE data2);
                        ^
rbtree.c:1736:12: warning: 'rb_iterate' is deprecated: by: rb_block_call since 1.9 [-Wdeprecated-declarations]
    return rb_iterate(pp_group, (VALUE)&group_args, pp_value, (VALUE)pair_arg);
           ^
/Users/vladimirtemnikov/.asdf/installs/ruby/3.1.3/include/ruby-3.1.0/ruby/internal/iterator.h:269:1: note: 'rb_iterate' has been explicitly marked deprecated here
RBIMPL_ATTR_DEPRECATED(("by: rb_block_call since 1.9"))
^
/Users/vladimirtemnikov/.asdf/installs/ruby/3.1.3/include/ruby-3.1.0/ruby/internal/attr/deprecated.h:36:53: note: expanded from macro 'RBIMPL_ATTR_DEPRECATED'
# define RBIMPL_ATTR_DEPRECATED(msg) __attribute__((__deprecated__ msg))
                                                    ^
rbtree.c:1736:53: warning: incompatible function pointer types passing 'VALUE (VALUE, pp_pair_arg_t *)' (aka 'unsigned long (unsigned long, pp_pair_arg_t *)') to parameter of type 'rb_block_call_func_t' (aka 'unsigned long (*)(unsigned long, unsigned long, int, const unsigned long *, unsigned long)') [-Wincompatible-function-pointer-types]
    return rb_iterate(pp_group, (VALUE)&group_args, pp_value, (VALUE)pair_arg);
                                                    ^~~~~~~~
/Users/vladimirtemnikov/.asdf/installs/ruby/3.1.3/include/ruby-3.1.0/ruby/internal/iterator.h:283:75: note: passing argument to parameter 'proc' here
VALUE rb_iterate(VALUE (*func1)(VALUE), VALUE data1, rb_block_call_func_t proc, VALUE data2);
                                                                          ^
rbtree.c:1765:5: warning: 'rb_iterate' is deprecated: by: rb_block_call since 1.9 [-Wdeprecated-declarations]
    rb_iterate(pp_group, (VALUE)&group_args, pp_pair, (VALUE)&pair_arg);
    ^
/Users/vladimirtemnikov/.asdf/installs/ruby/3.1.3/include/ruby-3.1.0/ruby/internal/iterator.h:269:1: note: 'rb_iterate' has been explicitly marked deprecated here
RBIMPL_ATTR_DEPRECATED(("by: rb_block_call since 1.9"))
^
/Users/vladimirtemnikov/.asdf/installs/ruby/3.1.3/include/ruby-3.1.0/ruby/internal/attr/deprecated.h:36:53: note: expanded from macro 'RBIMPL_ATTR_DEPRECATED'
# define RBIMPL_ATTR_DEPRECATED(msg) __attribute__((__deprecated__ msg))
                                                    ^
rbtree.c:1765:46: warning: incompatible function pointer types passing 'VALUE (VALUE, pp_pair_arg_t *)' (aka 'unsigned long (unsigned long, pp_pair_arg_t *)') to parameter of type 'rb_block_call_func_t' (aka 'unsigned long (*)(unsigned long, unsigned long, int, const unsigned long *, unsigned long)') [-Wincompatible-function-pointer-types]
    rb_iterate(pp_group, (VALUE)&group_args, pp_pair, (VALUE)&pair_arg);
                                             ^~~~~~~
/Users/vladimirtemnikov/.asdf/installs/ruby/3.1.3/include/ruby-3.1.0/ruby/internal/iterator.h:283:75: note: passing argument to parameter 'proc' here
VALUE rb_iterate(VALUE (*func1)(VALUE), VALUE data1, rb_block_call_func_t proc, VALUE data2);
                                                                          ^
rbtree.c:1796:5: warning: 'rb_iterate' is deprecated: by: rb_block_call since 1.9 [-Wdeprecated-declarations]
    rb_iterate(pp_group, (VALUE)&group_args, pp_each_pair, (VALUE)rbtree_arg);
    ^
/Users/vladimirtemnikov/.asdf/installs/ruby/3.1.3/include/ruby-3.1.0/ruby/internal/iterator.h:269:1: note: 'rb_iterate' has been explicitly marked deprecated here
RBIMPL_ATTR_DEPRECATED(("by: rb_block_call since 1.9"))
^
/Users/vladimirtemnikov/.asdf/installs/ruby/3.1.3/include/ruby-3.1.0/ruby/internal/attr/deprecated.h:36:53: note: expanded from macro 'RBIMPL_ATTR_DEPRECATED'
# define RBIMPL_ATTR_DEPRECATED(msg) __attribute__((__deprecated__ msg))
                                                    ^
rbtree.c:1796:46: warning: incompatible function pointer types passing 'VALUE (VALUE, pp_rbtree_arg_t *)' (aka 'unsigned long (unsigned long, pp_rbtree_arg_t *)') to parameter of type 'rb_block_call_func_t' (aka 'unsigned long (*)(unsigned long, unsigned long, int, const unsigned long *, unsigned long)') [-Wincompatible-function-pointer-types]
    rb_iterate(pp_group, (VALUE)&group_args, pp_each_pair, (VALUE)rbtree_arg);
                                             ^~~~~~~~~~~~
/Users/vladimirtemnikov/.asdf/installs/ruby/3.1.3/include/ruby-3.1.0/ruby/internal/iterator.h:283:75: note: passing argument to parameter 'proc' here
VALUE rb_iterate(VALUE (*func1)(VALUE), VALUE data1, rb_block_call_func_t proc, VALUE data2);
                                                                          ^
rbtree.c:1823:12: warning: 'rb_iterate' is deprecated: by: rb_block_call since 1.9 [-Wdeprecated-declarations]
    return rb_iterate(pp_rbtree_group, (VALUE)&arg, pp_rbtree, (VALUE)&arg);
           ^
/Users/vladimirtemnikov/.asdf/installs/ruby/3.1.3/include/ruby-3.1.0/ruby/internal/iterator.h:269:1: note: 'rb_iterate' has been explicitly marked deprecated here
RBIMPL_ATTR_DEPRECATED(("by: rb_block_call since 1.9"))
^
/Users/vladimirtemnikov/.asdf/installs/ruby/3.1.3/include/ruby-3.1.0/ruby/internal/attr/deprecated.h:36:53: note: expanded from macro 'RBIMPL_ATTR_DEPRECATED'
# define RBIMPL_ATTR_DEPRECATED(msg) __attribute__((__deprecated__ msg))
                                                    ^
rbtree.c:1823:53: warning: incompatible function pointer types passing 'VALUE (VALUE, pp_rbtree_arg_t *)' (aka 'unsigned long (unsigned long, pp_rbtree_arg_t *)') to parameter of type 'rb_block_call_func_t' (aka 'unsigned long (*)(unsigned long, unsigned long, int, const unsigned long *, unsigned long)') [-Wincompatible-function-pointer-types]
    return rb_iterate(pp_rbtree_group, (VALUE)&arg, pp_rbtree, (VALUE)&arg);
                                                    ^~~~~~~~~
/Users/vladimirtemnikov/.asdf/installs/ruby/3.1.3/include/ruby-3.1.0/ruby/internal/iterator.h:283:75: note: passing argument to parameter 'proc' here
VALUE rb_iterate(VALUE (*func1)(VALUE), VALUE data1, rb_block_call_func_t proc, VALUE data2);
                                                                          ^
rbtree.c:1902:9: warning: 'rb_cData' is deprecated: by: rb_cObject.  Will be removed in 3.1. [-Wdeprecated-declarations]
        rb_cData
        ^
/Users/vladimirtemnikov/.asdf/installs/ruby/3.1.3/include/ruby-3.1.0/ruby/internal/core/rdata.h:394:18: note: expanded from macro 'rb_cData'
#define rb_cData rb_cData()
                 ^
/Users/vladimirtemnikov/.asdf/installs/ruby/3.1.3/include/ruby-3.1.0/ruby/internal/core/rdata.h:372:1: note: 'rb_cData' has been explicitly marked deprecated here
RBIMPL_ATTR_DEPRECATED(("by: rb_cObject.  Will be removed in 3.1."))
^
/Users/vladimirtemnikov/.asdf/installs/ruby/3.1.3/include/ruby-3.1.0/ruby/internal/attr/deprecated.h:36:53: note: expanded from macro 'RBIMPL_ATTR_DEPRECATED'
# define RBIMPL_ATTR_DEPRECATED(msg) __attribute__((__deprecated__ msg))
                                                    ^
26 warnings and 2 errors generated.
make: *** [rbtree.o] Error 1

make failed, exit code 2
Additional environment info

Segfault when include sorted_set in ruby 3+ on alpine

Environment:

ruby: 3.0.4/3.1.2
alpine 3.15.4
sample official ruby image from dockerhub: https://github.com/docker-library/ruby/blob/dd1b1c9650fd9470edf8399abb2a746e597a821b/3.0/alpine3.15/Dockerfile

Hi 👋 , I have noticed sorted_set is required in ruby 3 and business_time has made an update to include sorted_set.

Problem

As soon as, I installed both rmagick and rbtree or rmagick with sorted_set, segmentation fault would happen immediately with the single file rails setup below.

I have noticed sorted_set includes rbtree as dependency instead of rbtree3 and I'm not sure it's intended or not. Installing rbtree3 would not cause segfault immediately but installing rbtree or sorted_set while require rmagick with trigger segfault immediately as soon as the script run in alpine linux

Notes

Stack trace

/usr/local/bundle/gems/carrierwave-2.2.2/lib/carrierwave/processing/rmagick.rb:352: [BUG] Segmentation fault at 0x0000000000000000
ruby 3.0.4p208 (2022-04-12 revision 3fa771dded) [x86_64-linux-musl]

-- Control frame information -----------------------------------------------
c:0066 p:---- s:0334 e:000333 CFUNC  :read
c:0065 p:0050 s:0329 e:000328 METHOD /usr/local/bundle/gems/carrierwave-2.2.2/lib/carrierwave/processing/rmagick.rb:352
c:0064 p:0018 s:0317 e:000316 METHOD /usr/local/bundle/gems/carrierwave-2.2.2/lib/carrierwave/processing/rmagick.rb:176
c:0063 p:0050 s:0311 e:000310 BLOCK  /usr/local/bundle/gems/carrierwave-2.2.2/lib/carrierwave/uploader/processing.rb:83 [FINISH]
c:0062 p:---- s:0305 e:000304 CFUNC  :each
c:0061 p:0009 s:0301 e:000300 BLOCK  /usr/local/bundle/gems/carrierwave-2.2.2/lib/carrierwave/uploader/processing.rb:75
c:0060 p:0016 s:0298 e:000297 METHOD /usr/local/bundle/gems/carrierwave-2.2.2/lib/carrierwave/uploader/callbacks.rb:15
c:0059 p:0018 s:0292 e:000291 METHOD /usr/local/bundle/gems/carrierwave-2.2.2/lib/carrierwave/uploader/processing.rb:74
c:0058 p:0010 s:0287 e:000286 BLOCK  /usr/local/bundle/gems/carrierwave-2.2.2/lib/carrierwave/uploader/callbacks.rb:14 [FINISH]
c:0057 p:---- s:0283 e:000282 CFUNC  :each
c:0056 p:0012 s:0279 e:000278 METHOD /usr/local/bundle/gems/carrierwave-2.2.2/lib/carrierwave/uploader/callbacks.rb:14
c:0055 p:0176 s:0273 e:000272 METHOD /usr/local/bundle/gems/carrierwave-2.2.2/lib/carrierwave/uploader/cache.rb:144
c:0054 p:0065 s:0268 e:000267 BLOCK  /usr/local/bundle/gems/carrierwave-2.2.2/lib/carrierwave/mounter.rb:63
c:0053 p:0002 s:0264 e:000263 METHOD /usr/local/bundle/gems/carrierwave-2.2.2/lib/carrierwave/mounter.rb:176
c:0052 p:0005 s:0259 e:000258 BLOCK  /usr/local/bundle/gems/carrierwave-2.2.2/lib/carrierwave/mounter.rb:47 [FINISH]
c:0051 p:---- s:0255 e:000254 CFUNC  :map
c:0050 p:0035 s:0251 e:000250 METHOD /usr/local/bundle/gems/carrierwave-2.2.2/lib/carrierwave/mounter.rb:46
c:0049 p:0011 s:0245 e:000244 METHOD /usr/local/bundle/gems/carrierwave-2.2.2/lib/carrierwave/mount.rb:146
c:0048 p:0006 s:0240 e:000239 METHOD /usr/local/bundle/gems/carrierwave-2.2.2/lib/carrierwave/mount.rb:373
c:0047 p:0054 s:0235 e:000234 METHOD /usr/local/bundle/gems/carrierwave-2.2.2/lib/carrierwave/orm/activerecord.rb:75
c:0046 p:0012 s:0229 e:000227 BLOCK  test.rb:68 [FINISH]
c:0045 p:---- s:0225 e:000224 CFUNC  :instance_exec
c:0044 p:0013 s:0220 e:000219 METHOD /usr/local/bundle/gems/rspec-core-3.11.0/lib/rspec/core/example.rb:457
c:0043 p:0010 s:0214 e:000213 METHOD /usr/local/bundle/gems/rspec-core-3.11.0/lib/rspec/core/hooks.rb:365
c:0042 p:0007 s:0209 e:000208 BLOCK  /usr/local/bundle/gems/rspec-core-3.11.0/lib/rspec/core/hooks.rb:529 [FINISH]
c:0041 p:---- s:0205 e:000204 CFUNC  :each
c:0040 p:0012 s:0201 e:000200 METHOD /usr/local/bundle/gems/rspec-core-3.11.0/lib/rspec/core/hooks.rb:528
c:0039 p:0013 s:0194 e:000193 BLOCK  /usr/local/bundle/gems/rspec-core-3.11.0/lib/rspec/core/hooks.rb:615 [FINISH]
c:0038 p:---- s:0190 e:000189 CFUNC  :reverse_each

Repro

  1. Pull either docker pull ruby:3.0.4-alpine3.15 or docker pull ruby:3.1.2-alpine3.15
  2. Save this file as repro.rb in container
  3. Run command to install imagemagick 7, apk add pkgconfig imagemagick imagemagick-dev imagemagick-libs
  4. Run command to install sqlite3 apk add sqlite sqlite-dev
  5. Run command to install other sys libs apk add build-base gcc autoconf libffi-dev openssl-dev
  6. Run ruby repro.rb inside docker container
# frozen_string_literal: true

require 'bundler/inline'

gemfile(true) do
  source 'https://rubygems.org'

  git_source(:github) { |repo| "https://github.com/#{repo}.git" }

  gem 'rails', '~> 7.0.2.3'
  gem 'rspec-rails', '~> 5.1.1'

  gem 'carrierwave'
  gem 'rmagick', '~> 4.2.5'

  # either gem would make interpreter blows up
  # adding , require: false would on either gem would make it work but not ideal
  # gem 'rbtree'
  gem 'sorted_set'
  gem 'sqlite3'
end

require 'rmagick'

require 'active_support'
require 'active_support/core_ext/object/blank'
require 'active_record'

require 'action_controller/railtie'
require 'action_view/railtie'

require 'rspec/autorun'
require 'rspec/rails'
require 'carrierwave/orm/activerecord'

ActiveRecord::Base.establish_connection(adapter: 'sqlite3', database: ':memory:')

ActiveRecord::Schema.define do
  drop_table :users, if_exists: true

  create_table :users, force: true do |t|
    t.timestamps null: false
    t.string :avatar
  end
end

class AvatarUploader < CarrierWave::Uploader::Base
  include CarrierWave::RMagick
  storage :file

  process resize_to_fit: [777, 777]
end

class User < ActiveRecord::Base
  mount_uploader :avatar, AvatarUploader
end

RSpec.configure do |config|
  config.filter_run_excluding skip: true
  config.run_all_when_everything_filtered = true
  config.filter_run focus: true
end

RSpec.describe 'Segfault error' do
  let(:user) { User.new }
  let(:file) { Tempfile.new }
  let(:avatar) { Rack::Test::UploadedFile.new(file, 'application/pdf', true, original_filename: 'sample.pdf') }
  let(:avatar_key) { sample_key(User.new.uploader, extension: 'pdf') }

  before do
    user.avatar = avatar
  end

  it { expect(user.avatar).to eq(avatar) }
end

`include?` returns nil instead of false if not included

i found a potentially breaking change compared to the stdlib version of SortedSet:

on Ruby 2.7:

require 'set'
SortedSet.new.include?(1) # => false

on Ruby 3.0:

require 'sorted_set'
SortedSet.new.include?(1) # => nil

RBTree and Set return false in this case, but this code in set leads to nil being returned if anything other than a Hash defaulting to false is used as @hash. I guess this could either be fixed here in sorted_set by overriding #include? and its aliases, or in set by adding !! or so to the return value?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.