- RoutingDecision の missing_caps を Vec<CapabilityTag> に変更(型安全化) - error_tags は to_tag() メソッドで自動生成 - 全 callsite を enum variant に修正 - capability_tags モジュール(文字列定数群)を完全削除 - 全テスト PASS(型安全性向上を確認) - フォーマット適用
133 lines
4.6 KiB
Rust
133 lines
4.6 KiB
Rust
//! Capability Guard - Fail-Fast Reasons and Routing Decisions
|
|
//!
|
|
//! This module defines the vocabulary for pattern selection and failure reasons.
|
|
//! It provides standardized capability tags and routing decision structures.
|
|
|
|
use crate::mir::loop_pattern_detection::LoopPatternKind;
|
|
|
|
// ============================================================================
|
|
// Routing Decision
|
|
// ============================================================================
|
|
|
|
/// Routing decision - The result of pattern selection
|
|
///
|
|
/// This contains both the chosen pattern (if any) and detailed
|
|
/// diagnostic information about why other patterns were rejected.
|
|
#[derive(Debug, Clone)]
|
|
pub struct RoutingDecision {
|
|
/// Selected pattern (None = Fail-Fast)
|
|
pub chosen: Option<LoopPatternKind>,
|
|
|
|
/// Missing capabilities that prevented other patterns (type-safe!)
|
|
pub missing_caps: Vec<CapabilityTag>,
|
|
|
|
/// Selection reasoning (for debugging)
|
|
pub notes: Vec<String>,
|
|
|
|
/// Error tags for contract_checks integration
|
|
pub error_tags: Vec<String>,
|
|
}
|
|
|
|
impl RoutingDecision {
|
|
/// Create a successful routing decision
|
|
pub fn success(pattern: LoopPatternKind) -> Self {
|
|
Self {
|
|
chosen: Some(pattern),
|
|
missing_caps: Vec::new(),
|
|
notes: Vec::new(),
|
|
error_tags: Vec::new(),
|
|
}
|
|
}
|
|
|
|
/// Create a failed routing decision (Fail-Fast)
|
|
pub fn fail_fast(missing_caps: Vec<CapabilityTag>, reason: String) -> Self {
|
|
let error_tags = missing_caps
|
|
.iter()
|
|
.map(|cap| cap.to_tag().to_string())
|
|
.collect();
|
|
|
|
Self {
|
|
chosen: None,
|
|
missing_caps,
|
|
notes: vec![reason.clone()],
|
|
error_tags,
|
|
}
|
|
}
|
|
|
|
/// Add a diagnostic note
|
|
pub fn add_note(&mut self, note: String) {
|
|
self.notes.push(note);
|
|
}
|
|
|
|
/// Check if routing succeeded
|
|
pub fn is_success(&self) -> bool {
|
|
self.chosen.is_some()
|
|
}
|
|
|
|
/// Check if routing failed
|
|
pub fn is_fail_fast(&self) -> bool {
|
|
self.chosen.is_none()
|
|
}
|
|
}
|
|
|
|
// ============================================================================
|
|
// Capability Tags (Type-Safe Enum)
|
|
// ============================================================================
|
|
|
|
/// Capability tag - Type-safe vocabulary for pattern requirements
|
|
///
|
|
/// Each tag represents a specific capability that a loop pattern requires.
|
|
/// Using an enum (instead of string constants) provides:
|
|
/// - Compile-time error detection for typos
|
|
/// - IDE auto-completion
|
|
/// - Exhaustiveness checking in match expressions
|
|
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
|
pub enum CapabilityTag {
|
|
/// Requires: Carrier update is constant step (i = i + const)
|
|
ConstStep,
|
|
/// Requires: Single break point only
|
|
SingleBreak,
|
|
/// Requires: Single continue point only
|
|
SingleContinue,
|
|
/// Requires: Pure header condition (no side effects)
|
|
PureHeader,
|
|
/// Requires: Outer local condition variable
|
|
OuterLocalCond,
|
|
/// Requires: Complete exit bindings
|
|
ExitBindings,
|
|
/// Requires: Carrier promotion support
|
|
CarrierPromotion,
|
|
/// Requires: Consistent break value types
|
|
BreakValueType,
|
|
}
|
|
|
|
impl CapabilityTag {
|
|
/// Error message tag for contract_checks integration
|
|
pub fn to_tag(&self) -> &'static str {
|
|
match self {
|
|
Self::ConstStep => "CAP_MISSING_CONST_STEP",
|
|
Self::SingleBreak => "CAP_MISSING_SINGLE_BREAK",
|
|
Self::SingleContinue => "CAP_MISSING_SINGLE_CONTINUE",
|
|
Self::PureHeader => "CAP_MISSING_PURE_HEADER",
|
|
Self::OuterLocalCond => "CAP_MISSING_OUTER_LOCAL_COND",
|
|
Self::ExitBindings => "CAP_MISSING_EXIT_BINDINGS",
|
|
Self::CarrierPromotion => "CAP_MISSING_CARRIER_PROMOTION",
|
|
Self::BreakValueType => "CAP_MISSING_BREAK_VALUE_TYPE",
|
|
}
|
|
}
|
|
|
|
/// Human-readable description
|
|
pub fn description(&self) -> &'static str {
|
|
match self {
|
|
Self::ConstStep => "Carrier update is constant step (i = i + const)",
|
|
Self::SingleBreak => "break statement appears in single location only",
|
|
Self::SingleContinue => "continue statement appears in single location only",
|
|
Self::PureHeader => "Loop header condition has no side effects",
|
|
Self::OuterLocalCond => "Condition variable is defined in outer scope",
|
|
Self::ExitBindings => "Exit bindings are complete (no missing values)",
|
|
Self::CarrierPromotion => "LoopBodyLocal can be promoted to carrier",
|
|
Self::BreakValueType => "break value types are consistent across all branches",
|
|
}
|
|
}
|
|
}
|