diff --git a/src/mir/loop_canonicalizer/capability_guard.rs b/src/mir/loop_canonicalizer/capability_guard.rs index 10216e6b..f8aab126 100644 --- a/src/mir/loop_canonicalizer/capability_guard.rs +++ b/src/mir/loop_canonicalizer/capability_guard.rs @@ -66,17 +66,75 @@ impl RoutingDecision { } // ============================================================================ -// Capability Tags +// Capability Tags (Type-Safe Enum) // ============================================================================ -/// Capability tags - Standardized vocabulary for Fail-Fast reasons +/// Capability tag - Type-safe vocabulary for pattern requirements /// -/// These constants define the capabilities required by different patterns. -/// When a loop lacks a required capability, it uses the corresponding tag -/// to explain why it cannot be lowered by that pattern. +/// 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", + } + } +} + +// ============================================================================ +// Legacy Capability Tags (Deprecated - will be removed in Phase 139-P3-B) +// ============================================================================ + +/// Legacy capability tags - Standardized vocabulary for Fail-Fast reasons /// -/// NOTE: This module will be deprecated in Phase 139 in favor of the -/// CapabilityTag enum for type safety. +/// ⚠️ DEPRECATED: Use CapabilityTag enum instead for type safety. +/// This module will be removed in Phase 139-P3-B. +#[deprecated(since = "Phase 139-P3-A", note = "Use CapabilityTag enum instead")] pub mod capability_tags { /// Requires: Carrier update is constant step (`i = i + const`) pub const CAP_MISSING_CONST_STEP: &str = "CAP_MISSING_CONST_STEP";