Project

General

Profile

Actions

Bug #18577

closed

Range#include? returns wrong result for beginless range with exclusive string end

Added by takaram (Takuya Aramaki) almost 3 years ago. Updated almost 3 years ago.

Status:
Closed
Assignee:
-
Target version:
-
ruby -v:
ruby 3.1.0p0 (2021-12-25 revision fb4df44d16) [x86_64-linux]
[ruby-core:107521]

Description

Exclusive range should not include the end value, but (...'z').include? 'z' returns true. member? and === behave in the same way, while cover? does not.
This happens when the range is beginless and its end is string.

irb(main):001:0> (...'z').include? 'z'
=> true
irb(main):002:0> (...'z').member? 'z'
=> true
irb(main):003:0> (...'z') === 'z'
=> true
irb(main):004:0> (...'z').cover? 'z'
=> false

Updated by zverok (Victor Shepelev) almost 3 years ago

It seems that the cause is unnecessary (?) specialization of Range#include? for String arguments.

I believe string ranges should just fallback to the default implementation:

(...Date.today) === Date.today
# => false 
(...Date.today).cover? Date.today
# => false 
(...Date.today).include? Date.today
# in `each': can't iterate from NilClass (TypeError)

The removal of specialization will also fix current (and possible future) discrepancies of Range#cover? and Range#=== for String ranges.

If it is not acceptable (some cases of backward compatibility?), this statement should be fixed.

cc @jeremyevans0 (Jeremy Evans)

Updated by jeremyevans0 (Jeremy Evans) almost 3 years ago

zverok (Victor Shepelev) wrote in #note-1:

It seems that the cause is unnecessary (?) specialization of Range#include? for String arguments.

I believe string ranges should just fallback to the default implementation:

(...Date.today) === Date.today
# => false 
(...Date.today).cover? Date.today
# => false 
(...Date.today).include? Date.today
# in `each': can't iterate from NilClass (TypeError)

The removal of specialization will also fix current (and possible future) discrepancies of Range#cover? and Range#=== for String ranges.

If you want to remove the specialization, that's something that probably should be discussed at a developer meeting. I am against removing it. Not because I think the specialization is a good idea, but because I don't think it's worth breaking backwards compatibility (raising TypeError for previously working code).

If it is not acceptable (some cases of backward compatibility?), this statement should be fixed.

I submitted a pull request to fix this: https://github.com/ruby/ruby/pull/5541

Actions #3

Updated by jeremyevans (Jeremy Evans) almost 3 years ago

  • Status changed from Open to Closed

Applied in changeset git|fd710d7e9995679db80b7adf35bbda2cd4db90c6.


Fix Range#include? for beginless exclusive string ranges

Previously, include? would return true for the end of the range,
when it should return false because the range is exclusive.

Research and Analysis by Victor Shepelev.

Fixes [Bug #18577]

Actions

Also available in: Atom PDF

Like0
Like0Like0Like0