phase29af(p4): layout consistency fail-fast

This commit is contained in:
2025-12-29 05:59:01 +09:00
parent 87fbe6b950
commit 7d2967cfbf
10 changed files with 135 additions and 63 deletions

View File

@ -42,7 +42,4 @@ impl BoundaryCarrierLayout {
self.ordered_names.iter().position(|n| n == name)
}
pub fn len(&self) -> usize {
self.ordered_names.len()
}
}

View File

@ -38,17 +38,19 @@ pub(in crate::mir::builder::control_flow::joinir::merge) fn verify_boundary_hygi
}
if let Some(carrier_info) = &boundary.carrier_info {
let expected_len =
carrier_info.carriers.len() + if boundary.loop_var_name.is_some() { 1 } else { 0 };
let layout_len = BoundaryCarrierLayout::from_boundary(boundary).len();
if expected_len != layout_len {
let expected_names: Vec<&str> = std::iter::once(carrier_info.loop_var_name.as_str())
.chain(carrier_info.carriers.iter().map(|c| c.name.as_str()))
.collect();
let layout = BoundaryCarrierLayout::from_boundary(boundary);
let layout_names = layout.ordered_names();
if expected_names != layout_names {
return Err(error_tags::freeze_with_hint(
"phase29af/boundary_hygiene/layout_len",
"phase29af/boundary_hygiene/layout_order",
&format!(
"boundary carrier layout len {} does not match carrier_info len {}",
layout_len, expected_len
"boundary carrier order {:?} does not match carrier_info order {:?}",
layout_names, expected_names
),
"ensure loop_var + carriers ordering is consistent with carrier_info",
"ensure boundary carrier order matches carrier_info",
));
}

View File

@ -0,0 +1,39 @@
use crate::mir::builder::control_flow::joinir::merge::boundary_carrier_layout::BoundaryCarrierLayout;
use crate::mir::builder::control_flow::joinir::merge::loop_header_phi_info::LoopHeaderPhiInfo;
use crate::mir::join_ir::lowering::inline_boundary::JoinInlineBoundary;
/// Phase 29af P4: Verify boundary carrier order matches header PHI order.
pub(in crate::mir::builder::control_flow::joinir::merge) fn verify_header_phi_layout(
boundary: &JoinInlineBoundary,
loop_header_phi_info: &LoopHeaderPhiInfo,
) -> Result<(), String> {
use crate::mir::join_ir::lowering::error_tags;
let strict = crate::config::env::joinir_strict_enabled()
|| crate::config::env::joinir_dev_enabled();
if !strict {
return Ok(());
}
let boundary_layout = BoundaryCarrierLayout::from_boundary(boundary);
let boundary_names = boundary_layout.ordered_names();
let header_names: Vec<&str> = loop_header_phi_info
.carrier_order
.iter()
.map(|name| name.as_str())
.collect();
if boundary_names != header_names {
return Err(error_tags::freeze_with_hint(
"phase29af/layout/header_phi_order",
&format!(
"boundary carrier order {:?} does not match header PHI order {:?}",
boundary_names, header_names
),
"ensure boundary carrier layout matches header PHI construction order",
));
}
Ok(())
}

View File

@ -15,6 +15,7 @@ mod exit_bindings;
mod carrier_inputs;
mod boundary_creation;
mod boundary_hygiene;
mod header_phi_layout;
mod entry_params;
mod entry_like_policy;
@ -23,6 +24,7 @@ pub(super) use terminator_targets::verify_all_terminator_targets_exist;
pub(super) use exit_bindings::verify_exit_bindings_have_exit_phis;
pub(super) use carrier_inputs::verify_carrier_inputs_complete;
pub(super) use boundary_hygiene::verify_boundary_hygiene;
pub(super) use header_phi_layout::verify_header_phi_layout;
pub(super) use entry_like_policy::is_entry_like_source;
pub(in crate::mir::builder::control_flow::joinir) use boundary_creation::verify_boundary_contract_at_creation;
pub(in crate::mir::builder::control_flow::joinir) use entry_params::run_all_pipeline_checks;

View File

@ -224,6 +224,9 @@ pub(in crate::mir::builder) fn merge_joinir_mir_blocks(
&function_params,
debug,
)?;
if let Some(boundary) = boundary {
contract_checks::verify_header_phi_layout(boundary, &loop_header_phi_info)?;
}
// Phase 3: Remap ValueIds (with reserved PHI dsts protection)
// Phase 287 P0.2: Delegated to value_remapper module