dependency_injector/
error.rs

1//! Error types for dependency injection
2
3use std::any::TypeId;
4use thiserror::Error;
5
6/// Errors that can occur during dependency injection operations
7#[derive(Error, Debug)]
8pub enum DiError {
9    /// Service was not found in the container
10    #[error("Service not found: {type_name}")]
11    NotFound {
12        type_name: &'static str,
13        type_id: TypeId,
14    },
15
16    /// Circular dependency detected during resolution
17    #[error("Circular dependency detected while resolving: {type_name}")]
18    CircularDependency { type_name: &'static str },
19
20    /// Factory failed to create service
21    #[error("Failed to create service {type_name}: {reason}")]
22    CreationFailed {
23        type_name: &'static str,
24        reason: String,
25    },
26
27    /// Container is locked and cannot be modified
28    #[error("Container is locked - cannot register new services")]
29    Locked,
30
31    /// Attempted to register duplicate service
32    #[error("Service already registered: {type_name}")]
33    AlreadyRegistered { type_name: &'static str },
34
35    /// Parent scope was dropped
36    #[error("Parent scope has been dropped")]
37    ParentDropped,
38
39    /// Internal error
40    #[error("Internal DI error: {0}")]
41    Internal(String),
42}
43
44impl DiError {
45    /// Create a NotFound error for a type
46    #[inline]
47    pub fn not_found<T: 'static>() -> Self {
48        Self::NotFound {
49            type_name: std::any::type_name::<T>(),
50            type_id: TypeId::of::<T>(),
51        }
52    }
53
54    /// Create a CreationFailed error
55    #[inline]
56    pub fn creation_failed<T: 'static>(reason: impl Into<String>) -> Self {
57        Self::CreationFailed {
58            type_name: std::any::type_name::<T>(),
59            reason: reason.into(),
60        }
61    }
62
63    /// Create an AlreadyRegistered error
64    #[inline]
65    pub fn already_registered<T: 'static>() -> Self {
66        Self::AlreadyRegistered {
67            type_name: std::any::type_name::<T>(),
68        }
69    }
70
71    /// Create a CircularDependency error
72    #[inline]
73    pub fn circular<T: 'static>() -> Self {
74        Self::CircularDependency {
75            type_name: std::any::type_name::<T>(),
76        }
77    }
78}
79
80impl Clone for DiError {
81    fn clone(&self) -> Self {
82        match self {
83            Self::NotFound { type_name, type_id } => Self::NotFound {
84                type_name,
85                type_id: *type_id,
86            },
87            Self::CircularDependency { type_name } => Self::CircularDependency { type_name },
88            Self::CreationFailed { type_name, reason } => Self::CreationFailed {
89                type_name,
90                reason: reason.clone(),
91            },
92            Self::Locked => Self::Locked,
93            Self::AlreadyRegistered { type_name } => Self::AlreadyRegistered { type_name },
94            Self::ParentDropped => Self::ParentDropped,
95            Self::Internal(s) => Self::Internal(s.clone()),
96        }
97    }
98}
99
100/// Result type alias for DI operations
101pub type Result<T> = std::result::Result<T, DiError>;