phase29af(p0): pattern2 boundary hygiene ssot
This commit is contained in:
@ -27,6 +27,14 @@
|
||||
- `CarrierInit::BoolConst(_)` / `CarrierInit::LoopLocalZero` -> host binding is skipped
|
||||
- ConditionOnly carriers must not use `FromHost`
|
||||
|
||||
## Boundary hygiene (Phase 29af)
|
||||
- Header PHI 対象: `carrier_info` の carriers(LoopState + ConditionOnly + LoopLocalZero)
|
||||
- Exit reconnection 対象: LoopState のみ(ConditionOnly は exit_bindings に入れない)
|
||||
- Host binding 対象: `CarrierInit::FromHost` のみ(BoolConst / LoopLocalZero は host slot 不要)
|
||||
- Fail-Fast: exit_bindings の `carrier_name` 重複は禁止(debug_assert)
|
||||
- Fail-Fast: `CarrierInit::FromHost` が `host_id=0` の場合は Err
|
||||
- SSOT: `docs/development/current/main/phases/phase-29af/README.md`
|
||||
|
||||
## Out of scope
|
||||
- multiple breaks / continue / return in the loop body
|
||||
- reassigned LoopBodyLocal outside the derived-slot shape
|
||||
|
||||
@ -66,7 +66,25 @@ impl EmitJoinIRStepBox {
|
||||
|
||||
let exit_meta = &fragment_meta.exit_meta;
|
||||
use crate::mir::builder::control_flow::joinir::merge::exit_line::ExitMetaCollector;
|
||||
let exit_bindings = ExitMetaCollector::collect(builder, exit_meta, Some(&inputs.carrier_info), debug);
|
||||
let mut exit_bindings =
|
||||
ExitMetaCollector::collect(builder, exit_meta, Some(&inputs.carrier_info), debug);
|
||||
// Phase 29af P0: Exit reconnection targets LoopState only.
|
||||
exit_bindings.retain(|binding| {
|
||||
binding.role == crate::mir::join_ir::lowering::carrier_info::CarrierRole::LoopState
|
||||
});
|
||||
// Phase 29af P0: Reject duplicate carrier_name in exit_bindings.
|
||||
#[cfg(debug_assertions)]
|
||||
{
|
||||
use std::collections::HashSet;
|
||||
let mut seen = HashSet::new();
|
||||
for binding in &exit_bindings {
|
||||
debug_assert!(
|
||||
seen.insert(&binding.carrier_name),
|
||||
"Phase 29af Fail-Fast: duplicate exit_binding carrier '{}'",
|
||||
binding.carrier_name
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// Phase 256.8.5: Use JoinModule.entry.params as SSOT (no hardcoded ValueIds)
|
||||
use super::super::common::get_entry_function;
|
||||
@ -78,7 +96,22 @@ impl EmitJoinIRStepBox {
|
||||
// Build host_input_values in same order (loop_var + carriers)
|
||||
let mut host_input_values = vec![inputs.loop_var_id];
|
||||
for carrier in inputs.carrier_info.carriers.iter() {
|
||||
host_input_values.push(carrier.host_id);
|
||||
use super::super::common::{decide_carrier_binding_policy, CarrierBindingPolicy};
|
||||
match decide_carrier_binding_policy(carrier) {
|
||||
CarrierBindingPolicy::BindFromHost => {
|
||||
if carrier.host_id == crate::mir::ValueId(0) {
|
||||
return Err(format!(
|
||||
"[emit_joinir] Phase 29af Fail-Fast: FromHost carrier '{}' has host_id=0",
|
||||
carrier.name
|
||||
));
|
||||
}
|
||||
host_input_values.push(carrier.host_id);
|
||||
}
|
||||
CarrierBindingPolicy::SkipBinding => {
|
||||
// Placeholder: SkipBinding does not require a host slot.
|
||||
host_input_values.push(crate::mir::ValueId(0));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Verify count consistency (fail-fast)
|
||||
|
||||
Reference in New Issue
Block a user