geam_core/plan/execution/host/
error.rs1use 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}