22
33# @api private
44class Literal ::Types ::InterfaceType
5- # TODO: We can generate this and make it much more extensive.
6- METHOD_TYPE_MAPPINGS = {
7- :call => Set [ Proc , Method ] ,
8- :to_proc => Set [ Proc , Method , Symbol ] ,
9- :to_s => Set [ String ] ,
10- } . freeze
11-
125 include Literal ::Type
136
7+ # List of `===` method owners where the comparison will only match for objects with the same class
8+ OwnClassTypeMethodOwners = Set [ String , Integer , Kernel , Float , NilClass , TrueClass , FalseClass ] . freeze
9+
1410 def initialize ( *methods )
1511 raise Literal ::ArgumentError . new ( "_Interface type must have at least one method." ) if methods . size < 1
16- @methods = methods
12+ @methods = methods . to_set . freeze
1713 freeze
1814 end
1915
@@ -24,21 +20,30 @@ def inspect
2420 end
2521
2622 def ===( value )
27- @methods . all? { |m | value . respond_to? ( m ) }
23+ @methods . each do |method |
24+ return false unless value . respond_to? ( method )
25+ end
26+
27+ true
2828 end
2929
3030 def >=( other )
3131 case other
3232 when Literal ::Types ::InterfaceType
33- @methods . all? { | m | other . methods . include? ( m ) }
33+ @methods . subset? ( other . methods )
3434 when Module
35- @methods . map { |m | METHOD_TYPE_MAPPINGS [ m ] } . all? { |types | types &.include? ( other ) }
35+ public_methods = other . public_instance_methods . to_set
36+ @methods . subset? ( public_methods )
3637 when Literal ::Types ::IntersectionType
3738 other . types . any? { |type | Literal . subtype? ( type , self ) }
3839 when Literal ::Types ::ConstraintType
3940 other . object_constraints . any? { |type | Literal . subtype? ( type , self ) }
4041 else
41- false
42+ if OwnClassTypeMethodOwners . include? ( other . method ( :=== ) . owner )
43+ self === other
44+ else
45+ false
46+ end
4247 end
4348 end
4449
0 commit comments