--int-overflow=promote ๅฎๅ
จๅไฝ่จ็ป
ใดใผใซ
SPINEL_INT_OVERFLOW=promote (-DSP_INT_OVERFLOW_MODE_PROMOTE) ใง:
make testๅ จ passmake benchๅ จ passmake optcarrotPASS + checksum 59662 (Makefile ใใ--int-overflow=wrappin ้คๅป)
็พ็ถ (master HEAD, 2026-06-19 ๅ่จๆธฌ โ ๆง bc7e1a1 ่กจใฏ obsolete)
| Target | promote ็ตๆ |
|---|---|
make test SPINEL_INT_OVERFLOW=promote(front-end ใ cc ใ promote driven) | 966/966 pass |
make bench ็ธๅฝ | 57/57 pass |
optcarrot (-DSP_INT_OVERFLOW_MODE_PROMOTE) | ใณใณใใคใซๆๅ + checksum 59662 |
โ 5ๆใฎ error ใใฑใใ(bit-ops/index/FFI ็ญใoptcarrot 72 errors)ใฏ ๆขใซๅ
จใฆ่งฃๆถๆธใฟใๅข็ๅคๆใฏๅฎ่ฃ
ๆธใฟใdefault gate(966 + optcarrot 59662 + bench 57)ใฏ g_promote_mode gate ใซใใไธๅคใ
้ฒๆ (2026-06-19)
- bigint
**/<</>>ใฎใณใผใ็ๆใใฐไฟฎๆญฃ(92e8d6dc):**ใฏ codegen ๆช้ ็ทใง int path ใซ่ฝใกใshift ใฏTY_BIGINTๆจ่ซใใใ "unsupported call"ใruntime ใฎsp_bigint_shl/shrใto_intใง 64bit ใซ truncate ใใฆใใใ3 ๆผ็ฎใจใไปปๆ็ฒพๅบฆใซใ - ใใญใใฏใซใผใ่็ฉใฎ bigint ๆๆ ผ(9295160d):
infer_bigint_loop_localsใtimes/each/upto/downto/step/loop/each_with_indexใใญใใฏใซๆกๅผต(g_promote_modegate)ใf=1; 25.times{|i| f=f*(i+1)}ใ promote ใง MRI ไธ่ดใไป้ใใฆ emit_op_assign ใฎ captured-cell path ใ int ๅฐ็จใ ใฃใใใฐ(bigint cell ใซsp_int_mulใง truncate)ใไฟฎๆญฃใ - Makefile promote ใในใ้
็ท:
make test SPINEL_INT_OVERFLOW=promoteใ front-end ใซ--int-overflow=promoteใcc ใซ-D...PROMOTEใๆธกใใใใซ(ไปฅๅใฏ test list ใ filter ใใใ ใ=promote codegen path ๆชๆค่จผ)ใpromote-only ใในใใฏtest/promote_*.rbๅฝๅใง raise/wrap ใใ้คๅคใpromote ๅ จ suite 966/0/0ใ
ๆฎใๆฌ่ณช็ gap (2026-06-19 ๆดๆฐ)
ๆๆ ผๆฉๆงใฏ g_promote_mode ไธใฎ infer_bigint_loop_locals(while + block loop ใฎ self-ref multiply ๆคๅบ)ใruntime macro ใซใฏ promote arm ใ็กใ(sp_int_add ใฏ overflow ใง raise)ใฎใงใ้็ใซ "็ก้ๅขๆฎ" ใจๅคๅฎใงใใ local ใ ใใ bigint ๅใใใใ
ๆฎใ raise ใซใชใใใฟใผใณ:
- ้ขๆฐๅผๆฐ็ต็ฑ(
def mul(x,y)=x*y; mul(10**15,10**15))= ้็ๆคๅบใฏๅ็็ใซไธๅฏ่ฝใruntime promote ใ่ฆใ=legacy ใฎๅ จ intโbigint widen(ไธ่จใๅฎๆ่ทฏใ)ใใใใๆๅพใฎๆฌไธธใ - ใชใใฉใซ็ดฏไน / bigint ใชใใฉใซ(
10**30,100000000000000000000)โ INT_MAX ใซ้ฃฝๅใAST ใ int64 ๅคใใไฟๆใใชใ(IntegerNode "value" ใ int)ใฎใง parser ๆฎตใง decimal ๆๅญๅใไฟๆใใๅฅ feature ใ่ฆใใpromote ๆฉๆงใจใฏ็ฌ็ซใ +/<<ใฎๅ็ด่็ฉ(*/**ใฎใฟ self-ref ๆคๅบๅฏพ่ฑก)ใ
ๆข็ฅใฎๅจ่พบใใฐ(promote ็ก้ขไฟใปdefault ใงใๅ็พ): 1.upto(N){ ... } ใฎ no-block-param ใใญใใฏใ body ใ drop(h=0; 1.upto(5){h+=1}; puts h โ 0)ใupto codegen ใฎๅฅไปถใ
ๆก็จๆน้: poly-based(SP_TAG_BIGINT)โ 2026-06-19 matz ๆฑบๅฎ
legacy ใฎใๅ
จ int โ bigint widenใใงใฏใชใใpoly ๅค(sp_RbVal)ใซ bigint ใ่ผใใๆนๅใๆก็จ(matz ๅคๆญ)ใ็็ฑ: (a) SP_TAG_BIGINT ่ฟฝๅ ใฏ promote ใจ็ก้ขไฟใซ็ฐ็จฎใณใณใใ/ใชใใฉใซ bug ใ็ดใ็ฌ็ซไพกๅคใใใใ(b) ๅฐใใ int ใฏ unbox ใฎใพใพ=Ruby ใฎ fixnumโbignum ใจๅใใง legacy ๅ
จ bigint ใใๅฎ็จ็ใ(c) ใณใขๆ่ณใ bug ไฟฎๆญฃใจๅ
ฑๆใ
้ฒๆ(landed)
- Increment 1 (ce6995c8):
SP_TAG_BIGINT(v.p=GC bigint)ใsp_box_bigint+ emit_boxed/unbox ใฎ TY_BIGINT arm + GC mark + poly consumer ๅ จ arm(puts/to_s/inspect/class_name/to_i/to_f/numeric_p/eq/cmp/hash-key)+ codegenemit_bigint_operand(poly operand ใsp_poly_as_bigintใง narrow)ใโ[1,"x",big]/{k:big}/ bigint hash-key ๅไฝใclang+ASAN ๆค่จผใ - Increment 2a (48863f34):
sp_poly_add/sub/mulใ bigint operand ใ bigint ๆผ็ฎใธ(ๅ จใขใผใใbigint+intโ0 bug ไฟฎๆญฃ)+ promote ใง int+int overflowโbigint ๆๆ ผ(SP_INT_OVERFLOW_MODE_PROMOTE#ifdef gateใdefault/wrap ใฏ wrap ็ถญๆ)ใโ ๆขใซ poly ๅใฎๅคใฏ promote ใง runtime ๆๆ ผใใใ
ๆฎ: Increment 2b(ๆฌไธธ big-bang)= intโpoly widen under promote
ๆขใซ poly ใชๅคใฏ 2a ใงๆๆ ผใใใใ้ขๆฐๅผๆฐใชใฉ้็ใซ int ใช slot ใฏ poly ใงใชใใฎใง overflow ใใฆใๆๆ ผใงใใชใใๆๅพใฎๅฑฑใฏ promote ใขใผใใง่ฉฒๅฝ int slot ใ poly ใซ widenใใ analyze ๅคๆดใwiden ๅ ใ bigint(legacy)ใงใชใ poly ใช็นใ้ใ: ๅฐใใๅคใฏ unbox ใฎใพใพใoverflow ๆใ ใ 2a ใฎๆฉๆงใง boxใ
2026-06-19 ่ฉฆ่กใฎ็ฅ่ฆ(revert ๆธใmaster ใฏ 2a ใฎ promote 972 ใฎใพใพ):
promote_widen_arith_params(analyze.c ใฎ re-narrow ๅพ hook):defใกใฝใใ param ใฎใใก+/-/*/**ใฎ็ดๆฅ operand ใ poly ๅ(block paramใป้ DefNode scope ใฏ้คๅค)โ c2 =def mul(x,y)=x*y; mul(10^12,10^12)ใ 1e24 ใงๅใใ(MRI ไธ่ด)ใ- ใใใ promote suite ใ **972โ947(25 err/3 fail)**ใซ้่กใ้่กใฎๆฌ่ณช: codegen ใฏๅไธ่ดใๅๆใซ coercion ใๆฟๅ
ฅใใชใใฎใงใwiden ใใ poly param ใ int slot ใซๅบไผใๆใๅ
จ้จๅข็ๅ:
mrb_int = sp_RbVal(poly param โ int local / cvar ไปฃๅ ฅใไธกๆนๅ)yield xใง poly ใ int block param ใธ(n = poly)sp_double(poly)(ๅฅใกใฝใใๅผใณใฎ int param ใธ coercion ็กใ)mrb_int == sp_RbVal(ๆฏ่ผ)/ cvar init ใ้ๅฎๆฐ
- ไผๆญ pass ใๅขใใ(infer_block_params/ivar/cvar/param/return ใ post-widen ใงๅใ)ใจๅข็ใใใใใ ใ(whack-a-mole)ใ
- ็ต่ซ: 2b ใฏใๅ จ polyโint ๅข็ site ใง coercion ใๆฟๅ ฅใใ codegen sweepใ(ไปฃๅ ฅไธกๆนๅ / yield / call-arg / ๆฏ่ผ / cvar)ใ่ฆใใ็ใฎ big-bangใๅฐ็จใปใใทใงใณใงๅข็ใใฑใใ 1 ใคใใคใใใใใฏ sound ใช uniform widen(ๅ จ intโpoly + ๅข็ coercion ๅฎๅ)ใc2 ใๅใไบใฏ็ขบ่ชๆธใฟใชใฎใงๆนๅผ่ชไฝใฏๆญฃใใใๆฎใใฏๅข็็ถฒ็พ ใ
2026-06-19 ็ฌฌ2่ฉฆ่ก(ไฟๅฎ gate ๆนๅผใปrevert ๆธใmaster=2a ใฎ 972): ไฟๅฎ gate ใ้ใญใฆ้้่กใ็ใฃใใๅๆใใใๆ นๆฌ ripple ใ็นๅฎ:
- ๅฎ่ฃ
ใใ gate: (1) DefNode ใกใฝใใใฎใฟใปblock param ้คๅคใ(2)
scan_param_use=param ใฎๅ จ read ใ+/-/*/**ใฎ็ดๆฅ operandใฎๆใฎใฟ widen(yield/call-arg/index/ๆฏ่ผ/ไปฃๅ ฅใซ1ใคใงใๅบใใไธๅฏ)ใ(3)method(:sym)ใง address-taken ใชใกใฝใใใฏ้คๅคใ(4)ไผๆญใฏ infer_write_types+infer_return_types ใฎใฟ(full re-run ใฏ็ก้ขไฟ slot ใๆนไนฑ)ใ - ใใใง block2/method/i960/bound_method ็ณปใฏ็ทใc2 ็ถญๆใใ ใ pattern_pin/class_var_read/proc ็ญใๆฎๅญใ
- ๆ นๆฌๅๅ = return-type ripple: param ใ poly ๅใใใจ arith ็ตๆ=ใกใฝใใๆปใๅคใ poly ๅใใใใฎๆปใๅคใ int ๆ่ใงๆถ่ฒปใใๅ
จ caller ใๅฃใใ:
^(double(7))pin ๆฏ่ผ(mrb_int == sp_RbVal)x = double(7)(int local ใธ)/@@total = @@total + n(int cvar ใธใstatic init ้ๅฎๆฐใ)&blkใกใฝใใใฎ signature ไธไธ่ด(undefined reference to sp_with_logging)
- polyโint coercion ใงๆถใๆกใฏ promote ใๅฐ็กใ(ๆๆ ผๅคใ truncate)ใๆญฃ่งฃใฏๆถ่ฒป slot ๅดใ poly ใซ widen(=full propagation)+ codegen ใ poly ้ๅฏพๅฟใช site(cvar static init / pin)ใ coerceใ
- = caller call-site ใฎ tolerance ่งฃๆ ใ whole-program coercion sweep ใๅฟ ้ ใgate ใ ใใงใฏใ็ตๆใ puts ็ญ poly-tolerant ๆ่ใงใใๆถ่ฒปใใใชใใกใฝใใใใพใง็ตใใชใใจ้้่กใซใงใใใใใใฏ c2 ็ดใใๆฎใใชใใ
- ๆฌกใปใใทใงใณๆ้: (A) full propagation ใๅ ฅใใsur้ขๅใใ codegen site ใ 1 ใคใใค coerce(cvar poly init / pin poly ๆฏ่ผ / ๅ int-consume ใ poly widen)ใ(B) ใพใใฏ call-site tolerance gate(ๆปใๅคใ int ๆ่ใงๆถ่ฒปใใใใกใฝใใใฏ widen ใใชใ)ใๅฎ่ฃ ใ่ฉฆ่กใณใผใใฏ git ๅฑฅๆญด(ๆฌ commit ็ดๅ)ใซ็กใ=revert ๆธใๆฌ็ฏใๅฎๅ จใชๅ็พๆ้ ใ
2026-06-20 ็ฌฌ3่ฉฆ่ก ็ถ่ก = ๅข็ site ใฎๆจชๅฑ้ใง 831โ859(+28)ใ4 commitใdefault 992/0/0 ็ถญๆ:
full intโpoly widen pass(79709207)ใๅๅฐใซใERR(=C compile fail ใฎๅข็ coercion gap)ใ emission-site ๅไฝใงๆฝฐใใใๅ fix ใฏ poly slot ใๆคๅบใใใ rvalue ใ emit_boxed(node ็)/emit_boxed_text(ๅ+ใใญในใ็)ใง box ใใๅไธใใฟใผใณใใ้ๆฌก commit ใฏ็ทใๅขใใใชใใใจใใๅๅใฎๆฒ่ฆณใฏ่ชคใใงใๅไธ site ใฎใใฑใ(cvar static / instance_exec / range.each)ใฏ็ดๆฅ่คๆฐใในใใๅๅพฉใใ(ใใซใๅข็ใในใใ ใใๆจชไธฆใณไพๅญ)ใ
-
cvar static init(298a0e56, +2):
static sp_RbVal cvar = default_value(TY_POLY)ใsp_box_nil()(้ขๆฐๅผใณ=้ๅฎๆฐๅๆๅๅญ)ใ{SP_TAG_NIL,0,{0}}ๅฎๆฐ aggregate ใ emit(civ ใจๅใใฟใผใณ)ใdefault ใฎ genuine-poly cvar ใฎ latent bug ใ่งฃๆถใcodegen.c:2742ใ -
instance_exec/instance_eval block-param(dbc46864, +16): lifted block ใฎ
lv_<param> = <arg>ๆ็ธใ int arg ใ poly slot ใธใnumbered/requireds(็ดๆฅ argใปauto-splat ่ฆ็ด ใปtrampoline arg)/keyword ใฎ 4 ็ต่ทฏใง slot poly ใชใemit_boxedใcodegen_call.c:5268+ใ -
(a..b).each fusion(07e55f26, +3): loop var ใ int ็ด้งๅใpoly counter ใฏ fresh
mrb_intใง้งๅใๆฏ iterlv_i=sp_box_int(_tc)(emit_for ใจๅใใฟใผใณ)ใcodegen_call.c:10749ใ -
masgn target boxing(694f3f89, +7): scalar-RHS local(+typed-zero rest default)/tuple-element localใปcvar/typed-array destructure get/trailing rights get ใ boxใcodegen_stmt.cใ
-
leading-splat masgn(91c022ce, +1):
*xs, last=[..]ใฎ post-splat fixed target ใ temp ็ต็ฑ boxใsplat_destructure ็ทใcodegen_stmt.c:3672ใ(promote 860 ๅฐ้) -
โ ๆฑบๅฎ็ๆดๅฏ: widen pass ใฏ
scope->locals[].type/ivar_types/cvar_typesใ ใๆธใๆใใnode-type cache ใฏๆดๆฐใใชใใใใใซcomp_ntype(c, target_node)ใฏ widen ๅใฎในใซใฉๅ(int ็ญ)ใ่ฟใใslot ใ poly ใใฏๅฟ ใscope_local(scope, name)->type(or ivar/cvar ใฎ type ้ ๅ)ใงๅคๅฎใใใใจใrvalue ใ box ใใๅใฏcomp_ntype(value)(็ใฎๅคๅ)ใงๅใใใใฎ non-update ใฎใใใใง rest default ใฎ typed-zero(default_value(int)="0")ใๅพฉๅ ใงใใemit_boxed_text(int,"0")=sp_box_int(0)ใง quirk ไธ่ดใ -
โ block-param widen ้คๅค(0ed24068, 860โ901ใ+41!)= ๆฌใปใใทใงใณๆๅคงใฎๅๅ : block-param ๅๅพฉ(
[1,2,3,4].filter_map{|x| x*2 if x.even?})ใฏๆๅคงใฐใซใผใใ ใฃใใ็ๅ : widen ใฏ block-param ใฎ scope local ใ poly ๅใใใใblock emitter ใฏ use_shadow ใง param ใ element ๅ(int)ใซ retype ใใฆ body ใๅ infer ใใใใ ใeven?็ญใกใฝใใๅผใณใฎ inference ใฏ receiver ใ cache ใใ่ชญใใ ใใงๅ infer ใใชใ(*ๆผ็ฎๅญใฏ operand ใ infer_type ใงๆดๆฐใใ)ใฎใงใx*2=int /x.even?=poly ใซๆททๅจใใmrb_int lv_xshadow ใๅคๅดsp_RbVal lv_x(widen)ใไบ้ๅฎฃ่จใ่งฃ=block-param ใ widen ใใ้คๅค(is_block_paramskipใanalyze.c:2275)ใblock-param ใฏๅๅพฉใณใฌใฏใทใงใณใฎ element ๅใงๅไปใในใใงใwiden ใฏๅฎณใ ใใmethod param ใฏๅผใ็ถใ widen(promote ใฎๆฌๆจ)ใcompile error ใจไธ่ดใใ output-mismatch FAIL ใไธๆใๅฝๅใฏใanalyze ใงๅใไธ่ฒซ poly ๅใใๆณๅฎใใใใ้ใซใblock-param ใฏ widen ใใชใใใๆญฃ่งฃใ ใฃใใ -
polyโscalar unbox(29dbedea, 901โ909): block-param ใ int ใซไฟใฃใใใจใงใpoly source(widen ใใใ yield ๅคใปivarใปtrampoline temp)ใ int block-param ใธๆ็ธใใ้ๆนๅใๅฟ ่ฆใซใemit_block_invoke ใฎ yield ๆ็ธ + instance_exec ใฎ is_exec/tramp ๆ็ธใซ
bt scalar && at poly โ emit_unbox_textarm ใ่ฟฝๅ (box arm ใฎๅฏพ็งฐ)ใyield/forward_args_block/block_forward_*/inlined_yield_self_locals/instance_exec_mixed_args ็ทใ -
ๆฎ ERR=64 / FAIL=20(
/tmp/perr2.txtใฎๆๆณใงๅๅๅพ): B4 builtin-arg coerce(~19)= poly arg ใ builtin ใฎ int/typed param ใธ(sp_bigint_new_int/sp_range_include/sp_str_sub_range(_r)/user<=>=_lt_set_gt/sp_collect_s็ญใcall-arg site ใงๆฃๅจ coerce)ใB6 ๆฎ(polyโint ไปฃๅ ฅ)= ใพใ ๆพใๅใใฆใชใๆ็ธ siteใB1 ๆฎ(intโpoly ไปฃๅ ฅใ8)ใclosure capture(front-end, 5)=unsupported closure capturing a non-integer variable(widen ใง capture ๅคๆฐใ poly ๅโclosure ใ้ int capture ้ๅฏพๅฟใfront-end ๅถ้)ใไปใซ return mismatch(3)/invalid binary operands(4)/invalid initializer(2)/unsupported p argument(clamp)็ญใFAIL=20 ใฏใณใณใใคใซ้ใใๅบๅๅทฎ(ไพ:procใ proc ๆปใๅคใง6โ0)ใๅฅ้่ชฟๆปใ -
range/string builtin ใฎ poly arg coerce(17fa2d32, 909โ912):
sp_range_include(include?/case-as-value/when range-membership ใฎ 3 site)ใจ string slice/index(sp_str_sub_range[_r]/sp_str_char_at_or_nil)ใฎ int ๅผๆฐใ poly ใฎใจใsp_poly_to_i(string ๅดใฏemit_int_exprใงไธๅพ coerce)ใrange/case/truncate_module_method ็ทใpoly ็ต่ทฏใฎใฟๅคๅใdefault ไธๅคใ -
่ช่ตฐใใใ(912โ927ใ+15): masgn/pattern ็ณปใฎ box(pattern-match destructure+captureใleading-splatใcvar op-assignโ
sp_poly_<op>+inference ไฟฎๆญฃใbegin/rescue tail box)+ index/count ๅผๆฐใฎไธๆฌemit_int_exprๅ(array/string indexใปfetchใปcountใปop-assign ใฎmrb_int _t=<idx>็ด25 siteใpoly ใฎใฟ coerce ใง default ไธๅค)+ bigint slot poly ไปฃๅ ฅโsp_poly_as_bigint+ range/string-index builtin ใฎ poly arg coerceใๅ commit ใฏg_promote_mode็ต่ทฏใฎใฟๅคๅใdefault 992/0/0 + optcarrot 59662 ็ถญๆใ -
โ ็ฝ (่จ้ฒ):
emit_tail_valueใฎg_ret_type==POLY็กๆกไปถ box ใฏ explicit-return ็ต่ทฏใจไบ้ box ใง begin_rescue/forward_args_block ใๅๅธฐ(spot-test ใงใฏ PASS ใ ใ full-suite ใง็บ่ฆ)โ revertใๅ ฑๆ tail/return ็ต่ทฏใฎๅคๆดใฏ full-suite ๅฟ ้ (spot-test ไธๅฏ)ใ -
ๆฎ ERR=44 / FAIL=22 ใฎๆง้ ็ใใญใใซใผ:
- proc/closure ใฎ poly ๅฏพๅฟ(closure-capture ~5 ERR + proc 6โ0 ็ญ FAIL)โ โ
(A) ๅ็ฌ land ไธๅฏใๅฎ่จผ(2026-06-21):
- proc ABI ใฏ่กจ้ข mrb_int ใ ใ poly side-channel ใๆขใซๆใค:
_sp_proc_poly_args[16](poly ๅผๆฐ)/_sp_proc_poly_ret(poly ๆปใๅค)ใproc ๆฌไฝใฏ_proc_N(void*_cap, mrb_int argc, mrb_int *args)ใ - (A) ใๅฎ่ฃ
ใป่จๆธฌ: โ poly capture cell(
sp_RbVal *_cell_x+sp_cell_scan_rbval+ cap-struct ใใฃใผใซใsp_RbVal*+ proc-capture ๅถ้ใซ poly ่จฑๅฏ)โกproc local ใฎproc_retใ widen(ๆฌไฝ scope ใฎ ret ใฏ widen ๆธใ ใ caller ๅดlv->proc_retใๆช widen โ.callใ side-channel ใ่ชญใพใ raw mrb_int=0 ใ่ฟใ)โขemit_proc_call_argsใฎ int slot ใซsp_poly_to_iๅ ฌ้(int proc param ใ args[k] ใ่ชญใใใ)ใ - ๅๅฅใซใฏ proc_closure / case_local_in_lambda ใ PASSใซใชใฃใใใfull-suite ใง 927โ920(PASS -7, FAIL +9)ใซ็ดๆธใ
- โ
็ๅ ใ็ขบๅฎ(2026-06-21 ็ฌฌ2ๆฌก่ชฟๆป)= proc_ret ใฎ post-widen fixpoint ไผๆญไธๆดๅ(ๅฝๅใside-channel ้ๅๅ
ฅใใจๆจๆธฌใใใ่ชคใ):
.callใฎ return ่ชญใฟๅบใใฏ proc ใฎ caller-sideproc_retใง int slot vs_sp_proc_poly_retใๅๅฒใใใใ proc ๆฌไฝใฎๅฎ emit ret ใจไธ่ดใใชใใจ 0 ใ่ฟใใ- ๅคฑๆๆนๅโ (naive widen=ๅ
จ proc_retโpoly):
->(a,b){a+b}(a,b ใฏ block-param ้คๅคใง intใๆฌไฝใฏreturn sp_int_add=int return)ใง caller ใ side-channel(ๆช่จญๅฎ)ใ่ชญใฟ 0ใmulti_arg_lambda ็ญ 11 lambda ใ้่กใ - ๅคฑๆๆนๅโก(literal ้ๅฎใง proc_ret ๅ่จ็ฎ=
proc_ret_of): multi_arg ใฏ็ดใ(ๆฌไฝ intโproc_ret int)ใใc = make_counter()(ใกใฝใใใ่ฟใ proc) ใฏ proc_ret ใ make_counter ใฎret_proc_ret(ๆช widen=int)็ฑๆฅใงใliteral ใซใผใใๅใใใผใ โ proc_closure ใๅ้่กใ - = proc_ret ใฏ่คๆฐใตใคใใฎ fixpoint(
x=proc{}analyze_pass.c:1124 / proc param :1218 / methodret_proc_ret:3719 / composeใปto_proc)ใwiden ๅพใซใใฎ fixpoint ๅ จไฝใๅๅๆใใใๅฟ ่ฆใใใใnaive widen ใ้จๅๅ่จ็ฎใไธๅฏใproc_node_ret=ๆฌไฝๆ็ตๅผใฎ infer(analyze_util.c:334)ใ
- โ
โ
่งฃๆฑบๆธใฟ(ed0c0d68, 927โ932, ๅๅธฐ0)= option 1(ABI ๅคๆดไธ่ฆ):
- โ poly capture cell:
sp_RbVal *_cell_x+sp_cell_scan_rbval(sp_gc.h)+ cap-struct ใใฃใผใซใsp_RbVal*(codegen.c)+ proc-capture ๅถ้ใซ TY_POLY ่จฑๅฏใread/write ๆขๅญ็ต่ทฏใง OK(lvalue deref + emit_assign ใฎ poly box arm)ใ - โกargs int-slot ๅ
ฌ้:
emit_proc_call_argsใง poly arg ใsp_poly_to_iใง int slot ใซใ็ฝฎใ(int proc param=block-param ้คๅค ใ args[k] ใ่ชญใใใ)ใ - โขproc_ret/ret_proc_ret ใฎ post-widen focused fixpoint(analyze.c, finalize infer ใฎๅพ):method scope ret_proc_ret(proc_ret_of ใงๆฌไฝใใ)+
x=proc{}/x=factory()ใฎ proc_ret ใๅๆใซใผใใงๅๅฐๅบใproc-return metadata ใฎใฟๆดๆฐใwiden slot ๅใฏไธๅคใ - โ
ๆฑบใๆ = fixpoint ๅพใซ
for id: infer_type(c,id)ใง node-type cache ใๅๆง็ฏใcodegen ใฎ.callใฏcomp_ntype(call node)(node cache)ใ่ชญใใฎใงใproc_ret ใๆดๆฐใใฆใ cache ใ stale ใ ใจ.callใๅคใ int slot ็ต่ทฏใๅบใใๅ infer ใฏ scope local ๅใ่ชญใใ ใใงๅคใใชใใฎใง widen ไธๅคใ - ็ตๆ: proc / proc_closure / case_local_in_lambda / enum_for_each / lowered_block_given ใ็ทใproc ใฎ 6โ0 FAIL ใ่งฃๆถใๅฝๅๆจๆธฌใฎใside-channel ้ๅๅ ฅใใABI ๅ จ้ขๆนไฟฎใใฏใใใใไธ่ฆใ ใฃใ(็ๅ ใฏ node-cache ใฎ refresh ๆผใ)ใ
- โ poly capture cell:
- proc ABI ใฏ่กจ้ข mrb_int ใ ใ poly side-channel ใๆขใซๆใค:
- node-cache stale:
emit_hash_key็ญใcomp_ntype(key)ใฎ widen ๅ int ใ่ชญใฟ coerce ใ้ฃใฐใ(int-keyed hash ใฎ poly key=bundle_class_06)ใlocal read ใฏscope_local()->typeใๆญฃใgeneric ใใซใใผใฏ node ๅไพๅญใไธญๅคฎ่งฃๆฑบ่ฆใ - 932โ939 ใฎๅฎๅ
จใฐใซใผใ landed(ๅ
จ g_promote_mode gate ๅ
ใdefault 992/0/0+optcarrot 59662 ็ถญๆ): bound-method ็ดๆฅ
.callใฎ arg ใemit_arg_or_defaultใง param ๅ coerce(method/i960)/ ClassVariableWriteNode ๆจ่ซใ cvar ๅ่ฟใ=ไบ้ box ่งฃๆถ(cvar_method_first_assign)/ poly-receiver dispatch ใฎ poly argโscalar param unbox(8313,<=>ๅ้ฒ)/ splat ๅฑ้่ฆ็ด ใ poly param ใธ box(splat_call)/<=>ใ ret widen ้คๅค(ๅฐ int ใใ่ฟใใ overflow ็กใโcaller ใฎ(a<=>b)<cmp>0ใ int ๆฏ่ผใง้ใใlrama_features)/ typed-array ret ใ body ใฎ PolyArray ใซ่ฟฝๅพ(post-widen fixpoint ใฎ loop3=method ret ใ body ๆซๅฐพ/return ใฎ PolyArray ใใๅๅฐๅบใmulti_return)ใ ๆฎ ERR=34(939 ๆ็น)ใฎๆฃๅจ one-off / ๆทฑใ codegen ใใฐ:- ptr_array: method ret ใฏ PolyArray ๅใใใ caller ใฎ
local = method()ใฎ local slot ๅใ IntArray ใฎใพใพ(infer_write_types ใฏ widen ๅ็ขบๅฎ)= method-retโlocal ๅใฎไผๆญ cascade ่ฆใ - poly-receiver dispatch ใฎ arg coerce ๅๆนๅ:
8313ใง poly argโscalar param ใฎ unbox arm ่ฟฝๅ ๆธ(<=>็ญใๅๅธฐ0)ใใ ใ user<=>(comparable_between_user_type ็ญ 3)ใฏ็ฌฌ2ใใญใใซใผ = between?/clamp ใฎ arg-hoist g_pre ๅๅ ฅใใฐใงๆฎใ:sp_Temp * _t7 = sp_RbVal _t10 = ...(Temp.new(5)ใฎ boxed arg hoist ใๅคๅด arg-temp decl ใฎๅๆๅๅญๅ ใซๆททๅ ฅ)ใemit_dispatch(codegen_fold.c:3389)ใง arg ใๅด buffer ่ฉไพกโprelude flush ๅพใซ temp declใใฎ้ ๅบไฟฎๆญฃใ่ฆใใ - closure_capture_float ็ณป(3, sp_runtime.h:187
mrb_int=sp_RbVal): poly cell ๅฐๅ ฅใง capture ใ้ใใใใซใชใฃใใใproc ๆฌไฝใฎ captured ๅคๆฐใฎ็ฎ่กใsp_int_add(poly cell, 1)(comp_ntype ใ intใcell ใฏ poly)ใproc ๆฌไฝ scope ใฎ captured-var ๅไธ่ดใ่ฆใใ - bound-method
.call็ดๆฅ dispatch ใฎ raw arg(method=sp_double / i960=sp_dbl / splat_call=sp_mix / bound_method_single_eval=sp_poly_puts / cvar_method_first_assign=sp_box_int): poly param ใธ int arg ใ box ใใใ - B6 polyโint(bm_instance_eval=ivar-write-as-expr / poly_dispatch_* / instance_exec break/next/trampoline_result / bundle_class_10 ็ญ)ใB1 intโpoly(instance_eval_block_params/bundle_misc_b/block2/bundle_classd_04)ใbinary op(pattern_pin
==/bundle_class_05<</lrama_features<)ใreturn mismatch(compile_time_define_method_int / multi_returnใปptr_array=PolyArray vs IntArray)ใinvalid init(i916/op_assign_user_operator)ใhash key(bundle_class_06=emit_hash_key ใฎ comp_ntype stale)ใsp_box_str int-conv(recursive_implicit_yield_value)ใsp_Integer undeclared(class_method_open_class_call)ใfloat aggregate(float_round_nonliteral)ใld error(fiber_capture_no_leak_to_sibling/i1007)ใfront-end(clamp_bounds/integer_div_by_zero)ใๅใ 1-2 ใในใใๅๅฅ่จบๆญ่ฆใ - FAIL=19 ใฏใณใณใใคใซ้ใใๅบๅๅทฎใๅฅ้ใ
- ptr_array: method ret ใฏ PolyArray ๅใใใ caller ใฎ
- proc/closure ใฎ poly ๅฏพๅฟ(closure-capture ~5 ERR + proc 6โ0 ็ญ FAIL)โ โ
(A) ๅ็ฌ land ไธๅฏใๅฎ่จผ(2026-06-21):
-
ๆๆณ:
/tmp/ptest.sh <name>(ๅไฝ)ใ/tmp/perragg.shโ/tmp/perr4.txt(ๅ จ ERR first-error)ใ/tmp/ptest_lastc(ๆๅพใฎ cfile)ใไธญๅคฎ coerce=emit_int_expr(polyโint)/emit_float_expr/sp_poly_as_bigint/emit_boxed+emit_boxed_text(โpoly)/emit_unbox_text(polyโscalar)ใ -
ๆฌกใฎไธๆ: (1) ๆฎ B4 one-off ใ
emit_int_expr/sp_poly_as_bigintใงๅๅฅ coerce(ไธญๅคฎๅใงใใ site ใฏ emit_int_expr ใซๅฏใใ)ใ(2) closure-capture front-end(capture ๅคๆฐ poly ๅฏพๅฟ or widen ้คๅค)ใ(3) FAIL=21 ใฎๅบๅๅทฎ(proc ็ญ)ใๆๆณ=/tmp/ptest.sh <name>ใ/tmp/perragg.shโ/tmp/perr2.txtใ/tmp/ptest_lastcใซๆๅพใฎ cfileใpolyโint ใฏemit_int_exprใpolyโfloat ใฏemit_float_exprใpolyโbigint ใฏsp_poly_as_bigintใๆขๅญใฎไธญๅคฎใใซใใผใ -
2026-06-21 ็ถ่ก(939โ959ใERR 34โ15ใ12 commitใๅ จ g_promote_mode gate ๅ ใง default 992/0/0 + optcarrot 59662 ็ถญๆ):
- pattern_pin(22d351d2): scalar scrutinee ใซๅฏพใใ pinned poly ๅค(
in ^xใx widen)ใemit_unbox_textใง unboxใ - poly cell op-assign(f5..): captured poly cell(
sp_RbVal *nใproc ๅn += 1)ใฎ compound-assign ใsp_poly_<op>/bitwise re-box ใธใclosure_capture_float/block_forward_value_callable/bundle_classd_13ใ - array-local cascade(78872692)= post-widen fixpoint step (4): map ใกใฝใใ ret ใ array literal ใ PolyArray ๅใใใจใ
local = valueใฎ IntArray/StrArray/FloatArray slot ใ TY_POLY_ARRAY ใซ่ฟฝๅพใptr_arrayใ - poly
<=>(e34530e2): poly operand ใฎ<=>ใsp_poly_cmpใธ(user class ใฎ<=>ใซ่ชค dispatch ใใฆ boxed-int payload ใ user-ptr cast โ recursion segfault ใๅ้ฟ)ใbundle_classd_50ใ - between? arg-hoist(f447..): Comparable#between? ใฎ self/lo/hi temp ใใๅ operand ใ local buffer ใงๅ ใซ emit ใใฆใใ decl prefix ใๆธใ(operand ่ช่บซใฎ g_pre hoist ใ decl ่กใๅฒใใชใใใ้ ๅบๅ ฅๆฟ)ใcomparable_between_user_typeใ
- unary
-@/+@/~on poly(analyze_infer): poly receiver ใฎ unary ใ poly/int ใซ่งฃๆฑบ(method-dispatch unify ใ user class ใฎ-@ใซ bind ใใฆ obj ๅใ cascade ใใใฎใ้ฒใ)ใunary_operator_methodsใ - poly-dispatch scalar slot unbox(8217): length-like poly dispatch ใฎ int slot ใซใwiden ใใใ user method ret(poly)ใ
emit_unbox_textใงไธใใ(box ๆนๅใฎ้)ใpoly_dispatch_builtin_all/poly_dispatch_ptr_array/bundle_class_10/bundle_classd_28ใ - instance_exec result slot ใ break/next ๅคใง sizing(codegen+analyze):
next val+1(poly)ใ trailing999(int)ใใๅบใใจใ result temp ใ union ๅใซใie_splice_value_ty(codegen)/ie_block_break_next_ty(analyze)ใง break/next ๅคๅใ unifyใg_ie_res_polyflag ใง scalar break/next/last ใ boxใinstance_exec_next/instance_exec_breakใ - nested destructure box(codegen_stmt):
a, (b, c), d = 1, [2,3], 4ใฎ inner array element ใ poly target slot ใซ boxใbundle_misc_bใ - obj op-assign user-operator arg box(codegen_stmt):
slot OP= rhs(obj slot + user OP)ใฎ rhs temp ใ OP param ใ poly ใฎใจใ boxใop_assign_user_operator + siblingใ - loop{} poly result(codegen_call): expression-position
loop{ break v }ใฎ result temp ใdefault_value()ใง init(NULLโsp_box_nil())+g_ie_res_polyใง scalar break ใ boxใi916ใ - constant cascade(analyze)= step (5):
COUNT = obj.mใงใกใฝใใ ret ใ widen ใใใจใ int ๅฎๆฐ slot ใ poly ใซ่ฟฝๅพใbare_module_body_cmethod_callใ - 959โ965+ ็ถ่ก(ใใใซ 9 commitใdefault 992/0/0+optcarrot 59662 ็ถญๆ):
- define_method subst literal ใ poly-return tail ใง box:
define_method("m_#{n}"){ n }ๅๆใกใฝใใใฎ ret ใ widen โ subst literal(int)ใ boxใtail box ๅคๅฎใ subst node ใฎๅใง sizingใcompile_time_define_method_intใ - poly-ivar attr-writer infer=poly:
obj.attr = vใฎๅคใฏ C ไปฃๅ ฅ็ตๆ=boxed polyใinfer ใ rhs(int)ๅใ่ฟใใฆใใ โ ivar poly ใชใ poly ่ฟใใinstance_eval ๆซๅฐพ setter ใฎ result temp sizing ไธ่ดใbm_instance_evalใ - instance_eval ivar-write ใ rebound class ใง่งฃๆฑบ: splice ๅ
block scope ใฏ class_id ็กใ โ
@v=42ใฎ ivar ๅ UNKNOWN(box skip + infer rhs ๅ)ใg_ie_class_id(codegen)/an_ie_class_id(analyze)ใง่งฃๆฑบใinstance_eval_block_paramsใ - instance_eval/exec call node ่ช่บซใ rebound scope ใงๅ infer: post-fixpoint ๅ infer ใฏ body ใ ใๆดๆฐใcall node ๅใฏ stale โ truthiness consumer ใ int-nil form ใ poly ใซใ
infer_type(c,id)่ฟฝๅ ใbundle_classd_04ใ - value-form hash
[]=ใฎ poly key ใ unbox:h[k]=v(ๅผ)ใฎ key ใ emit_expr ็ โ typed-key hash setter ใซ polyใemit_hash_key ็ต็ฑๅใbundle_class_06(-Werror ๆคๅบใmake test ใฏ lenient ใง่ฆ้ใ)ใ - Float#round/ceil/floor/truncate ใฎ poly ndigits unbox:
(double)(poly)aggregate error โ emit_int_exprใfloat_round_nonliteralใ
- define_method subst literal ใ poly-return tail ใง box:
- โ
make-test promote count ใฏ -Werror ็กใใง lenient + ไธฆๅ compile timeout ใง flaky(ๅไธ binary ๅๅฎ่กใง ยฑ1 ๆบใใ)ใๅ fix ใฎ็ขบ่จผใฏ
/tmp/ptest.sh(-Werror, deterministic)ใdefault 992/0/0 + optcarrot 59662 ใ hard gateใไธก่ ใฏๅ จ commit ใง็ท็ถญๆใ - 965โ971 ็ถ่ก(ใใใซ 6 commitใERR 9โ3ใdefault 992/0/0+optcarrot 59662 ็ถญๆ):
- instance_exec block param ใ่ช block scope ใง่งฃๆฑบ: forward-block(
&bใๅฅ site ใฎ literal ใซ่งฃๆฑบ)ใฎ param ใ call site scope ใฎ็ก้ขไฟใชaใ่ชญใฟ slot ๅ่ชค่ช โcomp_scope_of(reqs[p])(param node ใฎ scope)ใง่งฃๆฑบใis_exec/tramp ใฎ polyโint unbox ใ็บ็ซใinstance_exec_trampoline_resultใ - reopened-primitive ใฎ poly dispatch receiver unbox:
(sp_Integer*)_t.v.pใฏ้ struct โ.v.i/.v.f/.v.s/(sp_sym)ใง union field ่ชญใฟใclass_method_open_class_callใ - poly local
%=โ sp_poly_mod: op-assign arm ใ +,-,*,/ ใฎใฟ โ%่ฟฝๅ ใinteger_div_by_zeroใ - poly clamp:
sp_poly_clamp(runtime, tag-dispatch int/float + NaN/order check ๆขๅญ helper ๅๅฉ็จ)+ infer poly.clampโpoly + codegen ใฎ 2-arg/range formใclamp_boundsใ sp_gc_mark_rbvaltypo โsp_mark_rbval: fiber poly-capture scan ใๆชๅฎ็พฉใทใณใใซๅ็ ง = ld errorใpromote ใฎ poly fiber capture ใงๅ้ฒ่ฆใi1007 / fiber_capture_no_leak_to_siblingใ
- instance_exec block param ใ่ช block scope ใง่งฃๆฑบ: forward-block(
- โ
ๆฎ ERR=3(971 ๆ็นใdeterministicใๅ
จใฆ raw mrb_int carrier ABI family = ๆง้ ็ใใญใใซใผ):
- block2: no-block ใฎ inline yield ใ poly value-if ใฎ then ๅๅฒใง
_t2 = 0(int)ใ poly slot ใธใyield emit ใsp_box_nil()ๅใใฆใ value-if/inline ็ต่ทฏใ0ใๅบใ๏ผemit ใจ value-if ใฎไบๆฎตใyield emit ๅ็ฌไฟฎๆญฃใงใฏไธๅฏใinline+value-if ใฎ branch-default ใ่ฟฝใ่ฆ๏ผใ - bound_method_single_eval: object-bound
.callใฎ ABI ใmrb_int(*)(void*, mrb_int...)ๅบๅฎใpromote ใง target method ใฏ poly param/ret ใซ widen โ args ใ param ๅใซ box + ret cast ใ target ๅใซใใๅ่ชฟไฟฎๆญฃ่ฆ(return cast ๅ็ฌใฏ ERRโFAIL ๆชๅใrevert ๆธ)ใ - recursive_implicit_yield_value: lowered-yield ใฎ raw mrb_int carrier ใ string/int ไธก็จ block ใงๅๅคๅฅไธ่ฝ โ
sp_box_str(mrb_int)่ชค้ธๆใcarrier ใซๅ tag ใๆใใใ ABI ๅคๆด่ฆใ - FAIL=19 ใฏใณใณใใคใซ้ใใๅบๅๅทฎ(attr=promote-mode crash ็ญใๅฅ้)ใ
- block2: no-block ใฎ inline yield ใ poly value-if ใฎ then ๅๅฒใง
โ ใปใใทใงใณ็ทๆฌ(940โ971ใERR 33โ3): emission-site ใฎ box/unbox coercion + post-widen fixpoint ใฎ cascade(array-local step4 / ๅฎๆฐ step5)+ instance_exec/eval ใฎ rebound-scope ่งฃๆฑบ(ivar-write/call-node ๅ infer/forward-block param scope)+ poly dispatch ใฎๅๆนๅ coerce + runtime helper ่ฟฝๅ (sp_poly_clamp)ใง็ณป็ตฑ็ใซๆฝฐใใใhard gate(default 992/0/0 + optcarrot 59662)ใฏๅ จ commit ใง็ทใmake-test promote count ใฏ -Werror ็กใ + ไธฆๅ timeout ใง flakyใ็ขบ่จผใฏ
/tmp/ptest.shใ - pattern_pin(22d351d2): scalar scrutinee ใซๅฏพใใ pinned poly ๅค(
-
971โ973 ็ถ่ก(ERR 3โ1ใๆฎ 1 = recursive_implicit_yield_value ใฎใฟ):
- block2 CLOSED: no-block ใฎ inline yield ใ poly value-if/inline tail ใง
0(int)ใ poly slot ใธใ็ๅ =emit_tail_valueใๆๅญๅ"sp_box_nil()"ใemit_ret_nil(g_ret_type)(=scalar)ใซๆธใๆใใ็นไพ(g_result_var ใฎ poly ใ็ก่ฆ)ใ2 ๆฎตไฟฎๆญฃ: yield emit ใcomp_ntype==POLYใงsp_box_nil()ๅ +emit_tail_valueใg_result_polyๆใฏ as-is pass-throughใ - bound_method_single_eval CLOSED: object-bound
.callใmrb_int(*)(void*, mrb_int...)ๅบๅฎ ABI ใงใwiden ๅพใฎ poly param/ret ใ truncate(0 ่ฟใ)ใtarget ใ้็่งฃๆฑบใงใใๆใฏใใฎๅฎ return/param C ๅใง fn pointer ใ cast +emit_arg_or_defaultใง arg coerceใdefault mode ใฏ้ widen ใงๅไธใณใผใ(ๅๅธฐใชใ)ใ - โ
ๆฎ ERR=1 = recursive_implicit_yield_value(ๆทฑใ multi-pass ABIใๆฌใปใใทใงใณใง root cause ็ขบๅฎใปไฟฎๆญฃใฏ scope ๅคใจๅคๆญ):
- ็็ถ:
countdownใ string block({"done"})ใจ int block({42})ไธกๆนใใๅผใฐใใreturn ๅใฏ poly ใซ unifyใใ ใ lowered-yield ใฎyield=sp_proc_call(__yblk__)ใฏ raw mrb_int ใ่ฟใใcall-site block proc(_proc_N)ใ raw ๅค(int ใฏ็ด ใปstring ใฏ ptrโmrb_int cast)ใ่ฟใใใใreturn yieldใฎ box ใง string/int ใๅคๅฅใงใใsp_box_str(mrb_int)่ชค้ธๆใ - ไฟฎๆญฃใฎๅฟ
่ฆ 3 ็น(ๅๅฅใซใฏๅฎ่ฃ
ใใใใ pass ้ ๅบใงไธๆ็ซ): โ
method_call_ret/yield_value_typeใ lowered-yield ใงๅ จ call-site unify(็พ็ถใฏใper-call-site ็นๆฎๅใๅๆใง first block ๅใ break-ๆก็จ โ ๅไธใณใณใใคใซใฎๅฎๆ ใจไธไธ่ด)โกcall-site block proc ใ poly-ret ๅ(_sp_proc_poly_retใซ boxใcodegen.c:1084 ใฎblk_ret==POLYๆฉๆงใๆขๅญ)โขlowered yield emit ใ_sp_proc_poly_retใ่ชญใใ - โ
ใใญใใซใผ = pass ้ ๅบ:
blk_retใ่จ็ฎใใinfer_return_types(analyze_pass.c:3699)ๆ็นใง lowered-yield ๅ(blk_param="__yblk__"่จญๅฎใanalyze.c:1992+)ใใพใ ่ตฐใฃใฆใใใใcountdown ใฎblk_paramใ NULL โ blk_ret ่จ็ฎ่ชไฝใ lowered-yield scope ใไธๅ่ฆใชใ(debug ็ขบ่ช: ่ฉฒๅฝ pass ใง blk_param ไปใ scope ใ 0 ไปถ)ใใใฃใฆ โกใฎๅๆ(blk_ret==POLY)ใๆ็ซใใชใใ็ใฎไฟฎๆญฃใฏ blk_ret ่จ็ฎใ lowering ๅพใซๅใใ(or lowering pass ๅ ใง่จ็ฎ)+ โกโข ใฎๅ่ชฟใงใanalyzer ใฎ pass ้ ๅบใซ่ธใฟ่พผใๆง้ ๅคๆดใsiblings(proc/block2/forward_args_block ็ญ)ใฏๆฌ่ฉฆ่กใงๅๅธฐใชใใ็ขบ่ชๆธใ ใใๆฌไธธใฏๆชๅๆใฎใใ revertใปclean ็ถญๆใ - FAIL=19 ใฏใณใณใใคใซ้ใใๅบๅๅทฎ(attr=promote-mode crash ็ญใๅฅ้)ใ
- ็็ถ:
- block2 CLOSED: no-block ใฎ inline yield ใ poly value-if/inline tail ใง
2026-06-20 ็ฌฌ3่ฉฆ่ก = ๆน้ (A) full uniform widen ใๅฎ่ก(branch promote-full-widen-experiment ใซไฟๅ
จ):
matz ๆดๅฏใpoly ใฏ int(inline)ใจ bigint(heap)ไธกๆนใ 1 ๅคใงไฟๆใใใฎใงใlegacy ใฎๅ
จ bigint(ๅ
จ heap)ใใๅน็็ ็ฒใๆใใฆๅ
จ widen ใงใใใใๅใใๅ
จ int slot โ poly ใๅฎ่ฃ
(analyze.c ใฎ fixpoint ๅพใปnode-type cache ๅใg_promote_mode gateใ24 ่ก)ใparam/return/local/ivar/cvar ใฎ TY_INTโTY_POLYใ
- ๆฌไธธ #1 ใๅใใ:
def mul(x,y)=x*y; mul(10**15,10**15)= 10**30ใmul(3,4)=12(ๅฐ int ใฏ inline poly)ใMRI ไธ่ดใapproach ๅฎ่จผๅฎไบใ - default gate ็กๅท(992/0/0ใg_promote_mode gate)ใ
- promote suite 993โ831(32 fail / 130 error)= ๅข็ใใฑใใ่กจ้ขๅใๅ จใจใฉใผใฏ polyโint ๅข็ใฎ coercion ๆฌ ๅฆ(codegen ใๅไธ่ดๅๆ)ใ
- ๅ็ดไปฃๅ
ฅๅข็ใฏ emit_assign ใซๆขใซ poly-box arm ใใ(codegen_stmt.c:512
lv->type==TY_POLY โ emit_boxed)ใๆฎใใฏไปฅไธใฎ ๅข็ใใฑใ(C error ้ ปๅบฆ้ ใ/tmp/promerr.txt้่จ):- ไปฃๅ
ฅ
sp_RbVal = mrb_int/long(265)= op_assign(x+=1)ใปivar/cvar writeใปๅฎฃ่จๅๆๅใชใฉ emit_assign ไปฅๅคใฎไปฃๅ ฅ็ต่ทฏใๅ write emit ใซ poly-boxใ - ๆฏ่ผ
sp_RbVal <= / >= / < / > / == mrb_int(~60)= poly recv ใฎๆฏ่ผใsp_poly_lt/cmp/eqใซๅใ(scalar ๆฏ่ผ codegen ใ int ๅๆ)ใ - increment
wrong type argument to increment(28)=lv_x++(loop counter ็ญ)ใ poly slotใlv_x = sp_poly_add(lv_x, sp_box_int(1))ๅใ - builtin arg coerce(~40):
sp_IntArray_push(14)/sp_poly_to_s(11)/sp_poly_lt(9)/sp_bigint_new_int(5)/sp_poly_to_i(4)/sp_range_include(4)/sp_str_sub_range_r(4)= poly arg ใ builtin ใฎ int param ใธใcall-arg coerceใ - const/cvar static init ้ๅฎๆฐ(21)=
static ... = sp_box_int(...)(้ๅฎๆฐๅผ)ใcvar/const ใฎ poly ๅๆๅใ runtime init ใธ็งปใใใint ไฟๆใใฆ read ๆ boxใ - mrb_int = sp_RbVal(22)/ return mismatch(~10)= builtin ๆปใ(int)ใ poly slot ใธใใพใใฏ poly ๅคใ int return ๅใธใwiden ใๆฎใใๅข็ใ
- float
aggregate where floating-point expected(10)= poly ใ float ๆ่ใธใsp_poly_to_fcoerceใ
- ไปฃๅ
ฅ
- ๆฌกใฎไธๆ: ใใฑใ 1(op_assign/ivar/cvar write ใฎ poly-box)โ 2(ๆฏ่ผ)โ 3(increment)ใฎ้ ใงใๅใใฑใๅพใซ promote suite ใๅ่จๆธฌ(
rm -rf build/test-results && make test SPINEL_INT_OVERFLOW=promote OPT=-O1)ใemit_assign ใฎ poly arm ใใฟใผใณใๅ write/compare/return site ใซๆจชๅฑ้ใใไฝๆฅญใbranch ใใ cherry-pick ใใฆๅ้ใ - ๅคๆญ: ใใใฏ่จ็ป้ใ่คๆฐใปใใทใงใณใฎ big-bangใmaster ใฏ clean(2a ใฎ 993)็ถญๆใๅฎ้ๅพใซใพใจใใฆๆๆ ผใapproach ใฏ็ขบๅฎ(ๆฌไธธๅไฝใปๅน็ๅชไฝ)ใ
2026-06-21 ใใฑใ1(for-range loop counter)ๅฎ่ฃ
ใฎๆฑบๅฎ็็ฅ่ฆ:
emit_for ใฎ TY_RANGE arm ใซไฟฎๆญฃ(็ซฏ็นใ็ฌ็ซใซ sp_poly_to_i coerce + poly counter ใฏ fresh mrb_int temp ้งๅ&ๆฏ iter lv_<vn>=sp_box_int(_tc) ใง boxใearly return ใง else ๅ้ฟ)ใbranch promote-full-widen-experiment ใฎ commit bda23978 ใซไฟๅ
จใ
- ไฟฎๆญฃใฏ correct:
for i in 1..10(=55)+ poly ็ซฏ็น็for i in 1..f(=55)ใจใ MRI ไธ่ดใBUILD_OKใ็ซฏ็น coerce ใฏ counter ใฎ poly ๆงใจ็ฌ็ซใซๅฟ ่ฆ(concrete int counter + poly ็ซฏ็นnใงใmrb_int _t=lv_nใๅฃใใ)ใ - ใ ใ promote pass ใฏ 831 ๆจชใฐใ(errorโfail 1ไปถใฎใฟ็งปๅ)ใโตๅ failing ใในใใซ่คๆฐใฎ polyโint ๅข็ใ้ใชใโ1ใใฑใๅ็ฌใงใฏ็ทใซใชใใชใ(for-range ใ็ดใใฆใๅใในใๅ ใฎๆฌกใฎๅข็=ไปฃๅ ฅ/ๆฏ่ผ/builtin-arg ็ญใงใณใณใใคใซ็ถ่กไธ่ฝ)ใ
- ๆฆ็ฅ็็ต่ซ: ใใฑใ้ๆฌก commit ใฏไธญ้ใง pass ใๅขใใใชใใ็ทใซใใใซใฏ (1) 1ใในใใ็ธฆใซๅ จๅข็ๅฎ้(pass+1ใๅข็ใซใฟใญใฐ็ขบ่จผ)ใ (2) ๅ จๅข็(ไปฃๅ ฅไธกๆนๅ/ๆฏ่ผ/increment/builtin-arg/const-init/return/float)ใไธๆฌใงๆฝฐใ็ใฎ big-bangใๆฌกใปใใทใงใณใฏ for-range fix(bda23978)ใๅๅฐใซใใพใ 1 ใในใ็ธฆๅฎ้ใงๅ จๅข็ใฎๅฎ่ฃ ใใฟใผใณใ็ขบ็ซใใฆใใๆจชๅฑ้ใๅฎๅ จใ
(ๅ่)legacy ๆนๅผ
legacy backend(legacy/spinel_codegen.rb L55, L3037-3203)ใฏ promote ใงๅ
จ int slot ใ sp_Bigint* ใซ widen(method ABI = (void*, sp_Bigint*...) -> sp_Bigint*)ใๆก็จใใ(ไธ่จ็็ฑ)ใ
ๅฎ่ฃ ใฎ้ฃๆ:
- mode ไผ้: C ็ใฏ
codegen_program(nt)ใซ overflow mode ใๆธกใใชใ(main.c:355ใ็พ็ถ-Dใฎใฟ)ใg_promote_modeglobal ใ main.c ใง่จญๅฎใ analyze/codegen ใ่ชญใๅฟ ่ฆใ - big-bang ๆง: ๅ จ int ใ bigint ๅใใใจใๅใพใฃใฆใใชใๅข็ใๆฐใใซ่กจ้ขๅใใใใ้จๅ widen ใฏ promote ใณใณใใคใซใๅฃใใฎใงใๅ จๅข็ใๅๆใซ้ใๅฟ ่ฆ(=็พ optcarrot ใ้ใ็ฏๅฒใ่ถ ใใ path ใงๅๅบฆใใฑใๆฝฐใ)ใ
- optcarrot perf ้่กใชในใฏ: ใใญใใฏใซใผใๆคๅบใ็ด ๆดใซ่ถณใใจ optcarrot ใฎ
.timesๅx=x*yใๅคง้ bigint ๅใๅฃๆป ็ใซ้ ใใชใ(while ้ๅฎใฏใใฎๅ้ฟใ็็ฑใจๆใใใ)ใๅ จ int widen ใงใ promote optcarrot ใฏๅคงๅน ๆธ้(opt-in ใชใฎใง่จฑๅฎนใgate ใฏ wrap pin ใงไธๅค)ใ
ๆจๅฅจ: ๅฐ็จใฎ้ไธญไฝๆฅญใจใใฆ (1) mode ไผ้ โ(2) ๅ จ intโbigint widen pass(promote gate)โ(3) ่กจ้ขๅใใๅข็ใๆฝฐใ โ promote ใง test/bench/optcarrot ๅ็ขบ่ชใใฎ้ ใdefault/wrap ใฏ promote gate ใซใใไธๅคใชใฎใง gate ๅๅธฐใชในใฏใฏ promote ็ต่ทฏใซ้ๅฎใ
(ไปฅไธใ2026-05 ๅฝๆใฎ Error ใใฑใใๅ้ก โ ๅคใใฏ่งฃๆถๆธใฟใๅ่)
Error ใใฑใใๅ้ก
Bucket A: Bit operators on sp_Bigint * (LARGEST โ optcarrot ใฎ 80%)
error: invalid operands to binary & (have 'sp_Bigint *' and 'long long int')
error: wrong type argument to bit-complement
Ruby ใฎ a & b, a | b, a ^ b, a << n, a >> n, ~a ใง operands ใ bigint ใฎๆ C ๆผ็ฎๅญใไฝฟใใชใใ optcarrot ใฏ CPU emulator ใชใฎใง bit-op ใๅคง้ใ
ไฟฎๆญฃ: runtime helpers + codegen ๅๅฒ:
sp_bigint_and(a, b),_or,_xor,_shl,_shr,_not,_invcompile_operator_expr/compile_bitop_exprใง bigint operands ใๆคๅบ โ helper call emit- ๆททๅจ (bigint + int_literal) โ ไธๆนใ unbox / box ใใฆๆใใ
Bucket B: Builtin container helpers with bigint args
sp_IntArray_push(a, bigint_lv) โ needs sp_bigint_to_int
sp_IntArray_get(a, bigint_idx)
sp_FloatArray_set(a, idx, bigint_val) โ unbox + cast to mrb_float
sp_IntStrHash_set(h, bigint_key, val)
memory ใซ partial fix ่จๅใใใ ๆฎใใฎใฏ _push / _get / _set ใฎ็นๅฎ site ใจ FloatArray ใฎ bigintโfloat castใ
Bucket C: ๅๅพฉ / index ใง bigint
range.each { |i| arr[i] = ... } โ i bigintใ arr[i] ใง unbox ๅฟ
่ฆ
n.times { |i| ... }
block param ใ bigint ใง IntArray index ็ญใซไฝฟใใใ shapeใ ๆขใซ้จๅๅฏพๅฟๆธใฟใ ใๅใใใผใใ
Bucket D: FFI / typed user method call ใฎ poly โ bigint coerce
sp_Counter_cls_double(poly_val) โ param bigintใ arg poly
sp_mandelbrot(bigint, bigint) โ FFI param floatใ arg bigint
compile_typed_call_args ใง poly arg โ bigint param ใฎ coerce ใ่ฟฝๅ (mirror of #639 IVW unbox)ใ FFI :float / :int arg ใฏ bigint ใง sp_bigint_to_int โ castใ
Bucket E: Bigint slot init / return from poly
sp_Bigint * x = poly_expr โ .v.p extract ๅฟ
่ฆ
return poly_expr (function return bigint)
compile_expr_for_expected_type ใฎ polyโbigint arm ใ็กใ / ไธๅฎๅ
จใ
Bucket F: Bigint โ string ๅคๆๆผใ
puts bigint_val
"prefix" + bigint_val
sp_int_to_s(bigint_val) โ should be sp_bigint_to_s
memory ใซใๆๅญๅ่ฃ้ / str_concat / str << ใฎ bigintโstring ๅคๆ (sp_bigint_to_s)ใใจใใ partial fix ๆธใฟใ ๆฎใใฎ emit site ใๆขใใ
Bucket G: Test/bench infrastructure issues
promote ใจ็ก้ขไฟใซ่กจ้ขๅใใ shape:
int_eq_nil_strictโ int slot ใ bigint ๅใใใฎใง nil check ใฎๆๅใๅคใใpattern_pinโ pin pattern ใ int ใๆๅพ ใใฆใใ bigint ใงๅไธไธ่ดconst_self_ref_init_warnsโ ๅบๅ format ๅคๅ (0vs0LL?)
ใใใใฏๅๅฅ่ชฟๆปใ
Phases (ๅฎ่ฃ ้ )
Phase 1 โ Bit-op support for bigint (ๅคงใใญใใซใผ่งฃๆถ)
ๆๅคงใฎๅกใ ใใใง optcarrot ใฎ 80% errors ใๆถใใใ
1.1 lib/sp_runtime.h: ๆฐ helpers
sp_bigint_and(a, b),_or(a, b),_xor(a, b)โ ๆขๅญ GMP wrapper ็ต็ฑsp_bigint_shl(a, n),_shr(a, n)โ n ใฏ mrb_intsp_bigint_not(a)โ 1's complement (็ฌฆๅทๅ่ปข + 1 ใง signed ใจๅใ)
1.2 lib/sp_bigint.c: GMP mpz_and / mpz_ior / mpz_xor / mpz_mul_2exp / mpz_fdiv_q_2exp / mpz_com ใฉใใ
1.3 spinel_codegen.rb:
compile_operator_exprใงop in {"&", "|", "^", "<<", ">>"}&& (lt == bigint || rt == bigint) โ helper~ใฎๅ้ (compile_call_exprใง recv bigint mname~) โsp_bigint_not- mixed (bigint + int literal): literal ใ
sp_bigint_new_intใง box ใใฆ helperใ OR ไธกๆน unbox ใใฆ C ๆผ็ฎๅญ โ re-box
1.4 optcarrot ใงๅไฝ็ขบ่ชใ checksum 59662 ็ถญๆ็ขบ่ช
ๆๅพ : optcarrot promote PASSใ test promote +20ใ30 cases
Phase 2 โ Builtin container helpers ใฎ bigint unbox ๅใใใผใ
2.1 sp_IntArray_push emit site: arg ใ bigint ใชใ sp_bigint_to_int ใ wrap
2.2 sp_IntArray_get / _set / _index ๅๆง
2.3 sp_FloatArray_set ใฎ val ใ bigint ใชใ (mrb_float)sp_bigint_to_int(...) ใง cast
2.4 sp_*IntHash_* ใง key/val bigint ใฎ unbox
ๆๅพ : bench bm_loops_times / bm_matmul / bm_fannkuch PASSใ test promote +10ใ15 cases
Phase 3 โ Typed user method call ใฎ polyโbigint coerce
3.1 compile_typed_call_args (positional + kwarg):
- ๅผๆฐใฎ static type ใ
polyใง param expected ใbigintโ(arg).v.p็ต็ฑ - mirror of #639 ใฎ IVW unbox path
3.2 FFI :float / :int arg with bigint:
compile_ffi_func_callใง arg ใ bigint ใชใsp_bigint_to_intโ cast
ๆๅพ : nullable_poly_hash_arg_unbox ็ญ +5 testsใ bm_mandel_term / bm_so_mandelbrot ็ณป PASS
Phase 4 โ Bigint slot init / return from poly
4.1 compile_expr_for_expected_type: at == "poly" && expected == "bigint" โ (... ).v.p
4.2 compile_return_stmt: rt == "poly" && method return == "bigint" โ ๅๆง unbox
ๆๅพ : ๆฎ test promote errors +5
Phase 5 โ Bigint โ string ๅคๆๅใใใผใ
5.1 puts bigint, string interpolation "x=#{bigint}", << chain ใฎ emit site ใง bigint operand โ sp_bigint_to_s ็ต็ฑ
ๆๅพ : bench bm_csv_process / bm_jekyll_lite ็ณป PASS
Phase 6 โ ๅๅฅ test failure ่ชฟๆป
ๆฎ test failures ใๅๅฅใซๆฝฐใใ ๅใ ๅฐใใช shape:
int_eq_nil_strictโ bigint slot ใง nil compare ๆๅpattern_pinโ pattern matching ใฎ bigint scrutineeconst_self_ref_init_warnsโ output format ๅพฎๅทฎ
ๆๅพ : test promote 100% pass
Phase 7 โ Bench ๆฎใ + Makefile ๆด็
7.1 ๆฎ bench failures ๅๅฅใซๆฝฐใ
7.2 Makefile ใใ optcarrot ็จ --int-overflow=wrap pin ้คๅป (or --int-overflow=$(SPINEL_INT_OVERFLOW) defaulting to wrap ใ ใ promote ใงใ้ใ)
ๆๅพ : bench promote 100% pass
ๆค่จผใใญใผ (ๅ phase ใง)
# default mode ใฏๅฃใใชใ
rm -rf build/test-results/
make -j8 test 2>&1 | tail -2 # 631/0/0 ็ถญๆ
make optcarrot 2>&1 | tail -3 # checksum 59662 ็ถญๆ
# promote mode ้ฒๆ
rm -rf build/test-results/
SPINEL_INT_OVERFLOW=promote make \
CFLAGS="-O2 -Wno-all -Wno-unknown-warning-option -Wno-alloc-size-larger-than -DSP_INT_OVERFLOW_MODE_PROMOTE" \
-j8 test 2>&1 | tail -2
SPINEL_INT_OVERFLOW=promote make \
CFLAGS="-O2 -Wno-all -Wno-unknown-warning-option -Wno-alloc-size-larger-than -DSP_INT_OVERFLOW_MODE_PROMOTE" \
-j8 bench 2>&1 | tail -2
# optcarrot single
SPINEL_INT_OVERFLOW=promote ./spinel --int-overflow=promote build/optcarrot-single.rb -o /tmp/op_p
/tmp/op_p
ๅนๆ้ไบๆณ (็ดฏ็ฉ)
| Phase | test | bench | optcarrot |
|---|---|---|---|
| ็พ็ถ | 557/52/22 | 36/7/14 | C compile fail |
| 1ๅฎไบ | ~580/45/15 | ~45/5/7 | PASS (checksum 59662) |
| 2ๅฎไบ | ~595/40/8 | ~52/3/2 | PASS |
| 3ๅฎไบ | ~610/15/4 | ~55/2/0 | PASS |
| 4ๅฎไบ | ~620/8/2 | ~56/1/0 | PASS |
| 5ๅฎไบ | ~625/5/0 | ~57/0/0 | PASS |
| 6ๅฎไบ | 631/0/0 | 57/0/0 | PASS |
| 7ๅฎไบ | 631/0/0 | 57/0/0 | PASS (Makefile clean) |
ๅทฅๆฐๆฆ็ฎ
- Phase 1 (bit-ops): 2-4 hours
- Phase 2 (containers): 1-2 hours
- Phase 3 (call args): 1-2 hours
- Phase 4 (return/slot): 0.5-1 hour
- Phase 5 (string conv): 0.5-1 hour
- Phase 6 (ๅๅฅ test): 2-4 hours (varies)
- Phase 7 (bench + Makefile): 1-2 hours
ๅ่จ: 8-16 hours focused work
้ฒใๆนใฎๆณจๆ
- default ใๅฃใใชใ: ๅ commit ็ดๅพใซ
make test(default 631/0/0) +make optcarrot(wrap pinใ checksum 59662) ใๅใ - commit ใๅฐๅปใฟใซ: bucket 1 ใค โ 1 commit (memory
feedback_commit_often) - inline ้ขๆฐ vs macro:
sp_int_*ใฏ macroใ ๆฐ่ฆ helper ใๅใ pattern ใง (memoryfeedback_promote_mode_inline_pitfall) - stale cache ๆณจๆ: promote_int_to_bigint_globally ๅพใฎ cache invalidation ๆผใใซ่ญฆๆ
- ่จ้ฒ: ๅ phase ใฎ commit ๅพใ ๆฎใ errors / fails ใฎๆฐใ memo ใใฆ้ฒๆใใฉใใฏ
Risks
- optcarrot ใฏ --int-overflow=wrap ใๆ้: promote ใ ใจ bigint helper call overhead ใง fps ไฝไธใไบๆณใใใใ Makefile ใฎใใใฉใซใใฏ wrap ใฎใพใพใซใใ (promote ใฏ opt-in mode ใจใใ่จญ่จใซๆฒฟใ)
- bigint memory pressure: ๅ จ int slot ใ heap-allocated bigint ใซใชใ โ GC ๅงใจ allocator churnใ ๆขๅญ GC ใงๅฏพๅฟใงใใใๆธฌๅฎ่ฆ
- ๆขๅญ default test ใฎ non-determinism: ไธๅคใชใฏใใ ใใ stale cache invalidation ็ต็ฑใง็จใซ regression ใๅบใๅฏ่ฝๆงใใใ ๆฏ commit ใง default test ๅฟ ้
- ๆฐ helper ใฎ signedness: GMP ใฎ
mpz_and็ญใฏ arbitrary-precision ใง signed ่ช็ถใตใใผใใ spinel ๅดใง signedness ็ถญๆ็ขบ่ช
้ๅง phase
Phase 1 (bit-ops) ใๆๅชๅ ใ optcarrot ใ unblock ใใ ๅฝฑ้ฟใๆใๅคงใใใ ็ๆๅพใ ๅ helper ใ 1 ใคใใค่ฟฝๅ โ optcarrot ใงๅไฝ็ขบ่ช โ commitใ