From: bosticko@... Date: 2020-07-05T16:42:36+00:00 Subject: [ruby-core:99071] [Ruby master Bug#17014] Range#minmax returns incorrect results on non-numeric exclusive ranges Issue #17014 has been reported by sambostock (Sam Bostock). ---------------------------------------- Bug #17014: Range#minmax returns incorrect results on non-numeric exclusive ranges https://bugs.ruby-lang.org/issues/17014 * Author: sambostock (Sam Bostock) * Status: Open * Priority: Normal * ruby -v: 2.7.1 * Backport: 2.5: UNKNOWN, 2.6: UNKNOWN, 2.7: UNKNOWN ---------------------------------------- The implementation of `Range#minmax` added in [d5c60214c45](https://github.com/ruby/ruby/commit/d5c60214c45bafc1cf2a516f852394986f9c84bb) causes the following incorrect behaviour: ```ruby ('a'...'c').minmax # => ["a", ["a", "b"]] ``` instead of ```ruby ('a'...'c').minmax # => ["a", "b"] ``` ### Cause This is because the C implementation of `Range#minmax` (`range_minmax`) directly delegates to the C implementation of `Range#min` (`range_min`) and `Range#max` (`range_max`), without changing the execution context. `Range#max`'s C implementation (`range_max`), when given a non-numeric exclusive range, delegates to `super`, which is meant to call `Enumerable#max`. However, because `range_max` is called directly by `range_minmax`, `super` calls `Enumerable#minmax` instead, causing the incorrect nesting. ### Resolution - [ruby/ruby#3285](https://github.com/ruby/ruby/pull/3285) fixed this bug by explicitly calling `Range#min` and `Range#max`, instead of delegating **directly** to `range_min` and `range_max` - [ruby/ruby#3286](https://github.com/ruby/ruby/pull/3286) followed up by replacing `rb_intern("min")` and `rb_intern("max")` in the new implementation with statics `id_min` and `id_max` - [ruby/ruby#3290](https://github.com/ruby/ruby/pull/3290) follows up by extracting `range_min_internal` and `range_max_internal` from `range_min` and `range_max`, and calling those directly from `range_minmax` -- https://bugs.ruby-lang.org/ Unsubscribe: