[ruby-core:112922] [Ruby master Bug#19533] Behavior of ===/include? on a beginless/endless range (nil..nil) changed in ruby 3.2

Issue #19533 has been reported by knu (Akinori MUSHA). ---------------------------------------- Bug #19533: Behavior of ===/include? on a beginless/endless range (nil..nil) changed in ruby 3.2 https://bugs.ruby-lang.org/issues/19533 * Author: knu (Akinori MUSHA) * Status: Open * Priority: Normal * Target version: 3.2 * ruby -v: ruby 3.2.1 (2023-02-08 revision 31819e82c8) [x86_64-darwin22] * Backport: 2.7: UNKNOWN, 3.0: UNKNOWN, 3.1: UNKNOWN, 3.2: UNKNOWN ---------------------------------------- Starting from Ruby 2.7.0 a range `nil..nil` used to match any value until 3.2.0-preview3, but 3.2.0-rc1 started to reject it. ``` % docker run -it --rm rubylang/all-ruby ./all-ruby -e 'p( (nil..nil) === 1 )' (snip) ruby-2.6.10 false ruby-2.7.0-preview1 true ... ruby-3.2.0-preview3 true ruby-3.2.0-rc1 -e:1:in `===': cannot determine inclusion in beginless/endless ranges (TypeError) p( (nil..nil) === 1 ) ^ from -e:1:in `<main>' exit 1 ... ruby-3.2.1 -e:1:in `===': cannot determine inclusion in beginless/endless ranges (TypeError) p( (nil..nil) === 1 ) ^ from -e:1:in `<main>' ``` The previous behavior was so useful because when you have optional lower and upper bounds `lbound..rbound` would always work regardless of each end being nil or not. There is no mention of this in doc/NEWS/NEWS-3.2.0.md, so I'm afraid it was caused unintentionally while fixing other problems. ``` % docker run -it --rm rubylang/all-ruby ./all-ruby -e 'p( (nil..nil).cover?(1) )' (snip) ruby-2.6.10 false ruby-2.7.0-preview1 true ... ruby-3.2.1 true ``` This was pointed out by the following blog article (written in Japanese) as a "pitfall" that you need to work around when upgrading Ruby from 3.0/3.1 to 3.2. https://blog.studysapuri.jp/entry/2023/03/16/ujihisa-ruby32#endless-range%E3... -- https://bugs.ruby-lang.org/

Issue #19533 has been updated by mame (Yusuke Endoh). In #18580, @matz said:
I decided to make `include?` to raise exception for beginless/endless non-numeric ranges.
and `(nil..nil)` is considered as a non-numeric range. ---------------------------------------- Bug #19533: Behavior of ===/include? on a beginless/endless range (nil..nil) changed in ruby 3.2 https://bugs.ruby-lang.org/issues/19533#change-102444 * Author: knu (Akinori MUSHA) * Status: Open * Priority: Normal * Target version: 3.2 * ruby -v: ruby 3.2.1 (2023-02-08 revision 31819e82c8) [x86_64-darwin22] * Backport: 2.7: UNKNOWN, 3.0: UNKNOWN, 3.1: UNKNOWN, 3.2: UNKNOWN ---------------------------------------- Starting from Ruby 2.7.0 a range `nil..nil` used to match any value until 3.2.0-preview3, but 3.2.0-rc1 started to reject it. ``` % docker run -it --rm rubylang/all-ruby ./all-ruby -e 'p( (nil..nil) === 1 )' (snip) ruby-2.6.10 false ruby-2.7.0-preview1 true ... ruby-3.2.0-preview3 true ruby-3.2.0-rc1 -e:1:in `===': cannot determine inclusion in beginless/endless ranges (TypeError) p( (nil..nil) === 1 ) ^ from -e:1:in `<main>' exit 1 ... ruby-3.2.1 -e:1:in `===': cannot determine inclusion in beginless/endless ranges (TypeError) p( (nil..nil) === 1 ) ^ from -e:1:in `<main>' ``` The previous behavior was so useful because when you have optional lower and upper bounds `lbound..rbound` would always work regardless of each end being nil or not. There is no mention of this in doc/NEWS/NEWS-3.2.0.md, so I'm afraid it was caused unintentionally while fixing other problems. ``` % docker run -it --rm rubylang/all-ruby ./all-ruby -e 'p( (nil..nil).cover?(1) )' (snip) ruby-2.6.10 false ruby-2.7.0-preview1 true ... ruby-3.2.1 true ``` This was pointed out by the following blog article (written in Japanese) as a "pitfall" that you need to work around when upgrading Ruby from 3.0/3.1 to 3.2. https://blog.studysapuri.jp/entry/2023/03/16/ujihisa-ruby32#endless-range%E3... -- https://bugs.ruby-lang.org/

Issue #19533 has been updated by knu (Akinori MUSHA). mame (Yusuke Endoh) wrote in #note-2:
In #18580, @matz said:
I decided to make `include?` to raise exception for beginless/endless non-numeric ranges.
and `(nil..nil)` is considered as a non-numeric range.
Thanks for the info. This hurts not only because the behavior changed without notice (in the NEWS file) but because it broke the useful feature. Before the change, you could just say `scores.grep(min..max)` when `min` and `max` are both optional, but now you need to check if `min` and `max` are both nil and branch the logic. While `(nil..nil) === value` (used in `case`, `Enumerable#grep`, `any?`, etc.) no longer works, ActiveRecord queries like `Product.where(price: min..max)` still work because `===` is not used there. This is a bit confusing and hard to explain why. I'm not absolutely sure about `include?`, but as for `===` I'd like the previous behavior to be restored because it was so useful and aligned with `cover?`, and changing back wouldn't break existing code because the current behavior is to raise an error rather than returning false. ---------------------------------------- Bug #19533: Behavior of ===/include? on a beginless/endless range (nil..nil) changed in ruby 3.2 https://bugs.ruby-lang.org/issues/19533#change-102447 * Author: knu (Akinori MUSHA) * Status: Open * Priority: Normal * Target version: 3.2 * ruby -v: ruby 3.2.1 (2023-02-08 revision 31819e82c8) [x86_64-darwin22] * Backport: 2.7: UNKNOWN, 3.0: UNKNOWN, 3.1: UNKNOWN, 3.2: UNKNOWN ---------------------------------------- Starting from Ruby 2.7.0 a range `nil..nil` used to match any value until 3.2.0-preview3, but 3.2.0-rc1 started to reject it. ``` % docker run -it --rm rubylang/all-ruby ./all-ruby -e 'p( (nil..nil) === 1 )' (snip) ruby-2.6.10 false ruby-2.7.0-preview1 true ... ruby-3.2.0-preview3 true ruby-3.2.0-rc1 -e:1:in `===': cannot determine inclusion in beginless/endless ranges (TypeError) p( (nil..nil) === 1 ) ^ from -e:1:in `<main>' exit 1 ... ruby-3.2.1 -e:1:in `===': cannot determine inclusion in beginless/endless ranges (TypeError) p( (nil..nil) === 1 ) ^ from -e:1:in `<main>' ``` The previous behavior was so useful because when you have optional lower and upper bounds `lbound..rbound` would always work regardless of each end being nil or not. There is no mention of this in doc/NEWS/NEWS-3.2.0.md, so I'm afraid it was caused unintentionally while fixing other problems. ``` % docker run -it --rm rubylang/all-ruby ./all-ruby -e 'p( (nil..nil).cover?(1) )' (snip) ruby-2.6.10 false ruby-2.7.0-preview1 true ... ruby-3.2.1 true ``` This was pointed out by the following blog article (written in Japanese) as a "pitfall" that you need to work around when upgrading Ruby from 3.0/3.1 to 3.2. https://blog.studysapuri.jp/entry/2023/03/16/ujihisa-ruby32#endless-range%E3... -- https://bugs.ruby-lang.org/

Issue #19533 has been updated by nobu (Nobuyoshi Nakada). https://github.com/nobu/ruby/tree/infinite-range-inclusion ---------------------------------------- Bug #19533: Behavior of ===/include? on a beginless/endless range (nil..nil) changed in ruby 3.2 https://bugs.ruby-lang.org/issues/19533#change-102500 * Author: knu (Akinori MUSHA) * Status: Open * Priority: Normal * Target version: 3.2 * ruby -v: ruby 3.2.1 (2023-02-08 revision 31819e82c8) [x86_64-darwin22] * Backport: 2.7: UNKNOWN, 3.0: UNKNOWN, 3.1: UNKNOWN, 3.2: UNKNOWN ---------------------------------------- Starting from Ruby 2.7.0 a range `nil..nil` used to match any value until 3.2.0-preview3, but 3.2.0-rc1 started to reject it. ``` % docker run -it --rm rubylang/all-ruby ./all-ruby -e 'p( (nil..nil) === 1 )' (snip) ruby-2.6.10 false ruby-2.7.0-preview1 true ... ruby-3.2.0-preview3 true ruby-3.2.0-rc1 -e:1:in `===': cannot determine inclusion in beginless/endless ranges (TypeError) p( (nil..nil) === 1 ) ^ from -e:1:in `<main>' exit 1 ... ruby-3.2.1 -e:1:in `===': cannot determine inclusion in beginless/endless ranges (TypeError) p( (nil..nil) === 1 ) ^ from -e:1:in `<main>' ``` The previous behavior was so useful because when you have optional lower and upper bounds `lbound..rbound` would always work regardless of each end being nil or not. There is no mention of this in doc/NEWS/NEWS-3.2.0.md, so I'm afraid it was caused unintentionally while fixing other problems. ``` % docker run -it --rm rubylang/all-ruby ./all-ruby -e 'p( (nil..nil).cover?(1) )' (snip) ruby-2.6.10 false ruby-2.7.0-preview1 true ... ruby-3.2.1 true ``` This was pointed out by the following blog article (written in Japanese) as a "pitfall" that you need to work around when upgrading Ruby from 3.0/3.1 to 3.2. https://blog.studysapuri.jp/entry/2023/03/16/ujihisa-ruby32#endless-range%E3... -- https://bugs.ruby-lang.org/

Issue #19533 has been updated by matz (Yukihiro Matsumoto). It is an unintentional behavior. I agree to fix `nil .. nil` case. Matz. ---------------------------------------- Bug #19533: Behavior of ===/include? on a beginless/endless range (nil..nil) changed in ruby 3.2 https://bugs.ruby-lang.org/issues/19533#change-102757 * Author: knu (Akinori MUSHA) * Status: Open * Priority: Normal * Target version: 3.2 * ruby -v: ruby 3.2.1 (2023-02-08 revision 31819e82c8) [x86_64-darwin22] * Backport: 2.7: UNKNOWN, 3.0: UNKNOWN, 3.1: UNKNOWN, 3.2: UNKNOWN ---------------------------------------- Starting from Ruby 2.7.0 a range `nil..nil` used to match any value until 3.2.0-preview3, but 3.2.0-rc1 started to reject it. ``` % docker run -it --rm rubylang/all-ruby ./all-ruby -e 'p( (nil..nil) === 1 )' (snip) ruby-2.6.10 false ruby-2.7.0-preview1 true ... ruby-3.2.0-preview3 true ruby-3.2.0-rc1 -e:1:in `===': cannot determine inclusion in beginless/endless ranges (TypeError) p( (nil..nil) === 1 ) ^ from -e:1:in `<main>' exit 1 ... ruby-3.2.1 -e:1:in `===': cannot determine inclusion in beginless/endless ranges (TypeError) p( (nil..nil) === 1 ) ^ from -e:1:in `<main>' ``` The previous behavior was so useful because when you have optional lower and upper bounds `lbound..rbound` would always work regardless of each end being nil or not. There is no mention of this in doc/NEWS/NEWS-3.2.0.md, so I'm afraid it was caused unintentionally while fixing other problems. ``` % docker run -it --rm rubylang/all-ruby ./all-ruby -e 'p( (nil..nil).cover?(1) )' (snip) ruby-2.6.10 false ruby-2.7.0-preview1 true ... ruby-3.2.1 true ``` This was pointed out by the following blog article (written in Japanese) as a "pitfall" that you need to work around when upgrading Ruby from 3.0/3.1 to 3.2. https://blog.studysapuri.jp/entry/2023/03/16/ujihisa-ruby32#endless-range%E3... -- https://bugs.ruby-lang.org/

Issue #19533 has been updated by nagachika (Tomoyuki Chikanaga). Backport changed from 2.7: DONTNEED, 3.0: DONTNEED, 3.1: DONTNEED, 3.2: REQUIRED to 2.7: DONTNEED, 3.0: DONTNEED, 3.1: DONTNEED, 3.2: DONE ruby_3_2 5328c58c7d00540f4f56749aaeefb68761bd7eba merged revision(s) 1a149aab776aa6741628eb35482eff1ded197fd2,fb17c833f542222afdf482924877d43aa577782d,60f22ebf86248388b41b4ec751d16700f2b4b621. ---------------------------------------- Bug #19533: Behavior of ===/include? on a beginless/endless range (nil..nil) changed in ruby 3.2 https://bugs.ruby-lang.org/issues/19533#change-103899 * Author: knu (Akinori MUSHA) * Status: Closed * Priority: Normal * Target version: 3.2 * ruby -v: ruby 3.2.1 (2023-02-08 revision 31819e82c8) [x86_64-darwin22] * Backport: 2.7: DONTNEED, 3.0: DONTNEED, 3.1: DONTNEED, 3.2: DONE ---------------------------------------- Starting from Ruby 2.7.0 a range `nil..nil` used to match any value until 3.2.0-preview3, but 3.2.0-rc1 started to reject it. ``` % docker run -it --rm rubylang/all-ruby ./all-ruby -e 'p( (nil..nil) === 1 )' (snip) ruby-2.6.10 false ruby-2.7.0-preview1 true ... ruby-3.2.0-preview3 true ruby-3.2.0-rc1 -e:1:in `===': cannot determine inclusion in beginless/endless ranges (TypeError) p( (nil..nil) === 1 ) ^ from -e:1:in `<main>' exit 1 ... ruby-3.2.1 -e:1:in `===': cannot determine inclusion in beginless/endless ranges (TypeError) p( (nil..nil) === 1 ) ^ from -e:1:in `<main>' ``` The previous behavior was so useful because when you have optional lower and upper bounds `lbound..rbound` would always work regardless of each end being nil or not. There is no mention of this in doc/NEWS/NEWS-3.2.0.md, so I'm afraid it was caused unintentionally while fixing other problems. ``` % docker run -it --rm rubylang/all-ruby ./all-ruby -e 'p( (nil..nil).cover?(1) )' (snip) ruby-2.6.10 false ruby-2.7.0-preview1 true ... ruby-3.2.1 true ``` This was pointed out by the following blog article (written in Japanese) as a "pitfall" that you need to work around when upgrading Ruby from 3.0/3.1 to 3.2. https://blog.studysapuri.jp/entry/2023/03/16/ujihisa-ruby32#endless-range%E3... -- https://bugs.ruby-lang.org/
participants (5)
-
knu (Akinori MUSHA)
-
mame (Yusuke Endoh)
-
matz (Yukihiro Matsumoto)
-
nagachika (Tomoyuki Chikanaga)
-
nobu (Nobuyoshi Nakada)