Code Review: HashEql

tfpt review “/shelveset:HashEql;REDMOND\tomat”

Fixes implementation of Kernel#eql?, Kernel#==, Kernel#hash, Array#eql?
and Array#hash and improves CLR interop.
Improves performance of Array#- from quadratic algorithm to linear.

CLR interop:
“hash” is mapped to “GetHashCode” and following below rules:

  1.  A Ruby call to Kernel#hash on a CLR object that overrides 
    

GetHashCode will call that override.

  1.  A Ruby call to Kernel#hash on a Ruby subclass of a CLR type will 
    

call the GetHashCode of the CLR type if the Ruby subclass doesn’t
implement “hash” method.

  1.  A Ruby data structure (like Array) that calculates its hash code 
    

based on hash codes of its items dynamically calls “hash” on those
items.

  1.  Any call from C# to GetHashCode on an instance of any Ruby class 
    

will dynamically dispatch to either “hash”, “GetHashCode” or
“get_hash_code” whichever is found first in standard method resolution
order. If multiple of these methods are defined in the same class “hash”
has highest priority and “get_hash_code” the lowest. This implies that a
Ruby method definition with name “hash”, “GetHashCode” or
“get_hash_code” in any Ruby class overrides GetHashCode of the parent
CLR class.

Similarly is “eql?” mapped to “Equals”.

Kernel#== is an alias for “eql?” and hence has the same behavior when
invoked (calls CLR Equals virtual method).
However, 4) doesn’t hold for “==”, i.e. method == defined in a Ruby
class does NOT override CLR Equals method.

Adds /noadaptive option to unit test driver.
Fixes removal of CLR methods.

Simplifies implementation of IsRemovable on RubyMemberInfo using
IsRubyMethod. IsRubyMethod returns true on all members that were defined
by Ruby means, be it explicit method definition (def keyword), alias,
alias_method, define_method, public/private/protected, overload, of,
etc. CLR members used for definition of a new method (via define_method,
alias etc.) are called “detached” (as opposed to “attached” CLR members,
which represent the original CLR members). They behave like any Ruby
method with respect to method removal, virtual dispatch, IDO interop
dispatch etc. So their IsRubyMethod implementation returns true.

Tomas