コンテンツにスキップ

Rational / Complex / Range / Set — ConstantFolding カバレッジ監査

2026-05-22生成。Ruby 4.0のRational(3,4).methods - Object.new.methods等から型ごとに 固有メソッドを抽出し、現在の精度カバレッジを分類する。
実際のfold動作はRigor::Inference::MethodDispatcher.dispatchを使ったライブ計測による。


記号意味
ConstantFolding(カタログ経由invoke_unary/invoke_binary・特殊リフト)またはRbsDispatchの定数特化で実装済み
🔷別ティア処理済み(RBSで十分精度が出る、またはpurity:dispatchでfold不可)
🔲未実装だがConstant[T]精度向上の価値あり
🚫非対象(破壊的変更・例外を投げる・Enumerator返却・ランタイム依存)

列挙元: Rational(3,4).methods - Object.new.methods → Ruby 4.0.5
実装ファイル: lib/rigor/inference/method_dispatcher/constant_folding.rb
カタログ: data/builtins/ruby_core/rational.yml — C実装のメソッドのみ記録。

メソッド状態計測値(Rational(3,4))備考
numerator3カタログ:leaf → invoke_unary
denominator4同上
-@(-3/4)同上
abs(3/4)同上
magnitude(3/4)absの別名
floor0同上
ceil1同上
truncate0同上
round1同上
to_i0同上
to_f0.75同上
to_r(3/4)同上
rationalize(3/4)同上
hash1516034510...同上
to_s"3/4"同上
inspect"(3/4)"同上
positive?true同上
negative?false同上
real?trueRbsDispatch定数特化(Numeric RBSに() -> true
imag0RbsDispatch定数特化(() -> 0
imaginary0imagの別名、同上
+(5/4)カタログ:leaf_when_numeric、Rational引数でfold
-(1/4)同上
*(3/8)同上
/(3/2)同上
**0.866…同上(結果がFloatに変わる場合あり)
<false同上(比較演算子)
<=false同上
>true同上
>=true同上
<=>1同上
quo(3/2)カタログ:leaf_when_numeric
divmod[1, (1/4)]try_fold_divmodTuple[Constant[q], Constant[r]]
==🔷purity: dispatch。RBS boolで十分
infinite?🔷`Integernil`
finite?🔷`falsetrue`
+@🔷selfを返すunary + — RBSでRationalに解決。現行で十分
between?🔷Comparableモジュール経由。RBSでbool
clamp🚫引数の組み合わせが多く戻り型が複雑
coerce🔷[Numeric, Numeric]戻りが[Numeric, Numeric] — RBSで十分
zero?`falsetrue`
integer?`falsetrue`
nonzero?`Rationalnil`
realRationalRATIONAL_UNARYに追加済み。Constant[Rational]
rect / rectangular[Rational, Numeric]NUMERIC_ARRAY_UNARY_METHODSに追加済み(Rationalチェック含む)。Tupleリフト。
polar`[Rational, FloatInteger]`
abs2RationalRATIONAL_UNARYに追加済み。Constant[Rational]
arg / angle / phase`0Float`
conj / conjugateRationalRATIONAL_UNARYに追加済み。Constant[Rational]
divIntegerRATIONAL_BINARYに追加済み。Constant[Integer]
modulo / %RationalRATIONAL_BINARYに追加済み。Constant[Rational]
remainderRationalRATIONAL_BINARYに追加済み。
fdivFloatRATIONAL_BINARYに追加済み。Constant[Float]
to_c🔲ComplexComplex(self, 0)Constant[Complex]。ComplexがSCALAR_CLASSESにあれば可。低優先度
i🔲ComplexComplex(0, self)を返す。同上。低優先度
step🚫反復子
singleton_method_added🚫内部フック
to_intto_iの別名、同等のfold

🔴 高優先度(なし — 主要な数値演算はすべて実装済み)

🟡 中優先度(全項目実装済み)

  • zero?, integer?RATIONAL_UNARY Setに追加済み
  • real, abs2, conj/conjugate → 同上
  • rect/rectangularNUMERIC_ARRAY_UNARY_METHODS拡張済み
  • divRATIONAL_BINARY Setに追加済み

🟢 低優先度(全項目実装済み)

  • nonzero?, polar, arg/angle/phase → 上記Set追加で対応済み
  • modulo, %, remainder, fdiv → 上記Set追加で対応済み
  • to_c, i → ComplexがConstantキャリアに入っているため原理的に可

列挙元: Complex(3,4).methods - Object.new.methods → Ruby 4.0.5
実装ファイル: constant_folding.rb (catalog + COMPLEX_ARRAY_UNARY_METHODS)
カタログ: data/builtins/ruby_core/complex.yml

メソッド状態計測値(Complex(3,4))備考
real3カタログ:leaf → invoke_unary
imaginary / imag4同上
-@(-3-4i)同上
abs / magnitude5.0同上
abs225同上
arg / angle / phase0.927…同上
rect / rectangular[3, 4]COMPLEX_ARRAY_UNARY_METHODS → Tupleリフト(前セッションで実装)
polar[5.0, 0.927…]同上
conjugate / conj(3-4i)カタログ:leaf
real?falseカタログ:leaf
numerator(3+4i)同上
denominator1同上
hash821720373…同上
finite?true同上
infinite?nil同上(ComplexがNaN/Infinite要素を持つ場合nilでない)
to_c(3+4i)同上(selfを返す)
+(4+6i)カタログ:leaf_when_numeric
-(2+2i)同上
*(-5+10i)同上
/((11/5)-(2/5)*i)同上
**(-0.41…-0.66…i)同上
quo((11/5)-(2/5)*i)カタログ:leaf
fdiv(2.2-0.4i)同上
==falseカタログ:leaf
eql?false同上
integer?🔷`falsetrue`
+@🔷selfを返すunary +。RBS Complexで十分
coerce🔷[Complex, Complex]戻り型複雑。RBSで十分
<=>🔷purity:dispatch。Complexには全順序なし(nilを返す)。RBSで十分
to_s🔷Stringpurity: dispatch(複素数の文字列化が部品に依存)。fold不可
inspect🔷String同上
rationalize🚫虚部が0でない場合RangeErrorをraise。推論時安全でない
to_i🚫同上
to_f🚫同上
to_r🚫同上
to_int🚫同上
nonzero?`Complexnil`
zero?`falsetrue`
singleton_method_added🚫内部フック

🔴 高優先度(なし — 前セッションで主要ギャップを解消済み)

🟡 中優先度(全項目実装済み)

  • zero?, nonzero?COMPLEX_UNARY Setに追加済み(unary_ops_forComplexケース追加)

🟢 低優先度(上記のみ)


列挙元: (1..5).methods - Object.new.methods → Ruby 4.0.5
実装ファイル: constant_folding.rbRANGE_FOLD_METHODS, try_fold_range_constant_unary
カタログ: data/builtins/ruby_core/range.yml

メソッド状態計測値((1..5))備考
begin1カタログ:leaf → invoke_unary
end5同上
exclude_end?false同上
hash-800979437…同上
to_s"1..5"同上
first(0引数)1try_fold_range_constant_unary
last(0引数)5同上
min(0引数)1同上
max(0引数)5同上
size5同上(RANGE_FOLD_METHODS:sizeあり)
count(0引数)5同上(:countあり)
to_a[1, 2, 3, 4, 5]range_to_a_tupleTuple[Constant…]
to_setSet[1, 2, 3, 4, 5]meta_newset_new_lift経由 → Constant[Set]
include?trueカタログ:leaf + binary fold
member?trueinclude?の別名(カタログに同エントリー)
cover?trueカタログ:leaf + binary fold
===trueカタログ:leaf + binary fold
inspect🔷Stringpurity: dispatch(begin/endのinspectを呼ぶ)。fold不可
==🔷purity: dispatch。RBS boolで十分
eql?🔷purity: dispatch。同上
overlap?🔷`falsetrue`
bsearch🚫purity: dispatch、ブロック依存
step🚫反復子
each🚫反復子
reverse_each🚫反復子
%🚫Enumerator / ブロック反復子
all? / any? / none? / one?🔷BlockFolding経由
map / select / reject / flat_map🔷BlockFolding / RBS
sum🔲Integer等差数列はn*(a+b)/2でConstantに畳める。中優先度
entriesArray[Dynamic[top]]RANGE_FOLD_METHODS:entries追加 + range_constant_unarywhen :entries追加済み。
minmax`[Dynamic[top]nil, Dynamic[top]
first(n)🔲Array[Dynamic[top]]整数引数あり形式。Tupleリフト可。中優先度
last(n)🔲Array[Dynamic[top]]同上
to_h🚫Range要素が[k, v]の2要素Arrayでない限りraise

🔴 高優先度(実装済み)

  • entriesRANGE_FOLD_METHODS:entries追加 + range_constant_unarywhen :entries then range_to_a_tuple(range)追加済み

🟡 中優先度(実装済み)

  • minmaxrange_constant_unarywhen :minmax + range_minmax_tuple追加済み
  • first(n) / last(n)try_fold_binary_setまたは専用のtry_fold_range_constant_binaryで整数引数n ≤ LIMITの場合にTupleリフト

🟢 低優先度

  • sum → 等差数列公式でConstantに畳む(ただしInteger Rangeのみ対象)

列挙元: Set.new.methods - Object.new.methods → Ruby 4.0.5
実装ファイル: constant_folding.rbSET_ARRAY_UNARY_METHODS, catalog経由)
カタログ: data/builtins/ruby_core/set.yml, set_catalog.rb

Set.ymlのaliases:セクション(length → size, member? → include?, + → |, === → include?)は catalog_allows?method_entryから見えない(instance_methodsキーにはない)。 そのため、これらの別名メソッドは現在すべてfoldできずにRBSへfallbackする。

メソッド状態計測値(Set[1,2,3])備考
size3カタログ:leaf → invoke_unary
empty?false同上
compare_by_identity?false同上
flattenSet[1, 2, 3]同上(結果がConstant[Set]
join"123"同上(引数なし区切り文字なし)
hash-379102493…同上
to_a[1, 2, 3]SET_ARRAY_UNARY_METHODS → Tupleリフト
entries[1, 2, 3]同上(:entriesSET_ARRAY_UNARY_METHODSに含まれる)
include?false(Set引数)/ true(整数引数)カタログ:leaf + binary fold
subset?falseカタログ:leaf + binary fold
superset?false同上
proper_subset?false同上
proper_superset?false同上
-Set[1]カタログ:leafset_i_difference)→ Constant[Set]
``Set[1, 2, 3, 4]
^Set[1, 4]カタログ:leafset_i_xor)→ Constant[Set]
<=>nilカタログ:leaf
<カタログ:leafproper_subset?の別名だが直接登録)
>カタログ:leafproper_superset?の別名)
<=カタログ:leafsubset?の別名)
>=カタログ:leafsuperset?の別名)
==🔷`falsetrue`
inspect🔷Stringpurity: dispatch。RBS Stringで十分
to_s🔷Stringinspectの別名。同上
to_set🔷Set[Dynamic[top]]purity: block_dependent。RBSで十分
to_h🔷Enumerable経由。RBSで十分
disjoint?🔷`falsetrue`
intersect?🔷`falsetrue`
&🔷Setpurity: block_dependentset_i_intersectionset_iter呼び出し)。fold不可
add / add?🚫破壊的変更
<<🚫addの別名。破壊的変更
clear / delete / delete? / delete_if🚫破壊的変更
replace / merge / subtract🚫破壊的変更
collect! / map! / select! / filter! / reject! / keep_if🚫破壊的変更
flatten!🚫破壊的変更
each🚫反復子
classify🚫ブロック依存、戻り型複雑
divide🚫同上
compare_by_identity🚫破壊的変更
reset🚫内部構造リビルド
lengthIntegerMethodCatalog#method_entryのエイリアス解決で対応済み。
member?`falsetrue`
+Set同上。
===`falsetrue`
Enumerable継承メソッド(all?, any?, map, select等)🔷BlockFolding / RBS

🔴 高優先度(なし — 主要な集合演算は実装済み)

🟡 中優先度(全項目実装済み)

  • length, member?, +のYAMLエイリアス解決
    • MethodCatalog#method_entryresolve_alias_entryを追加し、aliasesセクションも参照するよう拡張
    • ===も同一の仕組みで解決

🟢 低優先度(実装済み)

  • === → 同上の対応に含める

5. Phase 2 — ギャップのティア分類

Section titled “5. Phase 2 — ギャップのティア分類”

invoke_unary / invoke_binaryが呼ぶだけで結果がConstant[T]になるもの。unary_ops_for / ops_forに新しいwhenケースを追加し、RATIONAL_UNARY, COMPLEX_UNARY, RATIONAL_BINARY定数Setを定義済み。

メソッド期待戻り型優先度
Rationalzero?Constant[bool]🟡
Rationalinteger?Constant[bool]🟡
RationalrealConstant[Rational]🟡
Rationalabs2Constant[Rational]🟡
Rationalconj, conjugateConstant[Rational]🟢
Rationalnonzero?`Constant[Rationalnil]`
RationaldivConstant[Integer]🟡
Rationalmodulo, %Constant[Rational]🟢
RationalremainderConstant[Rational]🟢
RationalfdivConstant[Float]🟢
Complexzero?Constant[bool]🟡
Complexnonzero?`Constant[Complexnil]`

実装手順(完了):

  1. constant_folding.rbRATIONAL_UNARY = Set[:zero?, :integer?, :real, :abs2, :conj, :conjugate, :nonzero?].freezeを追加
  2. RATIONAL_BINARY = Set[:div, :modulo, :%, :remainder, :fdiv].freezeを追加
  3. unary_ops_forelse Set.newの前にwhen Rational then RATIONAL_UNARY / when Complex then COMPLEX_UNARYケースを追加
  4. ops_forwhen Rational then RATIONAL_BINARYを追加
  5. 同様にCOMPLEX_UNARY = Set[:zero?, :nonzero?].freezeを追加

Tier A(Tupleリフト拡張)— RANGE_FOLD_METHODS追加

Section titled “Tier A(Tupleリフト拡張)— RANGE_FOLD_METHODS追加”
ファイル変更優先度
constant_folding.rbRANGE_FOLD_METHODS:entries追加済み🔴
constant_folding.rbrange_constant_unarywhen :entries追加済み(to_aと同じrange_to_a_tuple実装)🔴
constant_folding.rbRANGE_FOLD_METHODS:minmax追加 + range_constant_unarywhen :minmax + range_minmax_tuple追加済み🟡
対象修正箇所優先度
Set#length, Set#member?, Set#+method_catalog.rbresolve_alias_entry追加 + method_entryにエイリアス解決フォールバック追加済み🟡
Set#===同上🟢

なし(Rational / Complex / Range / SetはShapeDispatchが扱う構造型ではない)。

なし(本スコープ外。Range#sum, Range#first(n)等はブロックなしの数値計算なのでTier Aが適切)。

Tier D — 新singleton-foldingモジュール

Section titled “Tier D — 新singleton-foldingモジュール”

なし(Rational / Complex / Range / Setのsingletonメソッドに新モジュールが必要なものはない)。


作業変更先ファイル
RATIONAL_UNARY / RATIONAL_BINARY追加lib/rigor/inference/method_dispatcher/constant_folding.rb
COMPLEX_UNARY追加同上
Range#entries / minmax同上(RANGE_FOLD_METHODS, range_constant_unary
Setエイリアス解決lib/rigor/inference/builtins/set_catalog.rb + method_catalog.rb
ユニットスペックspec/rigor/inference/method_dispatcher/constant_folding_spec.rb
統合フィクスチャ(Rational/Complex)spec/integration/fixtures/rational_catalog.rb
統合フィクスチャ(Range/Set)spec/integration/fixtures/range_catalog.rb

© 2026 TypedDuck. Licensed under CC BY-SA 4.0.