Forum: Ruby-core [ruby-trunk - Bug #8872][Open] Case statements do not honor a refinement of the '===' method

20cc631a711e5190cfc7e6b59a845414?d=identicon&s=25 jconley88 (Jon Conley) (Guest)
on 2013-09-07 07:17
(Received via mailing list)
Issue #8872 has been reported by jconley88 (Jon Conley).

----------------------------------------
Bug #8872: Case statements do not honor a refinement of the '===' method
https://bugs.ruby-lang.org/issues/8872

Author: jconley88 (Jon Conley)
Status: Open
Priority: Normal
Assignee:
Category:
Target version:
ruby -v: ruby 2.0.0p247 (2013-06-27 revision 41674)
[x86_64-darwin11.4.2]
Backport: 1.9.3: UNKNOWN, 2.0.0: UNKNOWN


=begin
Below, I've redefined the ((|===|)) method of symbol to always return
true.  In ((|RefineTest#uses_refinement|)), I call ((|===|)) directly
and the refined method is called.  In
((|RefineTest#does_not_use_refinement|)), the ((|===|)) method is called
indirectly through a case statement.  If the refined ((|===|)) method
was called, the result should be ((*'The refinement was used'*)), but
this code currently returns ((*'The refinement was not used'*)).

 module RefineSymbol
   refine Symbol do
     def ===(other)
       true
     end
   end
 end

 using RefineSymbol

 class RefineTest
   def uses_refinement
     :a === :b
   end

   def does_not_use_refinement
     case :a
     when :b
       'The refinement was used'
     else
       'The refinement was not used'
     end
   end
 end

 rt = RefineTest.new
 rt.uses_refinement   # => true
 rt.does_not_use_refinement  # => expected 'The refinement was used' but
got 'The refinement was not used'
=end
F736999f7c1b7a87a100faa112bbc0f3?d=identicon&s=25 charliesome (Charlie Somerville) (Guest)
on 2013-09-07 08:48
(Received via mailing list)
Issue #8872 has been updated by charliesome (Charlie Somerville).

Backport changed from 1.9.3: UNKNOWN, 2.0.0: UNKNOWN to 1.9.3: DONTNEED,
2.0.0: REQUIRED


----------------------------------------
Bug #8872: Case statements do not honor a refinement of the '===' method
https://bugs.ruby-lang.org/issues/8872#change-41662

Author: jconley88 (Jon Conley)
Status: Closed
Priority: Normal
Assignee:
Category:
Target version:
ruby -v: ruby 2.0.0p247 (2013-06-27 revision 41674)
[x86_64-darwin11.4.2]
Backport: 1.9.3: DONTNEED, 2.0.0: REQUIRED


=begin
Below, I've redefined the ((|===|)) method of symbol to always return
true.  In ((|RefineTest#uses_refinement|)), I call ((|===|)) directly
and the refined method is called.  In
((|RefineTest#does_not_use_refinement|)), the ((|===|)) method is called
indirectly through a case statement.  If the refined ((|===|)) method
was called, the result should be ((*'The refinement was used'*)), but
this code currently returns ((*'The refinement was not used'*)).

 module RefineSymbol
   refine Symbol do
     def ===(other)
       true
     end
   end
 end

 using RefineSymbol

 class RefineTest
   def uses_refinement
     :a === :b
   end

   def does_not_use_refinement
     case :a
     when :b
       'The refinement was used'
     else
       'The refinement was not used'
     end
   end
 end

 rt = RefineTest.new
 rt.uses_refinement   # => true
 rt.does_not_use_refinement  # => expected 'The refinement was used' but
got 'The refinement was not used'
=end
B14001f2b40640dd6cb63f0e8f1f4869?d=identicon&s=25 Andrew White (pixeltrix)
on 2013-11-26 17:48
(Received via mailing list)
Issue #8872 has been updated by pixeltrix (Andrew White).


This has caused a regression in Rails where `===` isn't  being sent via
`method_missing`:

  https://github.com/rails/rails/pull/13055

This results in a segmentation fault.
----------------------------------------
Backport #8872: Case statements do not honor a refinement of the '==='
method
https://bugs.ruby-lang.org/issues/8872#change-43176

Author: jconley88 (Jon Conley)
Status: Closed
Priority: Normal
Assignee: nagachika (Tomoyuki Chikanaga)
Category:
Target version:


=begin
Below, I've redefined the ((|===|)) method of symbol to always return
true.  In ((|RefineTest#uses_refinement|)), I call ((|===|)) directly
and the refined method is called.  In
((|RefineTest#does_not_use_refinement|)), the ((|===|)) method is called
indirectly through a case statement.  If the refined ((|===|)) method
was called, the result should be ((*'The refinement was used'*)), but
this code currently returns ((*'The refinement was not used'*)).

 module RefineSymbol
   refine Symbol do
     def ===(other)
       true
     end
   end
 end

 using RefineSymbol

 class RefineTest
   def uses_refinement
     :a === :b
   end

   def does_not_use_refinement
     case :a
     when :b
       'The refinement was used'
     else
       'The refinement was not used'
     end
   end
 end

 rt = RefineTest.new
 rt.uses_refinement   # => true
 rt.does_not_use_refinement  # => expected 'The refinement was used' but
got 'The refinement was not used'
=end
C4f076f658dd3464f1d8785ad53a0d99?d=identicon&s=25 sorah (Shota Fukumori) (Guest)
on 2013-11-29 09:59
(Received via mailing list)
Issue #8872 has been updated by sorah (Shota Fukumori).


@pixeltrix Fixed at r43913, Thank you for your reporting
----------------------------------------
Backport #8872: Case statements do not honor a refinement of the '==='
method
https://bugs.ruby-lang.org/issues/8872#change-43242

Author: jconley88 (Jon Conley)
Status: Closed
Priority: Normal
Assignee: nagachika (Tomoyuki Chikanaga)
Category:
Target version:


=begin
Below, I've redefined the ((|===|)) method of symbol to always return
true.  In ((|RefineTest#uses_refinement|)), I call ((|===|)) directly
and the refined method is called.  In
((|RefineTest#does_not_use_refinement|)), the ((|===|)) method is called
indirectly through a case statement.  If the refined ((|===|)) method
was called, the result should be ((*'The refinement was used'*)), but
this code currently returns ((*'The refinement was not used'*)).

 module RefineSymbol
   refine Symbol do
     def ===(other)
       true
     end
   end
 end

 using RefineSymbol

 class RefineTest
   def uses_refinement
     :a === :b
   end

   def does_not_use_refinement
     case :a
     when :b
       'The refinement was used'
     else
       'The refinement was not used'
     end
   end
 end

 rt = RefineTest.new
 rt.uses_refinement   # => true
 rt.does_not_use_refinement  # => expected 'The refinement was used' but
got 'The refinement was not used'
=end
C4e88907313843cf07f6d85ba8162120?d=identicon&s=25 shugo (Shugo Maeda) (Guest)
on 2013-11-29 10:12
(Received via mailing list)
Issue #8872 has been updated by shugo (Shugo Maeda).

Status changed from Closed to Assigned
Assignee changed from nagachika (Tomoyuki Chikanaga) to matz (Yukihiro
Matsumoto)

As I stated in #9150, I doubt this feature conforms to the design policy
of refinements.
r42869 should be reverted, shouldn't it, Matz?
----------------------------------------
Backport #8872: Case statements do not honor a refinement of the '==='
method
https://bugs.ruby-lang.org/issues/8872#change-43243

Author: jconley88 (Jon Conley)
Status: Assigned
Priority: Normal
Assignee: matz (Yukihiro Matsumoto)
Category:
Target version:


=begin
Below, I've redefined the ((|===|)) method of symbol to always return
true.  In ((|RefineTest#uses_refinement|)), I call ((|===|)) directly
and the refined method is called.  In
((|RefineTest#does_not_use_refinement|)), the ((|===|)) method is called
indirectly through a case statement.  If the refined ((|===|)) method
was called, the result should be ((*'The refinement was used'*)), but
this code currently returns ((*'The refinement was not used'*)).

 module RefineSymbol
   refine Symbol do
     def ===(other)
       true
     end
   end
 end

 using RefineSymbol

 class RefineTest
   def uses_refinement
     :a === :b
   end

   def does_not_use_refinement
     case :a
     when :b
       'The refinement was used'
     else
       'The refinement was not used'
     end
   end
 end

 rt = RefineTest.new
 rt.uses_refinement   # => true
 rt.does_not_use_refinement  # => expected 'The refinement was used' but
got 'The refinement was not used'
=end
C4e88907313843cf07f6d85ba8162120?d=identicon&s=25 shugo (Shugo Maeda) (Guest)
on 2013-11-29 10:24
(Received via mailing list)
Issue #8872 has been updated by shugo (Shugo Maeda).


I strongly request committers not to change the behavior of Refinements
without Matz's permission, except when there's an obvious bug such as
SEGV in Refinements, because the current feature set of Refinements are
restricted to keep compatibility with other implementations such as
JRuby.

In general, refinements should be activated only in a certain lexical
scope.
----------------------------------------
Backport #8872: Case statements do not honor a refinement of the '==='
method
https://bugs.ruby-lang.org/issues/8872#change-43244

Author: jconley88 (Jon Conley)
Status: Assigned
Priority: Normal
Assignee: matz (Yukihiro Matsumoto)
Category:
Target version:


=begin
Below, I've redefined the ((|===|)) method of symbol to always return
true.  In ((|RefineTest#uses_refinement|)), I call ((|===|)) directly
and the refined method is called.  In
((|RefineTest#does_not_use_refinement|)), the ((|===|)) method is called
indirectly through a case statement.  If the refined ((|===|)) method
was called, the result should be ((*'The refinement was used'*)), but
this code currently returns ((*'The refinement was not used'*)).

 module RefineSymbol
   refine Symbol do
     def ===(other)
       true
     end
   end
 end

 using RefineSymbol

 class RefineTest
   def uses_refinement
     :a === :b
   end

   def does_not_use_refinement
     case :a
     when :b
       'The refinement was used'
     else
       'The refinement was not used'
     end
   end
 end

 rt = RefineTest.new
 rt.uses_refinement   # => true
 rt.does_not_use_refinement  # => expected 'The refinement was used' but
got 'The refinement was not used'
=end
C4f076f658dd3464f1d8785ad53a0d99?d=identicon&s=25 sorah (Shota Fukumori) (Guest)
on 2013-11-29 10:38
(Received via mailing list)
Issue #8872 has been updated by sorah (Shota Fukumori).


shugo (Shugo Maeda) wrote:
> I strongly request committers not to change the behavior of Refinements without
Matz's permission, except when there's an obvious bug such as SEGV in 
Refinements,
because the current feature set of Refinements are restricted to keep
compatibility with other implementations such as JRuby.
>
> In general, refinements should be activated only in a certain lexical scope.

Agreed.

Note that my commit (r43913) just fixes bug in the current behavior,
please revert it too with r42839, if we revert r42839.
----------------------------------------
Backport #8872: Case statements do not honor a refinement of the '==='
method
https://bugs.ruby-lang.org/issues/8872#change-43245

Author: jconley88 (Jon Conley)
Status: Assigned
Priority: Normal
Assignee: matz (Yukihiro Matsumoto)
Category:
Target version:


=begin
Below, I've redefined the ((|===|)) method of symbol to always return
true.  In ((|RefineTest#uses_refinement|)), I call ((|===|)) directly
and the refined method is called.  In
((|RefineTest#does_not_use_refinement|)), the ((|===|)) method is called
indirectly through a case statement.  If the refined ((|===|)) method
was called, the result should be ((*'The refinement was used'*)), but
this code currently returns ((*'The refinement was not used'*)).

 module RefineSymbol
   refine Symbol do
     def ===(other)
       true
     end
   end
 end

 using RefineSymbol

 class RefineTest
   def uses_refinement
     :a === :b
   end

   def does_not_use_refinement
     case :a
     when :b
       'The refinement was used'
     else
       'The refinement was not used'
     end
   end
 end

 rt = RefineTest.new
 rt.uses_refinement   # => true
 rt.does_not_use_refinement  # => expected 'The refinement was used' but
got 'The refinement was not used'
=end
0ec4920185b657a03edf01fff96b4e9b?d=identicon&s=25 matz (Yukihiro Matsumoto) (Guest)
on 2013-11-29 11:11
(Received via mailing list)
Issue #8872 has been updated by matz (Yukihiro Matsumoto).


The basic principle of refinements is that refinement do work in local
scope.
So methods called from the scope will be refined but method called from
methods called will not.

And very importantly, "===" called from case statement is controversial.
It can be viewed as a method called from case statement, or case
statement itself is just a syntax sugar wrapping "===" calls.  From the
former point of view, refine should not affect "===", but from the
latter POV, refinement should change the behavior.

Right now, we took the former POV, and OP expected the latter.
So I would like to hear from others.

Matz.

----------------------------------------
Backport #8872: Case statements do not honor a refinement of the '==='
method
https://bugs.ruby-lang.org/issues/8872#change-43250

Author: jconley88 (Jon Conley)
Status: Assigned
Priority: Normal
Assignee: matz (Yukihiro Matsumoto)
Category:
Target version:


=begin
Below, I've redefined the ((|===|)) method of symbol to always return
true.  In ((|RefineTest#uses_refinement|)), I call ((|===|)) directly
and the refined method is called.  In
((|RefineTest#does_not_use_refinement|)), the ((|===|)) method is called
indirectly through a case statement.  If the refined ((|===|)) method
was called, the result should be ((*'The refinement was used'*)), but
this code currently returns ((*'The refinement was not used'*)).

 module RefineSymbol
   refine Symbol do
     def ===(other)
       true
     end
   end
 end

 using RefineSymbol

 class RefineTest
   def uses_refinement
     :a === :b
   end

   def does_not_use_refinement
     case :a
     when :b
       'The refinement was used'
     else
       'The refinement was not used'
     end
   end
 end

 rt = RefineTest.new
 rt.uses_refinement   # => true
 rt.does_not_use_refinement  # => expected 'The refinement was used' but
got 'The refinement was not used'
=end
C4e88907313843cf07f6d85ba8162120?d=identicon&s=25 shugo (Shugo Maeda) (Guest)
on 2013-11-29 13:07
(Received via mailing list)
Issue #8872 has been updated by shugo (Shugo Maeda).


matz (Yukihiro Matsumoto) wrote:
> And very importantly, "===" called from case statement is controversial.
> It can be viewed as a method called from case statement, or case statement
itself is just a syntax sugar wrapping "===" calls.  From the former point of
view, refine should not affect "===", but from the latter POV, refinement should
change the behavior.

Ruby has other features which call methods implicitly.  For example,
Range#to_a is called by the following code:

  a = *[1..10]

Should refinements be honored in all such features?
----------------------------------------
Backport #8872: Case statements do not honor a refinement of the '==='
method
https://bugs.ruby-lang.org/issues/8872#change-43259

Author: jconley88 (Jon Conley)
Status: Assigned
Priority: Normal
Assignee: matz (Yukihiro Matsumoto)
Category:
Target version:


=begin
Below, I've redefined the ((|===|)) method of symbol to always return
true.  In ((|RefineTest#uses_refinement|)), I call ((|===|)) directly
and the refined method is called.  In
((|RefineTest#does_not_use_refinement|)), the ((|===|)) method is called
indirectly through a case statement.  If the refined ((|===|)) method
was called, the result should be ((*'The refinement was used'*)), but
this code currently returns ((*'The refinement was not used'*)).

 module RefineSymbol
   refine Symbol do
     def ===(other)
       true
     end
   end
 end

 using RefineSymbol

 class RefineTest
   def uses_refinement
     :a === :b
   end

   def does_not_use_refinement
     case :a
     when :b
       'The refinement was used'
     else
       'The refinement was not used'
     end
   end
 end

 rt = RefineTest.new
 rt.uses_refinement   # => true
 rt.does_not_use_refinement  # => expected 'The refinement was used' but
got 'The refinement was not used'
=end
C4e88907313843cf07f6d85ba8162120?d=identicon&s=25 shugo (Shugo Maeda) (Guest)
on 2013-11-29 14:29
(Received via mailing list)
Issue #8872 has been updated by shugo (Shugo Maeda).


I've found that for expressions honor refinements.

module RefineEach
  refine Array do
    def each
      yield "refined"
    end
  end
end

using RefineEach

for i in [1, 2, 3]
  p i
end

for expressions seem to be more closely related to method calls, but I'm
not sure how refinements should be handled in these cases....
----------------------------------------
Backport #8872: Case statements do not honor a refinement of the '==='
method
https://bugs.ruby-lang.org/issues/8872#change-43265

Author: jconley88 (Jon Conley)
Status: Assigned
Priority: Normal
Assignee: matz (Yukihiro Matsumoto)
Category:
Target version:


=begin
Below, I've redefined the ((|===|)) method of symbol to always return
true.  In ((|RefineTest#uses_refinement|)), I call ((|===|)) directly
and the refined method is called.  In
((|RefineTest#does_not_use_refinement|)), the ((|===|)) method is called
indirectly through a case statement.  If the refined ((|===|)) method
was called, the result should be ((*'The refinement was used'*)), but
this code currently returns ((*'The refinement was not used'*)).

 module RefineSymbol
   refine Symbol do
     def ===(other)
       true
     end
   end
 end

 using RefineSymbol

 class RefineTest
   def uses_refinement
     :a === :b
   end

   def does_not_use_refinement
     case :a
     when :b
       'The refinement was used'
     else
       'The refinement was not used'
     end
   end
 end

 rt = RefineTest.new
 rt.uses_refinement   # => true
 rt.does_not_use_refinement  # => expected 'The refinement was used' but
got 'The refinement was not used'
=end
C4e88907313843cf07f6d85ba8162120?d=identicon&s=25 Eregon (Benoit Daloze) (Guest)
on 2013-11-29 14:33
(Received via mailing list)
Issue #8872 has been updated by Eregon (Benoit Daloze).


shugo (Shugo Maeda) wrote:
>
>   a = *[1..10]

You probably meant

    a = [*1..10]

----------------------------------------
Backport #8872: Case statements do not honor a refinement of the '==='
method
https://bugs.ruby-lang.org/issues/8872#change-43266

Author: jconley88 (Jon Conley)
Status: Assigned
Priority: Normal
Assignee: matz (Yukihiro Matsumoto)
Category:
Target version:


=begin
Below, I've redefined the ((|===|)) method of symbol to always return
true.  In ((|RefineTest#uses_refinement|)), I call ((|===|)) directly
and the refined method is called.  In
((|RefineTest#does_not_use_refinement|)), the ((|===|)) method is called
indirectly through a case statement.  If the refined ((|===|)) method
was called, the result should be ((*'The refinement was used'*)), but
this code currently returns ((*'The refinement was not used'*)).

 module RefineSymbol
   refine Symbol do
     def ===(other)
       true
     end
   end
 end

 using RefineSymbol

 class RefineTest
   def uses_refinement
     :a === :b
   end

   def does_not_use_refinement
     case :a
     when :b
       'The refinement was used'
     else
       'The refinement was not used'
     end
   end
 end

 rt = RefineTest.new
 rt.uses_refinement   # => true
 rt.does_not_use_refinement  # => expected 'The refinement was used' but
got 'The refinement was not used'
=end
C4e88907313843cf07f6d85ba8162120?d=identicon&s=25 shugo (Shugo Maeda) (Guest)
on 2013-11-29 15:09
(Received via mailing list)
Issue #8872 has been updated by shugo (Shugo Maeda).


Eregon (Benoit Daloze) wrote:
> >   a = *[1..10]
>
> You probably meant
>
>     a = [*1..10]

Ah, I meant:

  a = *1..10

Thanks anyway.
----------------------------------------
Backport #8872: Case statements do not honor a refinement of the '==='
method
https://bugs.ruby-lang.org/issues/8872#change-43267

Author: jconley88 (Jon Conley)
Status: Assigned
Priority: Normal
Assignee: matz (Yukihiro Matsumoto)
Category:
Target version:


=begin
Below, I've redefined the ((|===|)) method of symbol to always return
true.  In ((|RefineTest#uses_refinement|)), I call ((|===|)) directly
and the refined method is called.  In
((|RefineTest#does_not_use_refinement|)), the ((|===|)) method is called
indirectly through a case statement.  If the refined ((|===|)) method
was called, the result should be ((*'The refinement was used'*)), but
this code currently returns ((*'The refinement was not used'*)).

 module RefineSymbol
   refine Symbol do
     def ===(other)
       true
     end
   end
 end

 using RefineSymbol

 class RefineTest
   def uses_refinement
     :a === :b
   end

   def does_not_use_refinement
     case :a
     when :b
       'The refinement was used'
     else
       'The refinement was not used'
     end
   end
 end

 rt = RefineTest.new
 rt.uses_refinement   # => true
 rt.does_not_use_refinement  # => expected 'The refinement was used' but
got 'The refinement was not used'
=end
C4e88907313843cf07f6d85ba8162120?d=identicon&s=25 shugo (Shugo Maeda) (Guest)
on 2013-11-30 02:48
(Received via mailing list)
Issue #8872 has been updated by shugo (Shugo Maeda).


Could anyone tell me use cases of this feature?

I think refinements are for object-oriented ways using dynamic dispatch,
but case expressions are not for such object-oriented ways.
----------------------------------------
Backport #8872: Case statements do not honor a refinement of the '==='
method
https://bugs.ruby-lang.org/issues/8872#change-43272

Author: jconley88 (Jon Conley)
Status: Assigned
Priority: Normal
Assignee: matz (Yukihiro Matsumoto)
Category:
Target version:


=begin
Below, I've redefined the ((|===|)) method of symbol to always return
true.  In ((|RefineTest#uses_refinement|)), I call ((|===|)) directly
and the refined method is called.  In
((|RefineTest#does_not_use_refinement|)), the ((|===|)) method is called
indirectly through a case statement.  If the refined ((|===|)) method
was called, the result should be ((*'The refinement was used'*)), but
this code currently returns ((*'The refinement was not used'*)).

 module RefineSymbol
   refine Symbol do
     def ===(other)
       true
     end
   end
 end

 using RefineSymbol

 class RefineTest
   def uses_refinement
     :a === :b
   end

   def does_not_use_refinement
     case :a
     when :b
       'The refinement was used'
     else
       'The refinement was not used'
     end
   end
 end

 rt = RefineTest.new
 rt.uses_refinement   # => true
 rt.does_not_use_refinement  # => expected 'The refinement was used' but
got 'The refinement was not used'
=end
E8a419959139f3f505b49bb95f7e7afe?d=identicon&s=25 Joshua Ballanco (jballanc)
on 2013-11-30 11:07
(Received via mailing list)
Issue #8872 has been updated by jballanc (Joshua Ballanco).


To play devil's advocate, I think the opposing question to be asked is
"how would you alter the behavior of case evaluation using refinements"?

It may be, as shugo states, that refinements are not meant to be used
for altering the behavior of expressions. In this case, the answer to
the question I posed is, simply, "you don't."

That said, I think it is fairly well understood in the Ruby community
that "===" is related to case. I've even heard the operator described as
"case equality". Playing devil's advocate again, what is the use case
for refining "===" if it _doesn't_ affect the evaluation of a
case...when clause?
----------------------------------------
Backport #8872: Case statements do not honor a refinement of the '==='
method
https://bugs.ruby-lang.org/issues/8872#change-43283

Author: jconley88 (Jon Conley)
Status: Assigned
Priority: Normal
Assignee: matz (Yukihiro Matsumoto)
Category:
Target version:


=begin
Below, I've redefined the ((|===|)) method of symbol to always return
true.  In ((|RefineTest#uses_refinement|)), I call ((|===|)) directly
and the refined method is called.  In
((|RefineTest#does_not_use_refinement|)), the ((|===|)) method is called
indirectly through a case statement.  If the refined ((|===|)) method
was called, the result should be ((*'The refinement was used'*)), but
this code currently returns ((*'The refinement was not used'*)).

 module RefineSymbol
   refine Symbol do
     def ===(other)
       true
     end
   end
 end

 using RefineSymbol

 class RefineTest
   def uses_refinement
     :a === :b
   end

   def does_not_use_refinement
     case :a
     when :b
       'The refinement was used'
     else
       'The refinement was not used'
     end
   end
 end

 rt = RefineTest.new
 rt.uses_refinement   # => true
 rt.does_not_use_refinement  # => expected 'The refinement was used' but
got 'The refinement was not used'
=end
C4e88907313843cf07f6d85ba8162120?d=identicon&s=25 shugo (Shugo Maeda) (Guest)
on 2013-12-04 03:55
(Received via mailing list)
Issue #8872 has been updated by shugo (Shugo Maeda).


jballanc (Joshua Ballanco) wrote:
> To play devil's advocate, I think the opposing question to be asked is "how
would you alter the behavior of case evaluation using refinements"?
>
> It may be, as shugo states, that refinements are not meant to be used for
altering the behavior of expressions. In this case, the answer to the question I
posed is, simply, "you don't."
>
> That said, I think it is fairly well understood in the Ruby community that "==="
is related to case. I've even heard the operator described as "case equality".
Playing devil's advocate again, what is the use case for refining "===" if it
_doesn't_ affect the evaluation of a case...when clause?

I don't come up with any use case for refining "===" regardless of
whether it affects the evaluation of a case expression or not.
I'm neutral about this issue, and really want to know use cases.
----------------------------------------
Backport #8872: Case statements do not honor a refinement of the '==='
method
https://bugs.ruby-lang.org/issues/8872#change-43402

Author: jconley88 (Jon Conley)
Status: Assigned
Priority: Normal
Assignee: matz (Yukihiro Matsumoto)
Category:
Target version:


=begin
Below, I've redefined the ((|===|)) method of symbol to always return
true.  In ((|RefineTest#uses_refinement|)), I call ((|===|)) directly
and the refined method is called.  In
((|RefineTest#does_not_use_refinement|)), the ((|===|)) method is called
indirectly through a case statement.  If the refined ((|===|)) method
was called, the result should be ((*'The refinement was used'*)), but
this code currently returns ((*'The refinement was not used'*)).

 module RefineSymbol
   refine Symbol do
     def ===(other)
       true
     end
   end
 end

 using RefineSymbol

 class RefineTest
   def uses_refinement
     :a === :b
   end

   def does_not_use_refinement
     case :a
     when :b
       'The refinement was used'
     else
       'The refinement was not used'
     end
   end
 end

 rt = RefineTest.new
 rt.uses_refinement   # => true
 rt.does_not_use_refinement  # => expected 'The refinement was used' but
got 'The refinement was not used'
=end
5cf8f058a4c094bb708174fb43e7a387?d=identicon&s=25 nagachika (Tomoyuki Chikanaga) (Guest)
on 2013-12-18 02:40
(Received via mailing list)
Issue #8872 has been updated by nagachika (Tomoyuki Chikanaga).


hi,

Is there any progress? Does anyone has usecase of refinements & case
statement?
----------------------------------------
Backport #8872: Case statements do not honor a refinement of the '==='
method
https://bugs.ruby-lang.org/issues/8872#change-43730

Author: jconley88 (Jon Conley)
Status: Assigned
Priority: Normal
Assignee: matz (Yukihiro Matsumoto)
Category:
Target version:


=begin
Below, I've redefined the ((|===|)) method of symbol to always return
true.  In ((|RefineTest#uses_refinement|)), I call ((|===|)) directly
and the refined method is called.  In
((|RefineTest#does_not_use_refinement|)), the ((|===|)) method is called
indirectly through a case statement.  If the refined ((|===|)) method
was called, the result should be ((*'The refinement was used'*)), but
this code currently returns ((*'The refinement was not used'*)).

 module RefineSymbol
   refine Symbol do
     def ===(other)
       true
     end
   end
 end

 using RefineSymbol

 class RefineTest
   def uses_refinement
     :a === :b
   end

   def does_not_use_refinement
     case :a
     when :b
       'The refinement was used'
     else
       'The refinement was not used'
     end
   end
 end

 rt = RefineTest.new
 rt.uses_refinement   # => true
 rt.does_not_use_refinement  # => expected 'The refinement was used' but
got 'The refinement was not used'
=end
0ec4920185b657a03edf01fff96b4e9b?d=identicon&s=25 matz (Yukihiro Matsumoto) (Guest)
on 2013-12-18 07:11
(Received via mailing list)
Issue #8872 has been updated by matz (Yukihiro Matsumoto).


After consideration, I think for and case statement should honor
refinement since they are fundamentally syntax sugar using each/===
methods.

Matz.

----------------------------------------
Backport #8872: Case statements do not honor a refinement of the '==='
method
https://bugs.ruby-lang.org/issues/8872#change-43740

Author: jconley88 (Jon Conley)
Status: Assigned
Priority: Normal
Assignee: matz (Yukihiro Matsumoto)
Category:
Target version:


=begin
Below, I've redefined the ((|===|)) method of symbol to always return
true.  In ((|RefineTest#uses_refinement|)), I call ((|===|)) directly
and the refined method is called.  In
((|RefineTest#does_not_use_refinement|)), the ((|===|)) method is called
indirectly through a case statement.  If the refined ((|===|)) method
was called, the result should be ((*'The refinement was used'*)), but
this code currently returns ((*'The refinement was not used'*)).

 module RefineSymbol
   refine Symbol do
     def ===(other)
       true
     end
   end
 end

 using RefineSymbol

 class RefineTest
   def uses_refinement
     :a === :b
   end

   def does_not_use_refinement
     case :a
     when :b
       'The refinement was used'
     else
       'The refinement was not used'
     end
   end
 end

 rt = RefineTest.new
 rt.uses_refinement   # => true
 rt.does_not_use_refinement  # => expected 'The refinement was used' but
got 'The refinement was not used'
=end
5cf8f058a4c094bb708174fb43e7a387?d=identicon&s=25 nagachika (Tomoyuki Chikanaga) (Guest)
on 2013-12-21 16:04
(Received via mailing list)
Issue #8872 has been updated by nagachika (Tomoyuki Chikanaga).


How about 2.0.0? Can I change the behavior at 2.0.0 to same with 2.1?
If so I'll backport r43913 to fix SEGV.
----------------------------------------
Backport #8872: Case statements do not honor a refinement of the '==='
method
https://bugs.ruby-lang.org/issues/8872#change-43808

Author: jconley88 (Jon Conley)
Status: Assigned
Priority: Normal
Assignee: matz (Yukihiro Matsumoto)
Category:
Target version:


=begin
Below, I've redefined the ((|===|)) method of symbol to always return
true.  In ((|RefineTest#uses_refinement|)), I call ((|===|)) directly
and the refined method is called.  In
((|RefineTest#does_not_use_refinement|)), the ((|===|)) method is called
indirectly through a case statement.  If the refined ((|===|)) method
was called, the result should be ((*'The refinement was used'*)), but
this code currently returns ((*'The refinement was not used'*)).

 module RefineSymbol
   refine Symbol do
     def ===(other)
       true
     end
   end
 end

 using RefineSymbol

 class RefineTest
   def uses_refinement
     :a === :b
   end

   def does_not_use_refinement
     case :a
     when :b
       'The refinement was used'
     else
       'The refinement was not used'
     end
   end
 end

 rt = RefineTest.new
 rt.uses_refinement   # => true
 rt.does_not_use_refinement  # => expected 'The refinement was used' but
got 'The refinement was not used'
=end
0ec4920185b657a03edf01fff96b4e9b?d=identicon&s=25 unknown (Guest)
on 2014-01-15 17:30
(Received via mailing list)
Issue #8872 has been updated by Yukihiro Matsumoto.

ruby -v set to 2.0.0

I don't think changing the behavior in the middle of a release is a good
idea.
So I don't encourage backporting.  Thanks.

Matz.


----------------------------------------
Backport #8872: Case statements do not honor a refinement of the '==='
method
https://bugs.ruby-lang.org/issues/8872#change-44355

* Author: Jon Conley
* Status: Assigned
* Priority: Normal
* Assignee: Yukihiro Matsumoto
* Category:
* Target version:
* ruby -v: 2.0.0
----------------------------------------
=begin
Below, I've redefined the ((|===|)) method of symbol to always return
true.  In ((|RefineTest#uses_refinement|)), I call ((|===|)) directly
and the refined method is called.  In
((|RefineTest#does_not_use_refinement|)), the ((|===|)) method is called
indirectly through a case statement.  If the refined ((|===|)) method
was called, the result should be ((*'The refinement was used'*)), but
this code currently returns ((*'The refinement was not used'*)).

 module RefineSymbol
   refine Symbol do
     def ===(other)
       true
     end
   end
 end

 using RefineSymbol

 class RefineTest
   def uses_refinement
     :a === :b
   end

   def does_not_use_refinement
     case :a
     when :b
       'The refinement was used'
     else
       'The refinement was not used'
     end
   end
 end

 rt = RefineTest.new
 rt.uses_refinement   # => true
 rt.does_not_use_refinement  # => expected 'The refinement was used' but
got 'The refinement was not used'
=end
5cf8f058a4c094bb708174fb43e7a387?d=identicon&s=25 unknown (Guest)
on 2014-01-23 13:05
(Received via mailing list)
Issue #8872 has been updated by Tomoyuki Chikanaga.

Assignee changed from Yukihiro Matsumoto to Tomoyuki Chikanaga

Hi,

I've told matz that this change introduced by r42923 was already
released at 2.0.0p353 and matz decided to not to revert the changeset.
(see https://twitter.com/yukihiro_matz/status/423500823788662784 )

I will backport r43913 to fix SEGV introduced at r42923.

Thanks.

----------------------------------------
Backport #8872: Case statements do not honor a refinement of the '==='
method
https://bugs.ruby-lang.org/issues/8872#change-44542

* Author: Jon Conley
* Status: Assigned
* Priority: Normal
* Assignee: Tomoyuki Chikanaga
* Category:
* Target version:
* ruby -v: -
----------------------------------------
=begin
Below, I've redefined the ((|===|)) method of symbol to always return
true.  In ((|RefineTest#uses_refinement|)), I call ((|===|)) directly
and the refined method is called.  In
((|RefineTest#does_not_use_refinement|)), the ((|===|)) method is called
indirectly through a case statement.  If the refined ((|===|)) method
was called, the result should be ((*'The refinement was used'*)), but
this code currently returns ((*'The refinement was not used'*)).

 module RefineSymbol
   refine Symbol do
     def ===(other)
       true
     end
   end
 end

 using RefineSymbol

 class RefineTest
   def uses_refinement
     :a === :b
   end

   def does_not_use_refinement
     case :a
     when :b
       'The refinement was used'
     else
       'The refinement was not used'
     end
   end
 end

 rt = RefineTest.new
 rt.uses_refinement   # => true
 rt.does_not_use_refinement  # => expected 'The refinement was used' but
got 'The refinement was not used'
=end
5cf8f058a4c094bb708174fb43e7a387?d=identicon&s=25 unknown (Guest)
on 2014-01-23 13:41
(Received via mailing list)
Issue #8872 has been updated by Tomoyuki Chikanaga.

Status changed from Assigned to Closed

Applied in changeset r44695.

----------
merge revision(s) 43913: [Backport #8872] [Backport #9175]

  * vm_insnhelper.c (check_match): Fix SEGV with VM_CHECKMATCH_TYPE_CASE
    and class of `pattern` has `method_missing`
    [Bug #8882] [ruby-core:58606]

----------------------------------------
Backport #8872: Case statements do not honor a refinement of the '==='
method
https://bugs.ruby-lang.org/issues/8872#change-44546

* Author: Jon Conley
* Status: Closed
* Priority: Normal
* Assignee: Tomoyuki Chikanaga
* Category:
* Target version:
* ruby -v: -
----------------------------------------
=begin
Below, I've redefined the ((|===|)) method of symbol to always return
true.  In ((|RefineTest#uses_refinement|)), I call ((|===|)) directly
and the refined method is called.  In
((|RefineTest#does_not_use_refinement|)), the ((|===|)) method is called
indirectly through a case statement.  If the refined ((|===|)) method
was called, the result should be ((*'The refinement was used'*)), but
this code currently returns ((*'The refinement was not used'*)).

 module RefineSymbol
   refine Symbol do
     def ===(other)
       true
     end
   end
 end

 using RefineSymbol

 class RefineTest
   def uses_refinement
     :a === :b
   end

   def does_not_use_refinement
     case :a
     when :b
       'The refinement was used'
     else
       'The refinement was not used'
     end
   end
 end

 rt = RefineTest.new
 rt.uses_refinement   # => true
 rt.does_not_use_refinement  # => expected 'The refinement was used' but
got 'The refinement was not used'
=end
This topic is locked and can not be replied to.