From e8aa6a9ec20dc06650f6a6a71f2d7b88a74455fd Mon Sep 17 00:00:00 2001 From: SamW Date: Mon, 15 Jun 2026 20:10:51 -0700 Subject: [PATCH 01/10] Initial commit---non-coerce, non-odd ones --- core/integer.rbs | 73 ++----- core/numeric.rbs | 3 + test/stdlib/Integer_test.rb | 393 +++++++++++++++++++++++++++++++++++- test/stdlib/test_helper.rb | 9 + 4 files changed, 422 insertions(+), 56 deletions(-) diff --git a/core/integer.rbs b/core/integer.rbs index fd2ef0ae49..039fafb145 100644 --- a/core/integer.rbs +++ b/core/integer.rbs @@ -93,6 +93,8 @@ # given value. # class Integer < Numeric + # TODO: `undef self.new` + # # Returns `1`. # - def denominator: () -> Integer + def denominator: () -> 1 # # - def magnitude: () -> Integer + alias magnitude abs # # Returns `self` modulo `other` as a real numeric (Integer, Float, or Rational). @@ -1009,7 +1010,7 @@ class Integer < Numeric # # Related: Integer#pred (predecessor value). # - def next: () -> Integer + alias next succ # # Returns `self`. # - def numerator: () -> Integer + def numerator: () -> self # # Returns `self`; intended for compatibility to character literals in Ruby 1.9. # - def ord: () -> Integer + def ord: () -> self def polar: () -> [ Integer, Integer | Float ] @@ -1180,8 +1181,7 @@ class Integer < Numeric # # Related: Integer#truncate. # - def round: (?half: :up | :down | :even) -> Integer - | (int digits, ?half: :up | :down | :even) -> (Integer | Float) + def round: (?int digits, ?half: Numeric::round_mode) -> Integer # # Returns `self` (which is already an Integer). # - def to_i: () -> Integer + def to_i: () -> self # # Returns a string containing the place-value representation of `self` in radix @@ -965,7 +965,7 @@ class Integer < Numeric # 3.lcm(-7) #=> 21 # ((1<<31)-1).lcm((1<<61)-1) #=> 4951760154835678088235319297 # - def lcm: (Integer) -> Integer + def lcm: (Integer other_int) -> Integer # # Returns `true` if `self` is numerically equal to `other`; `false` otherwise. diff --git a/test/stdlib/Integer_test.rb b/test/stdlib/Integer_test.rb index 557a0930cb..10d5d4e280 100644 --- a/test/stdlib/Integer_test.rb +++ b/test/stdlib/Integer_test.rb @@ -39,8 +39,8 @@ def test_op_mod(method: :%) 38, method, 12.0 # Notably not `Complex` as complex doesn't define `%` - assert_send_type '[O < RBS::Ops::_Subtract[S, R], S, R] (Numeric::_Coerce[38, O, S]) -> R', - 38, method, Coercable.new('fmt: %s', &:to_s) + assert_send_type '(Coercable) -> Coercable::OpReturn', + 38, method, Coercable.for_op(:%) end def test_op_and @@ -57,8 +57,8 @@ def test_op_mul assert_send_type '(Complex) -> Complex', 38, :*, 12i - assert_send_type '[O < RBS::Ops::_Times[S, R], S, R] (Numeric::_Coerce[38, O, S]) -> R', - 38, :*, Coercable.new(%w[a b], &:to_s) + assert_send_type '(Coercable) -> Coercable::OpReturn', + 38, :*, Coercable.for_op(:*) end def test_op_pow @@ -71,8 +71,8 @@ def test_op_pow assert_send_type '(Complex) -> Complex', 38, :**, 12i - assert_send_type '[O < RBS::Ops::_Power[S, R], S, R] (Numeric::_Coerce[38, O, S]) -> R', - 38, :**, Coercable.new(10i, &:i) + assert_send_type '(Coercable) -> Coercable::OpReturn', + 38, :**, Coercable.for_op(:**) end def test_op_add @@ -85,8 +85,8 @@ def test_op_add assert_send_type '(Complex) -> Complex', 38, :+, 12i - assert_send_type '[O < RBS::Ops::_Add[S, R], S, R] (Numeric::_Coerce[38, O, S]) -> R', - 38, :+, Coercable.new('foo', &:to_s) + assert_send_type '(Coercable) -> Coercable::OpReturn', + 38, :+, Coercable.for_op(:+) end def test_op_sub @@ -99,8 +99,8 @@ def test_op_sub assert_send_type '(Complex) -> Complex', 38, :-, 12i - assert_send_type '[O < RBS::Ops::_Subtract[S, R], S, R] (Numeric::_Coerce[38, O, S]) -> R', - 38, :-, Coercable.new([3], &:digits) + assert_send_type '(Coercable) -> Coercable::OpReturn', + 38, :-, Coercable.for_op(:-) end def test_op_uneg @@ -118,8 +118,8 @@ def test_op_div assert_send_type '(Complex) -> Complex', 38, :/, 12i - assert_send_type '[O < RBS::Ops::_Times[S, R], S, R] (Numeric::_Coerce[38, O, S]) -> R', - 38, :/, Coercable.new(10i, &:i) + assert_send_type '(Coercable) -> Coercable::OpReturn', + 38, :/, Coercable.for_op(:/) end def test_op_lt @@ -131,8 +131,8 @@ def test_op_lt 38, :<, 12.0 # Notably not `Complex` as complex doesn't define `<` - assert_send_type '[O < RBS::Ops::_LessThan[S, R], S, R] (Numeric::_Coerce[38, O, S]) -> R', - 38, :<, Coercable.new(Set[8, 4]){ |n| n.digits.to_set } + assert_send_type '(Coercable) -> Coercable::OpReturn', + 38, :<, Coercable.for_op(:<) end def test_op_lsh @@ -148,12 +148,20 @@ def test_op_leq 38, :<=, 12.0 # Notably not `Complex` as complex doesn't define `<=` - assert_send_type '[O < RBS::Ops::_LessThanOrEqual[S, R], S, R] (Numeric::_Coerce[38, O, S]) -> R', - 38, :<=, Coercable.new(Set[8, 4]){ |n| n.digits.to_set } + assert_send_type '(Coercable) -> Coercable::OpReturn', + 38, :<=, Coercable.for_op(:<=) end def test_op_cmp - # omit 'todo' + assert_send_type '(Integer) -> (-1 | 0 | 1)', + 38, :<=>, 12 + assert_send_type '(Rational) -> (-1 | 0 | 1)', + 38, :<=>, 12r + + with_untyped.and 12, 12r, 12.0, 12i, Coercable.new(Set[8, 4]){ |n| n.digits.to_set } do |other| + assert_send_type '(untyped) -> Integer?', + 38, :<=>, other + end end def test_op_eq(method: :==) @@ -177,8 +185,8 @@ def test_op_gt 38, :>, 12.0 # Notably not `Complex` as complex doesn't define `>` - assert_send_type '[O < RBS::Ops::_GreaterThan[S, R], S, R] (Numeric::_Coerce[38, O, S]) -> R', - 38, :>, Coercable.new(Set[8, 4]){ |n| n.digits.to_set } + assert_send_type '(Coercable) -> Coercable::OpReturn', + 38, :>, Coercable.for_op(:>) end def test_op_geq @@ -190,8 +198,8 @@ def test_op_geq 38, :>=, 12.0 # Notably not `Complex` as complex doesn't define `>` - assert_send_type '[O < RBS::Ops::_GreaterThanOrEqual[S, R], S, R] (Numeric::_Coerce[38, O, S]) -> R', - 38, :>=, Coercable.new(Set[8, 4]){ |n| n.digits.to_set } + assert_send_type '(Coercable) -> Coercable::OpReturn', + 38, :>=, Coercable.for_op(:>=) end def test_op_rsh diff --git a/test/stdlib/test_helper.rb b/test/stdlib/test_helper.rb index 2484042875..228f5e82ae 100644 --- a/test/stdlib/test_helper.rb +++ b/test/stdlib/test_helper.rb @@ -81,6 +81,24 @@ def with_timeout(seconds: 1, nanoseconds: 0) end class Coercable < RBS::UnitTest::Convertibles::BlankSlate + class OpReturn < ::RBS::UnitTest::Convertibles::BlankSlate + end + + class CoerceOther < ::RBS::UnitTest::Convertibles::BlankSlate + end + + class CoerceSelf < ::RBS::UnitTest::Convertibles::BlankSlate + def initialize(method = nil) + if method + ::Kernel.instance_method(:define_singleton_method).bind_call(self, method) { |other| OpReturn.new } + end + end + end + + def self.for_op(method) + new(CoerceSelf.new(method)){ |x| CoerceOther.new } + end + def initialize(self_ret, &converter) @self_ret = self_ret @converter = converter || ->(x) { x } From e3b842d46878a4783486ab42057ed12733e23d49 Mon Sep 17 00:00:00 2001 From: SamW Date: Tue, 16 Jun 2026 10:53:06 -0700 Subject: [PATCH 07/10] bitwise and shifts --- core/integer.rbs | 13 ++++++++----- test/stdlib/Integer_test.rb | 28 +++++++++++++++++++++++----- 2 files changed, 31 insertions(+), 10 deletions(-) diff --git a/core/integer.rbs b/core/integer.rbs index c6a6694309..6f61826ef3 100644 --- a/core/integer.rbs +++ b/core/integer.rbs @@ -190,7 +190,8 @@ class Integer < Numeric # # Related: Integer#| (bitwise OR), Integer#^ (bitwise EXCLUSIVE OR). # - def &: (Integer) -> Integer + def &: (Integer other) -> Integer + | [O < RBS::Ops::_And[S, R], S, R] (Numeric::_Coerce[self, O, S] other) -> R #