@@ -3576,13 +3576,16 @@ fn translate_to_native_jit(
35763576 && native_set_ty(ty, *dst, NativeTy::Int, c)
35773577 }
35783578 // Capturing-closure inline (OSR × J2): the closure operand is a
3579- // native handle; the materialized capture `dst` is an `Int`-class
3580- // register (the `closure_capture` helper returns scalar bits). A
3581- // body that uses the capture as a `Float` conflicts here ⇒ bail, so
3582- // only Int/Bool-class captures inline natively (Float deferred).
3583- RegInstr::NativeClosureCapture { dst, closure, .. } => {
3579+ // native handle; the materialized capture `dst` carries the
3580+ // capture's scalar bits (the `closure_capture` helper returns the
3581+ // raw i64 bit pattern: an `Int` directly, a `Bool` as 0/1, a
3582+ // `Float` reinterpreted via `f64::to_bits`). Leave `dst`'s class to
3583+ // flow from its uses — exactly like a `GetFieldSlot` read — so an
3584+ // Int/Bool capture stays Int-class and a Float capture becomes
3585+ // Float-class. Lowering admits only a provably Int/Bool/Float `dst`
3586+ // (and the Float arm bit-reinterprets the i64 slot to f64).
3587+ RegInstr::NativeClosureCapture { dst: _, closure, .. } => {
35843588 native_set_ty(ty, *closure, NativeTy::Handle, c)
3585- && native_set_ty(ty, *dst, NativeTy::Int, c)
35863589 }
35873590 _ => true,
35883591 };
@@ -3996,10 +3999,16 @@ fn translate_to_native_jit(
39963999 index,
39974000 } => {
39984001 // The closure handle is a native-readable handle; materialize
3999- // capture `index`'s scalar bits into the `Int`-class `dst` (the
4000- // inlined body's capture register). A non-scalar capture bails
4001- // out-of-band in the host helper.
4002- require(handle_reg(*closure) && int_or_free(*dst))?;
4002+ // capture `index`'s scalar bits into `dst` (the inlined body's
4003+ // capture register). `dst` may be Int/Bool (i64 used directly) or
4004+ // Float (the i64 slot is `f64::to_bits`, bit-reinterpreted to f64 in
4005+ // codegen); an unconstrained `dst` defaults to Int. A non-scalar
4006+ // (Handle/flat) `dst` bails. A non-scalar capture VALUE additionally
4007+ // bails out-of-band in the host helper at runtime.
4008+ require(
4009+ handle_reg(*closure)
4010+ && (int_or_free(*dst) || bool_ty(*dst) || float(*dst)),
4011+ )?;
40034012 let index = i64::try_from(*index).ok()?;
40044013 let index = u32::try_from(index).ok()?;
40054014 JitInstr::ClosureCapture {
@@ -4355,18 +4364,20 @@ fn translate_osr_loop(
43554364 }
43564365 // Synthetic closure-inline ops (only present when an inlined
43574366 // capturing/monomorphic closure body landed in the OSR region):
4358- // the closure operand is a native Handle param; an id read or a
4359- // materialized capture is `Int`-class.
4367+ // the closure operand is a native Handle param; an id read is
4368+ // `Int`-class. A materialized capture's `dst` is left to flow from
4369+ // its uses (Int/Bool/Float) — the helper returns the raw scalar bit
4370+ // pattern (a `Float` via `f64::to_bits`), and lowering admits only a
4371+ // provably Int/Bool/Float `dst`, bit-reinterpreting a Float slot.
43604372 RegInstr::NativeGuardClosureId { closure, .. } => {
43614373 native_set_ty(ty, *closure, NativeTy::Handle, c)
43624374 }
43634375 RegInstr::NativeClosureId { dst, closure } => {
43644376 native_set_ty(ty, *closure, NativeTy::Handle, c)
43654377 && native_set_ty(ty, *dst, NativeTy::Int, c)
43664378 }
4367- RegInstr::NativeClosureCapture { dst, closure, .. } => {
4379+ RegInstr::NativeClosureCapture { dst: _ , closure, .. } => {
43684380 native_set_ty(ty, *closure, NativeTy::Handle, c)
4369- && native_set_ty(ty, *dst, NativeTy::Int, c)
43704381 }
43714382 _ => true,
43724383 };
@@ -4552,7 +4563,14 @@ fn translate_osr_loop(
45524563 JitInstr::ClosureId { dst: r(*dst), base: r(*closure) }
45534564 }
45544565 RegInstr::NativeClosureCapture { dst, closure, index } => {
4555- require(handle_reg(*closure) && int_or_free(*dst))?;
4566+ // The capture's `dst` may be Int/Bool (i64 slot used directly) or
4567+ // Float (the i64 slot is `f64::to_bits`, bit-reinterpreted to f64
4568+ // in codegen). An unconstrained `dst` defaults to Int. A non-scalar
4569+ // `dst` (Handle/flat array) cannot hold a scalar capture ⇒ bail.
4570+ require(
4571+ handle_reg(*closure)
4572+ && (int_or_free(*dst) || bool_ty(*dst) || float(*dst)),
4573+ )?;
45564574 let index = u32::try_from(*index).ok()?;
45574575 JitInstr::ClosureCapture { dst: r(*dst), base: r(*closure), index }
45584576 }
0 commit comments