Skip to main content

geam_core/plan/execution/host/
error.rs

1use crate::plan::FunctionType;
2use ecow::EcoString;
3use std::fmt;
4
5#[derive(Debug, Clone, PartialEq, Eq)]
6pub struct HostSpecializationError {
7    package: EcoString,
8    module: EcoString,
9    function: EcoString,
10    signature: FunctionType,
11    reason: HostSpecializationErrorReason,
12}
13
14#[derive(Debug, Clone, PartialEq, Eq)]
15pub enum HostSpecializationErrorReason {
16    UndeterminedReturnStorage,
17    UninhabitedCallbackArguments { callback: FunctionType },
18}
19
20impl HostSpecializationError {
21    pub(in crate::plan::execution) fn undetermined_return_storage(
22        package: EcoString,
23        module: EcoString,
24        function: EcoString,
25        signature: FunctionType,
26    ) -> Self {
27        Self {
28            package,
29            module,
30            function,
31            signature,
32            reason: HostSpecializationErrorReason::UndeterminedReturnStorage,
33        }
34    }
35
36    pub(in crate::plan::execution) fn uninhabited_callback_arguments(
37        package: EcoString,
38        module: EcoString,
39        function: EcoString,
40        signature: FunctionType,
41        callback: FunctionType,
42    ) -> Self {
43        Self {
44            package,
45            module,
46            function,
47            signature,
48            reason: HostSpecializationErrorReason::UninhabitedCallbackArguments { callback },
49        }
50    }
51
52    pub fn package(&self) -> &EcoString {
53        &self.package
54    }
55
56    pub fn module(&self) -> &EcoString {
57        &self.module
58    }
59
60    pub fn function(&self) -> &EcoString {
61        &self.function
62    }
63
64    pub fn signature(&self) -> &FunctionType {
65        &self.signature
66    }
67
68    pub fn reason(&self) -> &HostSpecializationErrorReason {
69        &self.reason
70    }
71}
72
73impl fmt::Display for HostSpecializationError {
74    fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
75        match &self.reason {
76            HostSpecializationErrorReason::UndeterminedReturnStorage => write!(
77                formatter,
78                "host function `{}::{}.{}` has an executable specialization `{:?}` whose successful return storage cannot be determined",
79                self.package, self.module, self.function, self.signature,
80            ),
81            HostSpecializationErrorReason::UninhabitedCallbackArguments { callback } => write!(
82                formatter,
83                "host function `{}::{}.{}` has an executable specialization `{:?}` that exposes callback `{:?}` with uninhabited arguments",
84                self.package, self.module, self.function, self.signature, callback,
85            ),
86        }
87    }
88}
89
90impl std::error::Error for HostSpecializationError {}
91
92#[cfg(test)]
93mod tests {
94    use super::{HostSpecializationError, HostSpecializationErrorReason};
95    use crate::{FunctionType, ValueType};
96
97    #[test]
98    fn exposes_the_undetermined_return_storage_specialization() {
99        let signature = FunctionType::new(
100            Vec::new(),
101            ValueType::Parameter(crate::plan::TypeParameterId(0)),
102        );
103        let error = HostSpecializationError::undetermined_return_storage(
104            "host_support".into(),
105            "host/generic".into(),
106            "produce".into(),
107            signature.clone(),
108        );
109
110        assert_eq!(error.package(), "host_support");
111        assert_eq!(error.module(), "host/generic");
112        assert_eq!(error.function(), "produce");
113        assert_eq!(error.signature(), &signature);
114        assert_eq!(
115            error.reason(),
116            &HostSpecializationErrorReason::UndeterminedReturnStorage,
117        );
118        assert_eq!(
119            error.to_string(),
120            "host function `host_support::host/generic.produce` has an executable specialization `FunctionType { arguments: [], return_: Parameter(TypeParameterId(0)) }` whose successful return storage cannot be determined",
121        );
122        assert_eq!(error.clone(), error);
123    }
124
125    #[test]
126    fn exposes_the_uninhabited_callback_specialization() {
127        let callback = FunctionType::new(
128            vec![ValueType::Parameter(crate::plan::TypeParameterId(0))],
129            ValueType::Int,
130        );
131        let signature = FunctionType::new(
132            vec![ValueType::Function(Box::new(callback.clone()))],
133            ValueType::Int,
134        );
135        let error = HostSpecializationError::uninhabited_callback_arguments(
136            "host_support".into(),
137            "host/function".into(),
138            "apply".into(),
139            signature.clone(),
140            callback.clone(),
141        );
142
143        assert_eq!(error.package(), "host_support");
144        assert_eq!(error.module(), "host/function");
145        assert_eq!(error.function(), "apply");
146        assert_eq!(error.signature(), &signature);
147        assert_eq!(
148            error.reason(),
149            &HostSpecializationErrorReason::UninhabitedCallbackArguments {
150                callback: callback.clone(),
151            },
152        );
153        assert_eq!(
154            error.to_string(),
155            "host function `host_support::host/function.apply` has an executable specialization `FunctionType { arguments: [Function(FunctionType { arguments: [Parameter(TypeParameterId(0))], return_: Int })], return_: Int }` that exposes callback `FunctionType { arguments: [Parameter(TypeParameterId(0))], return_: Int }` with uninhabited arguments",
156        );
157        assert_eq!(error.clone(), error);
158    }
159}