refactor(pattern2): introduce PromoteDecision enum to eliminate Option wrapping ambiguity
Phase 263 P0.1: PromoteDecision API hardening
目的: Result<Option<PromoteStepResult>, String> の揺れを型で固定し、迷子をゼロに
Changes:
- promote_step_box.rs:
- PromoteDecision enum を導入(Promoted/NotApplicable/Freeze)
- PromoteStepBox::run() の戻り値を Result<PromoteDecision, String> に統一
- promote_and_prepare_carriers() が inputs の所有権を受け取り、PromoteDecision を直接構築
- Reject 分岐を型安全に二分化(文字列マッチング維持、型で意図を明確化)
- pattern2_lowering_orchestrator.rs:
- orchestrator 側の分岐を1箇所に固定(match PromoteDecision {...})
- NotApplicable → Ok(None) で後続経路へ
- Freeze → Err で Fail-Fast
受け入れ:
- quick smoke: 45/46 PASS ✅(悪化なし)
- NotApplicable は必ず Ok(None) で Pattern2全体を抜ける
- Freeze は必ず Err(fail-fast)
Next: ファイル構造リファクタリング(pattern2/api/ フォルダ化)を別フェーズで検討
This commit is contained in:
@ -62,15 +62,22 @@ impl Pattern2LoweringOrchestrator {
|
||||
let facts = GatherFactsStepBox::gather(builder, condition, body, fn_body, &ctx, verbose)?;
|
||||
let inputs = ApplyPolicyStepBox::apply(condition, body, facts)?;
|
||||
|
||||
let promoted = PromoteStepBox::run(builder, condition, body, inputs, debug, verbose)?;
|
||||
let mut inputs = match promoted {
|
||||
Some(result) => result.inputs,
|
||||
None => {
|
||||
// Phase 263 P0: Pattern2 cannot handle this loop (e.g., reassigned LoopBodyLocal)
|
||||
// Phase 263 P0.1: PromoteDecision で分岐を1箇所に固定(型安全)
|
||||
use super::pattern2_steps::promote_step_box::PromoteDecision;
|
||||
let mut inputs = match PromoteStepBox::run(builder, condition, body, inputs, debug, verbose)? {
|
||||
PromoteDecision::Promoted(result) => {
|
||||
result.inputs
|
||||
}
|
||||
PromoteDecision::NotApplicable => {
|
||||
// Pattern2 cannot handle this loop (e.g., reassigned LoopBodyLocal)
|
||||
// Return Ok(None) to allow router to try next path (legacy binding)
|
||||
super::super::trace::trace().debug("pattern2", "Pattern2 aborted (promotion failed), allowing fallback");
|
||||
super::super::trace::trace().debug("pattern2", "Pattern2 aborted (not applicable), allowing fallback");
|
||||
return Ok(None);
|
||||
}
|
||||
PromoteDecision::Freeze(reason) => {
|
||||
// Pattern2 should handle this but implementation is missing → Fail-Fast
|
||||
return Err(reason);
|
||||
}
|
||||
};
|
||||
|
||||
// Phase 256.5: Wire current_static_box_name from builder context or function name
|
||||
|
||||
@ -16,6 +16,22 @@ pub(crate) struct PromoteStepResult {
|
||||
pub inputs: Pattern2Inputs,
|
||||
}
|
||||
|
||||
/// Phase 263 P0.1: Promotion decision for Pattern2 LoopBodyLocal handling
|
||||
///
|
||||
/// Eliminates Option<_> wrapping ambiguity by making decision explicit.
|
||||
pub(crate) enum PromoteDecision {
|
||||
/// Promotion succeeded - Pattern2 can proceed
|
||||
Promoted(PromoteStepResult),
|
||||
|
||||
/// Pattern2 not applicable (e.g., reassigned LoopBodyLocal, no promotable pattern)
|
||||
/// → Router should try next path (legacy binding, etc.)
|
||||
NotApplicable,
|
||||
|
||||
/// Pattern2 should handle this but implementation is missing
|
||||
/// → Fail-Fast with error message
|
||||
Freeze(String),
|
||||
}
|
||||
|
||||
pub(crate) struct PromoteStepBox;
|
||||
|
||||
impl PromoteStepBox {
|
||||
@ -23,24 +39,22 @@ impl PromoteStepBox {
|
||||
builder: &mut MirBuilder,
|
||||
condition: &ASTNode,
|
||||
body: &[ASTNode],
|
||||
mut inputs: Pattern2Inputs,
|
||||
inputs: Pattern2Inputs,
|
||||
debug: bool,
|
||||
verbose: bool,
|
||||
) -> Result<Option<PromoteStepResult>, String> {
|
||||
match Self::promote_and_prepare_carriers(builder, condition, body, &mut inputs, debug, verbose)? {
|
||||
Some(()) => Ok(Some(PromoteStepResult { inputs })),
|
||||
None => Ok(None), // Pattern2 cannot handle this loop
|
||||
}
|
||||
) -> Result<PromoteDecision, String> {
|
||||
Self::promote_and_prepare_carriers(builder, condition, body, inputs, debug, verbose)
|
||||
}
|
||||
|
||||
pub(in crate::mir::builder) fn promote_and_prepare_carriers(
|
||||
builder: &mut MirBuilder,
|
||||
condition: &ASTNode,
|
||||
body: &[ASTNode],
|
||||
inputs: &mut Pattern2Inputs,
|
||||
inputs: Pattern2Inputs,
|
||||
debug: bool,
|
||||
verbose: bool,
|
||||
) -> Result<Option<()>, String> {
|
||||
) -> Result<PromoteDecision, String> {
|
||||
let mut inputs = inputs;
|
||||
use crate::mir::join_ir::lowering::digitpos_condition_normalizer::DigitPosConditionNormalizer;
|
||||
use crate::mir::loop_pattern_detection::loop_condition_scope::LoopConditionScopeBox;
|
||||
|
||||
@ -121,11 +135,11 @@ impl PromoteStepBox {
|
||||
inputs.read_only_body_local_slot = Some(slot);
|
||||
}
|
||||
PolicyDecision::Reject(reason) => {
|
||||
// Phase 263 P0 + Step 2.5: Reject を二分化
|
||||
// Phase 263 P0.1: Reject を PromoteDecision で二分化(型安全)
|
||||
if reason.contains("not_readonly")
|
||||
|| reason.contains("No promotable pattern detected")
|
||||
{
|
||||
// 対象外: Pattern2 で処理できない形 → Ok(None) で後続経路へ
|
||||
// 対象外: Pattern2 で処理できない形 → NotApplicable で後続経路へ
|
||||
#[cfg(debug_assertions)]
|
||||
{
|
||||
eprintln!(
|
||||
@ -133,13 +147,13 @@ impl PromoteStepBox {
|
||||
cond_body_local_vars, reason
|
||||
);
|
||||
}
|
||||
return Ok(None); // Pattern2 全体を中止
|
||||
return Ok(PromoteDecision::NotApplicable);
|
||||
} else {
|
||||
// 対象だが未対応(freeze級): 実装バグ or 将来実装予定 → Err で Fail-Fast
|
||||
return Err(format!(
|
||||
// 対象だが未対応(freeze級): 実装バグ or 将来実装予定 → Freeze で Fail-Fast
|
||||
return Ok(PromoteDecision::Freeze(format!(
|
||||
"[pattern2/promote_step] Pattern2 未対応エラー(LoopBodyLocal {:?}): {}",
|
||||
cond_body_local_vars, reason
|
||||
));
|
||||
)));
|
||||
}
|
||||
}
|
||||
PolicyDecision::None => {}
|
||||
@ -192,7 +206,7 @@ impl PromoteStepBox {
|
||||
}
|
||||
}
|
||||
|
||||
Ok(Some(()))
|
||||
Ok(PromoteDecision::Promoted(PromoteStepResult { inputs }))
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user