Remove Trio boxes and tidy loop scope warnings

This commit is contained in:
nyash-codex
2025-11-30 11:46:14 +09:00
parent ea120dc9b1
commit 2ea0f2a202
18 changed files with 294 additions and 1765 deletions

View File

@ -3,7 +3,7 @@
//! 制約(必読):
//! - 条件式の中身を解析しないCompare/BinOp を MIR そのままコピーするだけ)
//! - 多重ヘッダ/ネストループは対象外v1 は minimal_ssa_skip_ws の単純ループ専用)
//! - pinned/carrier/exit は LoopVarClassBox / LoopExitLivenessBox から渡された前提で扱う
//! - pinned/carrier/exit は LoopScopeShape から渡された前提で扱う
//! - 解析に失敗したら必ず None を返し、呼び元にフォールバックさせる
use std::collections::BTreeMap;

View File

@ -4,9 +4,10 @@
//! - LoopForm + MirQuery + MirFunction から、JoinIR 降下に必要な情報を抽出する。
//! - pinned/carrier 推定と ValueId マッピング、header/exit スナップショット収集を一元化。
//! - generic_case_a/B など複数ロワーで再利用するための「入口箱」だよ。
//!
//! Phase 70-1: Trio (LocalScopeInspectorBox, LoopVarClassBox) 依存削除
//! - 変数分類は LoopScopeShape::from_loop_form() に一本化(二重分類問題解消)
use crate::mir::phi_core::local_scope_inspector::LocalScopeInspectorBox;
use crate::mir::phi_core::loop_var_classifier::{LoopVarClass, LoopVarClassBox};
use crate::mir::{BasicBlockId, MirFunction, MirInstruction, MirQuery, ValueId};
use std::collections::{BTreeMap, BTreeSet};
@ -21,10 +22,12 @@ pub(crate) struct LoopFormIntake {
/// LoopForm + MIR から pinned/carrier とスナップショットを抽出する。
///
/// Phase 70-1: var_classes 引数削除Trio 依存排除)
/// 実際の変数分類は呼び出し側が LoopScopeShape::from_loop_form() で実施
///
/// 失敗時は Noneフォールバック用
pub(crate) fn intake_loop_form(
loop_form: &crate::mir::loop_form::LoopForm,
var_classes: &LoopVarClassBox,
query: &impl MirQuery,
mir_func: &MirFunction,
) -> Option<LoopFormIntake> {
@ -165,36 +168,10 @@ pub(crate) fn intake_loop_form(
}
}
// LocalScopeInspector に snapshot を登録して VarClass 判定の土台を整える
let mut inspector = LocalScopeInspectorBox::new();
inspector.record_snapshot(loop_form.header, &header_vals_mir);
for (bb, snap) in &exit_snapshots {
inspector.record_snapshot(*bb, snap);
}
let all_names: Vec<String> = header_vals_mir.keys().cloned().collect();
let classified = var_classes.classify_all(
&all_names,
&pinned_hint,
&carrier_hint,
&inspector,
&exit_preds,
);
let ordered_pinned: Vec<String> = classified
.iter()
.filter(|(_, c)| matches!(c, LoopVarClass::Pinned))
.map(|(n, _)| n.clone())
.collect::<BTreeSet<_>>()
.into_iter()
.collect();
let ordered_carriers: Vec<String> = classified
.iter()
.filter(|(_, c)| matches!(c, LoopVarClass::Carrier))
.map(|(n, _)| n.clone())
.collect::<BTreeSet<_>>()
.into_iter()
.collect();
// Phase 70-1: Trio 分類を削除し、pinned_hint/carrier_hint をそのまま返す
// 実際の分類は LoopScopeShape::from_loop_form() 内部で実施される(二重分類問題解消)
let ordered_pinned: Vec<String> = pinned_hint.into_iter().collect::<BTreeSet<_>>().into_iter().collect();
let ordered_carriers: Vec<String> = carrier_hint.into_iter().collect::<BTreeSet<_>>().into_iter().collect();
if ordered_pinned.is_empty() || ordered_carriers.is_empty() {
return None;

View File

@ -3,94 +3,44 @@
//! LoopForm / 既存箱から LoopScopeShape を構築し、Case-A minimal ターゲットは
//! analyze_case_a パスにルーティングする。
//!
//! # Phase 48-6: Trio 依存の境界
//!
//! このファイルは **唯一 TrioLoopVarClassBox/LoopExitLivenessBox/LocalScopeInspectorBox
//! 知らないといけない層** として設計されている。
//!
//! ## Trio が表に出る箇所(意図的に許容)
//!
//! 1. **builder.rs**(このファイル): from_existing_boxes_legacy とその helper 関数
//! 2. **phi_core/* 自身**: Trio の実装ファイル(保持)
//! 3. **legacy bridge**: json_v0_bridge/lowering/loop_.rsPhase 62+ で段階廃止)
//! 4. **テスト**: loop_scope_shape/tests.rs, loop_form_intake.rs検証用
//!
//! ## 外部からの利用
//!
//! 外部JoinIR lowering, LoopToJoinLowerer 等)は **LoopScopeShape の API のみ** を使用し、
//! Trio の存在を知らない設計になっているPhase 48-2/48-4 完了)。
//! Trio legacy boxes は完全に除去済み。
//! LoopForm / LoopFormIntake から LoopScopeShape を構築し、変数分類と定義位置を
//! LoopScopeShape の内部に閉じ込める。
use std::collections::{BTreeMap, BTreeSet};
use crate::mir::control_form::LoopId;
use crate::mir::join_ir::lowering::loop_form_intake::LoopFormIntake;
use crate::mir::loop_form::LoopForm;
// Phase 48-6: Trio 依存builder.rs のみが知る層)
use crate::mir::phi_core::local_scope_inspector::LocalScopeInspectorBox;
use crate::mir::phi_core::loop_exit_liveness::LoopExitLivenessBox;
use crate::mir::phi_core::loop_var_classifier::{LoopVarClass, LoopVarClassBox};
use crate::mir::{BasicBlockId, MirQuery};
use super::case_a::{is_case_a_minimal_target, validate_case_a_structural};
use super::shape::LoopScopeShape;
use super::shape::{LoopScopeShape, LoopVarClass};
impl LoopScopeShape {
/// Case-A ルーティング込みで LoopScopeShape を構築
pub(crate) fn from_existing_boxes(
pub(crate) fn from_loop_form(
loop_form: &LoopForm,
intake: &LoopFormIntake,
var_classes: &LoopVarClassBox,
exit_live_box: &LoopExitLivenessBox,
query: &impl MirQuery,
_query: &impl MirQuery,
func_name: Option<&str>,
) -> Option<Self> {
if let Some(name) = func_name {
if is_case_a_minimal_target(name) {
return Self::analyze_case_a(
loop_form,
intake,
var_classes,
exit_live_box,
query,
name,
);
return Self::analyze_case_a(loop_form, intake, name);
}
}
Self::from_existing_boxes_legacy(loop_form, intake, var_classes, exit_live_box, query)
}
/// Trio 引数なしで LoopScopeShape を構築Trio 内部化)
pub(crate) fn from_loop_form(
loop_form: &LoopForm,
intake: &LoopFormIntake,
query: &impl MirQuery,
func_name: Option<&str>,
) -> Option<Self> {
let var_classes = LoopVarClassBox::new();
let exit_live_box = LoopExitLivenessBox::new();
Self::from_existing_boxes(
loop_form,
intake,
&var_classes,
&exit_live_box,
query,
func_name,
)
Self::build_from_intake(loop_form, intake)
}
/// Case-A minimal 用の解析パスPhase 48-5: 構造判定検証追加)
fn analyze_case_a(
loop_form: &LoopForm,
intake: &LoopFormIntake,
var_classes: &LoopVarClassBox,
exit_live_box: &LoopExitLivenessBox,
query: &impl MirQuery,
func_name: &str,
) -> Option<Self> {
let result =
Self::from_existing_boxes_legacy(loop_form, intake, var_classes, exit_live_box, query)?;
let result = Self::build_from_intake(loop_form, intake)?;
// Phase 48-5: 構造判定検証(警告のみ、将来的に厳格化)
validate_case_a_structural(loop_form, &result, func_name);
@ -108,25 +58,9 @@ impl LoopScopeShape {
Some(result)
}
/// 既存箱ベースの従来実装Case-A 以外のループで使用)
///
/// # Phase 48-6: Trio を知らないといけない唯一の層
///
/// この関数は **TrioLoopVarClassBox/LoopExitLivenessBox/LocalScopeInspectorBox
/// 直接受け取り、LoopScopeShape に変換する責務** を持つ。
///
/// - **外部からは呼ばれない**: from_loop_form() が Trio を内部生成して隠蔽Phase 48-2
/// - **Legacy bridge のみ**: json_v0_bridge/lowering/loop_.rs が直接呼ぶPhase 62+ 廃止予定)
/// - **helper 関数**: 下記3関数も Trio を使用(このファイル内でのみ可視)
/// - build_inspector(): LocalScopeInspectorBox 構築
/// - classify_body_and_exit(): LoopVarClassBox 使用
/// - merge_exit_live_from_box(): LoopExitLivenessBox 使用
fn from_existing_boxes_legacy(
fn build_from_intake(
loop_form: &LoopForm,
intake: &LoopFormIntake,
var_classes: &LoopVarClassBox,
exit_live_box: &LoopExitLivenessBox,
query: &impl MirQuery,
) -> Option<Self> {
let layout = block_layout(loop_form);
@ -145,18 +79,16 @@ impl LoopScopeShape {
let pinned: BTreeSet<String> = intake.pinned_ordered.iter().cloned().collect();
let carriers: BTreeSet<String> = intake.carrier_ordered.iter().cloned().collect();
let inspector = build_inspector(intake, layout.exit);
let (body_locals, mut exit_live) =
classify_body_and_exit(var_classes, intake, &inspector, &layout);
let exit_live_from_box =
merge_exit_live_from_box(exit_live_box, query, intake, layout.exit);
for name in exit_live_from_box {
exit_live.insert(name);
}
let variable_definitions = collect_variable_definitions(intake, &layout);
let (body_locals, exit_live) = classify_body_and_exit(
intake,
&pinned,
&carriers,
&variable_definitions,
&layout,
);
let progress_carrier = carriers.iter().next().cloned();
let variable_definitions = extract_variable_definitions(&inspector);
Some(Self {
header: layout.header,
@ -199,43 +131,61 @@ fn block_layout(loop_form: &LoopForm) -> LoopBlockLayout {
}
}
/// Phase 48-6: Trio 依存 helperLocalScopeInspectorBox 構築)
///
/// LocalScopeInspectorBox に header/exit snapshot を登録して変数定義解析の土台を作る。
/// この関数は from_existing_boxes_legacy からのみ呼ばれ、Trio を直接扱う。
fn build_inspector(intake: &LoopFormIntake, exit: BasicBlockId) -> LocalScopeInspectorBox {
let mut inspector = LocalScopeInspectorBox::new();
inspector.record_snapshot(exit, &intake.header_snapshot);
for (bb, snap) in &intake.exit_snapshots {
inspector.record_snapshot(*bb, snap);
fn collect_variable_definitions(
intake: &LoopFormIntake,
layout: &LoopBlockLayout,
) -> BTreeMap<String, BTreeSet<BasicBlockId>> {
let mut var_defs: BTreeMap<String, BTreeSet<BasicBlockId>> = BTreeMap::new();
for var_name in intake.header_snapshot.keys() {
var_defs
.entry(var_name.clone())
.or_default()
.insert(layout.exit);
var_defs
.entry(var_name.clone())
.or_default()
.insert(layout.header);
}
inspector
for (bb, snap) in &intake.exit_snapshots {
for var_name in snap.keys() {
var_defs
.entry(var_name.clone())
.or_default()
.insert(*bb);
}
}
var_defs
}
/// Phase 48-6: Trio 依存 helperLoopVarClassBox による変数分類)
///
/// LoopVarClassBox::classify_all() を呼び出して変数を 4分類し、
/// body_locals と exit_live に振り分ける。
/// この関数は from_existing_boxes_legacy からのみ呼ばれ、Trio を直接扱う。
fn classify_body_and_exit(
var_classes: &LoopVarClassBox,
intake: &LoopFormIntake,
inspector: &LocalScopeInspectorBox,
pinned: &BTreeSet<String>,
carriers: &BTreeSet<String>,
variable_definitions: &BTreeMap<String, BTreeSet<BasicBlockId>>,
layout: &LoopBlockLayout,
) -> (BTreeSet<String>, BTreeSet<String>) {
let all_names: Vec<String> = intake.header_snapshot.keys().cloned().collect();
let classified = var_classes.classify_all(
&all_names,
&intake.pinned_ordered,
&intake.carrier_ordered,
inspector,
&intake.exit_preds,
);
let mut body_locals: BTreeSet<String> = BTreeSet::new();
let mut exit_live: BTreeSet<String> = BTreeSet::new();
for (name, class) in &classified {
let mut all_names: BTreeSet<String> = intake.header_snapshot.keys().cloned().collect();
for (_, snap) in &intake.exit_snapshots {
all_names.extend(snap.keys().cloned());
}
all_names.extend(pinned.iter().cloned());
all_names.extend(carriers.iter().cloned());
for name in all_names {
let class = classify_var(
&name,
pinned,
carriers,
&intake.exit_preds,
variable_definitions,
);
match class {
LoopVarClass::Pinned | LoopVarClass::Carrier => {
exit_live.insert(name.clone());
@ -263,40 +213,42 @@ fn classify_body_and_exit(
(body_locals, exit_live)
}
/// Phase 48-6: Trio 依存 helperLoopExitLivenessBox による exit_live 計算)
///
/// LoopExitLivenessBox::compute_live_at_exit() を呼び出して、
/// ループ終了時に live な変数集合を取得する。
/// この関数は from_existing_boxes_legacy からのみ呼ばれ、Trio を直接扱う。
fn merge_exit_live_from_box(
exit_live_box: &LoopExitLivenessBox,
query: &impl MirQuery,
intake: &LoopFormIntake,
exit_block: BasicBlockId,
) -> BTreeSet<String> {
exit_live_box.compute_live_at_exit(
query,
exit_block,
&intake.header_snapshot,
&intake.exit_snapshots,
)
fn classify_var(
var_name: &str,
pinned: &BTreeSet<String>,
carriers: &BTreeSet<String>,
exit_preds: &[BasicBlockId],
variable_definitions: &BTreeMap<String, BTreeSet<BasicBlockId>>,
) -> LoopVarClass {
if var_name.starts_with("__pin$") && var_name.contains("$@") {
return LoopVarClass::BodyLocalInternal;
}
if pinned.contains(var_name) {
return LoopVarClass::Pinned;
}
if carriers.contains(var_name) {
return LoopVarClass::Carrier;
}
if is_available_in_all(var_name, exit_preds, variable_definitions) {
LoopVarClass::BodyLocalExit
} else {
LoopVarClass::BodyLocalInternal
}
}
/// Phase 48-4: LocalScopeInspectorBox から variable_definitions を抽出
///
/// inspector.all_variables() と get_defining_blocks() を使って、
/// 変数名 → 定義ブロック集合のマッピングを構築する。
/// この関数は from_existing_boxes_legacy からのみ呼ばれ、Trio を直接扱う。
fn extract_variable_definitions(
inspector: &LocalScopeInspectorBox,
) -> BTreeMap<String, BTreeSet<BasicBlockId>> {
let mut var_defs = BTreeMap::new();
for var_name in inspector.all_variables() {
let blocks: BTreeSet<BasicBlockId> = inspector
.get_defining_blocks(&var_name)
.into_iter()
.collect();
var_defs.insert(var_name, blocks);
fn is_available_in_all(
var_name: &str,
required_blocks: &[BasicBlockId],
variable_definitions: &BTreeMap<String, BTreeSet<BasicBlockId>>,
) -> bool {
if let Some(defining_blocks) = variable_definitions.get(var_name) {
required_blocks
.iter()
.all(|block| defining_blocks.contains(block))
} else {
false
}
var_defs
}

View File

@ -16,7 +16,6 @@ mod structural;
pub(crate) use case_a::is_case_a_minimal_target;
pub(crate) use context::CaseAContext;
pub(crate) use shape::LoopScopeShape;
pub(crate) use structural::LoopStructuralAnalysis;
#[cfg(test)]
mod tests;

View File

@ -4,9 +4,30 @@
use std::collections::{BTreeMap, BTreeSet};
use crate::mir::phi_core::loop_var_classifier::LoopVarClass;
use crate::mir::BasicBlockId;
/// Variable classification for loop PHI generation.
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum LoopVarClass {
Pinned,
Carrier,
BodyLocalExit,
BodyLocalInternal,
}
impl LoopVarClass {
#[cfg(test)]
pub fn needs_exit_phi(self) -> bool {
matches!(self, LoopVarClass::Pinned | LoopVarClass::Carrier | LoopVarClass::BodyLocalExit)
}
#[cfg(test)]
pub fn needs_header_phi(self) -> bool {
matches!(self, LoopVarClass::Pinned | LoopVarClass::Carrier)
}
}
/// ループ変数スコープの統合ビュー
///
/// ## 4分類の定義
@ -32,7 +53,7 @@ use crate::mir::BasicBlockId;
/// - Block IDs: `header`, `body`, `latch`, `exit`
/// - Variable classification: `pinned`, `carriers`, `body_locals`, `exit_live`
/// - `progress_carrier`: 進捗チェック用(将来の Verifier で使用予定)
/// - `variable_definitions`: LocalScopeInspectorBox 情報統合予定Phase 48-5+
/// - `variable_definitions`: definition blocks collected from LoopFormIntake snapshots
#[derive(Debug, Clone)]
#[allow(dead_code)] // Block IDs and progress_carrier are reserved for future F-3/F-4 use
pub(crate) struct LoopScopeShape {
@ -50,12 +71,13 @@ pub(crate) struct LoopScopeShape {
impl LoopScopeShape {
/// header PHI が必要か判定
#[allow(dead_code)] // Phase 30: will be used in F-3 generic lowering
#[cfg(test)]
pub fn needs_header_phi(&self, var_name: &str) -> bool {
self.pinned.contains(var_name) || self.carriers.contains(var_name)
}
/// exit PHI が必要か判定
#[cfg(test)]
pub fn needs_exit_phi(&self, var_name: &str) -> bool {
self.exit_live.contains(var_name)
}
@ -70,21 +92,8 @@ impl LoopScopeShape {
self.carriers.iter().cloned().collect()
}
/// header PHI 対象pinned + carriers
#[allow(dead_code)] // Phase 30: will be used in F-3 generic lowering
pub fn header_phi_vars(&self) -> Vec<String> {
let mut result: Vec<String> = self.pinned.iter().cloned().collect();
result.extend(self.carriers.iter().cloned());
result
}
/// exit PHI 対象
#[allow(dead_code)] // Phase 30: will be used in F-3 generic lowering
pub fn exit_phi_vars(&self) -> Vec<String> {
self.exit_live.iter().cloned().collect()
}
/// 変数を4分類
#[cfg(test)]
pub fn classify(&self, var_name: &str) -> LoopVarClass {
if self.pinned.contains(var_name) {
return LoopVarClass::Pinned;
@ -105,20 +114,14 @@ impl LoopScopeShape {
}
}
/// 複数変数を一括分類
pub fn classify_all(&self, var_names: &[String]) -> Vec<(String, LoopVarClass)> {
var_names
.iter()
.map(|name| (name.clone(), self.classify(name)))
.collect()
}
/// ループ終了時に live な変数集合を返す
#[cfg(test)]
pub fn get_exit_live(&self) -> &BTreeSet<String> {
&self.exit_live
}
/// 変数が required_blocks すべてで利用可能か判定
#[cfg(test)]
pub fn is_available_in_all(&self, var_name: &str, required_blocks: &[BasicBlockId]) -> bool {
if let Some(def_blocks) = self.variable_definitions.get(var_name) {
required_blocks.iter().all(|bid| def_blocks.contains(bid))

View File

@ -108,7 +108,7 @@ impl LoopStructuralAnalysis {
mod tests {
use super::*;
use crate::mir::control_form::{ExitEdge, ExitKind, LoopId};
use crate::mir::{BasicBlockId, ValueId};
use crate::mir::BasicBlockId;
use std::collections::{BTreeMap, BTreeSet};
fn make_single_exit_analysis() -> ExitAnalysis {

View File

@ -1,7 +1,6 @@
use super::*;
use crate::mir::join_ir::lowering::loop_form_intake::LoopFormIntake;
use crate::mir::phi_core::loop_exit_liveness::LoopExitLivenessBox;
use crate::mir::phi_core::loop_var_classifier::{LoopVarClass, LoopVarClassBox};
use super::shape::LoopVarClass;
use crate::mir::{BasicBlockId, MirQuery, ValueId};
use std::collections::{BTreeMap, BTreeSet};
@ -49,21 +48,12 @@ impl MirQuery for EmptyQuery {
}
#[test]
fn test_from_existing_boxes_basic() {
fn test_from_loop_form_basic() {
let loop_form = make_dummy_loop_form();
let intake = make_dummy_intake();
let var_classes = LoopVarClassBox::new();
let exit_live_box = LoopExitLivenessBox::new();
let query = EmptyQuery;
let scope = LoopScopeShape::from_existing_boxes(
&loop_form,
&intake,
&var_classes,
&exit_live_box,
&query,
None,
);
let scope = LoopScopeShape::from_loop_form(&loop_form, &intake, &query, None);
assert!(scope.is_some());
let scope = scope.unwrap();
@ -87,19 +77,9 @@ fn test_from_existing_boxes_basic() {
fn test_needs_header_phi() {
let loop_form = make_dummy_loop_form();
let intake = make_dummy_intake();
let var_classes = LoopVarClassBox::new();
let exit_live_box = LoopExitLivenessBox::new();
let query = EmptyQuery;
let scope = LoopScopeShape::from_existing_boxes(
&loop_form,
&intake,
&var_classes,
&exit_live_box,
&query,
None,
)
.unwrap();
let scope = LoopScopeShape::from_loop_form(&loop_form, &intake, &query, None).unwrap();
assert!(scope.needs_header_phi("s"));
assert!(scope.needs_header_phi("n"));
@ -111,19 +91,9 @@ fn test_needs_header_phi() {
fn test_needs_exit_phi() {
let loop_form = make_dummy_loop_form();
let intake = make_dummy_intake();
let var_classes = LoopVarClassBox::new();
let exit_live_box = LoopExitLivenessBox::new();
let query = EmptyQuery;
let scope = LoopScopeShape::from_existing_boxes(
&loop_form,
&intake,
&var_classes,
&exit_live_box,
&query,
None,
)
.unwrap();
let scope = LoopScopeShape::from_loop_form(&loop_form, &intake, &query, None).unwrap();
assert!(scope.needs_exit_phi("s"));
assert!(scope.needs_exit_phi("n"));
@ -134,19 +104,9 @@ fn test_needs_exit_phi() {
fn test_ordered_accessors() {
let loop_form = make_dummy_loop_form();
let intake = make_dummy_intake();
let var_classes = LoopVarClassBox::new();
let exit_live_box = LoopExitLivenessBox::new();
let query = EmptyQuery;
let scope = LoopScopeShape::from_existing_boxes(
&loop_form,
&intake,
&var_classes,
&exit_live_box,
&query,
None,
)
.unwrap();
let scope = LoopScopeShape::from_loop_form(&loop_form, &intake, &query, None).unwrap();
let pinned = scope.pinned_ordered();
assert_eq!(pinned.len(), 2);
@ -197,19 +157,9 @@ fn test_block_ids_preserved() {
};
let intake = make_dummy_intake();
let var_classes = LoopVarClassBox::new();
let exit_live_box = LoopExitLivenessBox::new();
let query = EmptyQuery;
let scope = LoopScopeShape::from_existing_boxes(
&loop_form,
&intake,
&var_classes,
&exit_live_box,
&query,
None,
)
.unwrap();
let scope = LoopScopeShape::from_loop_form(&loop_form, &intake, &query, None).unwrap();
assert_eq!(scope.header, BasicBlockId::new(200));
assert_eq!(scope.body, BasicBlockId::new(300));
@ -245,19 +195,9 @@ fn test_deterministic_order() {
fn test_needs_phi_consistency() {
let loop_form = make_dummy_loop_form();
let intake = make_dummy_intake();
let var_classes = LoopVarClassBox::new();
let exit_live_box = LoopExitLivenessBox::new();
let query = EmptyQuery;
let scope = LoopScopeShape::from_existing_boxes(
&loop_form,
&intake,
&var_classes,
&exit_live_box,
&query,
None,
)
.unwrap();
let scope = LoopScopeShape::from_loop_form(&loop_form, &intake, &query, None).unwrap();
for var in &scope.pinned {
assert!(
@ -458,7 +398,7 @@ fn test_is_available_in_all_phase48_5_future() {
assert!(!scope.is_available_in_all("unknown", &[BasicBlockId::new(3)]));
}
/// Phase 48-4: from_existing_boxes で variable_definitions が埋まることを確認
/// Phase 48-4: from_loop_form で variable_definitions が埋まることを確認
#[test]
fn test_variable_definitions_from_inspector() {
let loop_form = make_dummy_loop_form();
@ -481,19 +421,9 @@ fn test_variable_definitions_from_inspector() {
(BasicBlockId::new(11), exit2_snap),
];
let var_classes = LoopVarClassBox::new();
let exit_live_box = LoopExitLivenessBox::new();
let query = EmptyQuery;
let scope = LoopScopeShape::from_existing_boxes(
&loop_form,
&intake,
&var_classes,
&exit_live_box,
&query,
None,
)
.unwrap();
let scope = LoopScopeShape::from_loop_form(&loop_form, &intake, &query, None).unwrap();
// s, n, i は両方の exit で利用可能 → is_available_in_all should be true
assert!(scope.is_available_in_all("s", &[BasicBlockId::new(10), BasicBlockId::new(11)]));
@ -532,19 +462,9 @@ fn test_variable_definitions_partial_availability() {
(BasicBlockId::new(22), exit3_snap),
];
let var_classes = LoopVarClassBox::new();
let exit_live_box = LoopExitLivenessBox::new();
let query = EmptyQuery;
let scope = LoopScopeShape::from_existing_boxes(
&loop_form,
&intake,
&var_classes,
&exit_live_box,
&query,
None,
)
.unwrap();
let scope = LoopScopeShape::from_loop_form(&loop_form, &intake, &query, None).unwrap();
// s は全 exit で利用可能
assert!(scope.is_available_in_all(

View File

@ -98,8 +98,8 @@ impl LoopToJoinLowerer {
let query = MirQueryBox::new(func);
// Step 2: LoopFormIntake を構築
// Phase 48-2: intake_loop_form は空の var_classes を使用(将来は from_loop_form に統合
let intake = intake_loop_form(loop_form, &Default::default(), &query, func)?;
// Phase 70-2: var_classes 引数削除完了Trio 依存ゼロ
let intake = intake_loop_form(loop_form, &query, func)?;
// Step 3: LoopScopeShape を構築
// Phase 48-2: from_loop_form() で Trio を内部化LoopExitLivenessBox 依存削除)