From: nagachika00@... Date: 2020-07-19T03:16:49+00:00 Subject: [ruby-core:99220] [Ruby master Bug#17014] Range#minmax returns incorrect results on non-numeric exclusive ranges Issue #17014 has been updated by nagachika (Tomoyuki Chikanaga). Backport changed from 2.5: DONTNEED, 2.6: DONTNEED, 2.7: REQUIRED to 2.5: DONTNEED, 2.6: DONTNEED, 2.7: DONE ruby_2_7 d24cce8e7f48b0b45f726f5f1ac7ff796f46ba72 merged revision(s) bf1a6771f305ea286a3ae575676924551c03e857,c1463625555b061a2b94c3b6c5581730b482a285. ---------------------------------------- Bug #17014: Range#minmax returns incorrect results on non-numeric exclusive ranges https://bugs.ruby-lang.org/issues/17014#change-86601 * Author: sambostock (Sam Bostock) * Status: Closed * Priority: Normal * ruby -v: 2.7.1 * Backport: 2.5: DONTNEED, 2.6: DONTNEED, 2.7: DONE ---------------------------------------- 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: