1mod extension;
23mod ops;
24mod types;
25mod types_mut;
26mod weak_registry;
27
28pub use weak_registry::WeakExtensionRegistry;
29
30pub(crate) use ops::{collect_op_extension, resolve_op_extensions};
31pub(crate) use types::{collect_op_types_extensions, collect_signature_exts};
32pub(crate) use types_mut::resolve_op_types_extensions;
33use types_mut::{
34    resolve_custom_type_exts, resolve_type_exts, resolve_typearg_exts, resolve_value_exts,
35};
36
37use derive_more::{Display, Error, From};
38
39use super::{Extension, ExtensionId, ExtensionRegistry, ExtensionSet};
40use crate::ops::constant::ValueName;
41use crate::ops::custom::OpaqueOpError;
42use crate::ops::{NamedOp, OpName, OpType, Value};
43use crate::types::{CustomType, FuncTypeBase, MaybeRV, TypeArg, TypeBase, TypeName};
44use crate::Node;
45
46pub fn resolve_type_extensions<RV: MaybeRV>(
48    typ: &mut TypeBase<RV>,
49    extensions: &WeakExtensionRegistry,
50) -> Result<(), ExtensionResolutionError> {
51    let mut used_extensions = WeakExtensionRegistry::default();
52    resolve_type_exts(None, typ, extensions, &mut used_extensions)
53}
54
55pub fn resolve_custom_type_extensions(
57    typ: &mut CustomType,
58    extensions: &WeakExtensionRegistry,
59) -> Result<(), ExtensionResolutionError> {
60    let mut used_extensions = WeakExtensionRegistry::default();
61    resolve_custom_type_exts(None, typ, extensions, &mut used_extensions)
62}
63
64pub fn resolve_typearg_extensions(
66    arg: &mut TypeArg,
67    extensions: &WeakExtensionRegistry,
68) -> Result<(), ExtensionResolutionError> {
69    let mut used_extensions = WeakExtensionRegistry::default();
70    resolve_typearg_exts(None, arg, extensions, &mut used_extensions)
71}
72
73pub fn resolve_value_extensions(
75    value: &mut Value,
76    extensions: &WeakExtensionRegistry,
77) -> Result<(), ExtensionResolutionError> {
78    let mut used_extensions = WeakExtensionRegistry::default();
79    resolve_value_exts(None, value, extensions, &mut used_extensions)
80}
81
82#[derive(Debug, Display, Clone, Error, From, PartialEq)]
84#[non_exhaustive]
85pub enum ExtensionResolutionError {
86    #[display("Error resolving opaque operation: {_0}")]
88    #[from]
89    OpaqueOpError(OpaqueOpError),
90    #[display(
92        "{op}{} requires extension {missing_extension}, but it could not be found in the extension list used during resolution. The available extensions are: {}",
93        node.map(|n| format!(" in {}", n)).unwrap_or_default(),
94        available_extensions.join(", ")
95    )]
96    MissingOpExtension {
97        node: Option<Node>,
99        op: OpName,
101        missing_extension: ExtensionId,
103        available_extensions: Vec<ExtensionId>,
105    },
106    #[display(
108        "Type {ty}{} requires extension {missing_extension}, but it could not be found in the extension list used during resolution. The available extensions are: {}",
109        node.map(|n| format!(" in {}", n)).unwrap_or_default(),
110        available_extensions.join(", ")
111    )]
112    MissingTypeExtension {
113        node: Option<Node>,
115        ty: TypeName,
117        missing_extension: ExtensionId,
119        available_extensions: Vec<ExtensionId>,
121    },
122    #[display(
124        "Type definition {def} in extension {extension} declares it was defined in {wrong_extension} instead."
125    )]
126    WrongTypeDefExtension {
127        extension: ExtensionId,
129        def: TypeName,
131        wrong_extension: ExtensionId,
133    },
134    #[display(
136        "Operation definition {def} in extension {extension} declares it was defined in {wrong_extension} instead."
137    )]
138    WrongOpDefExtension {
139        extension: ExtensionId,
141        def: OpName,
143        wrong_extension: ExtensionId,
145    },
146    #[display("The type of the opaque value '{value}' requires extensions {missing_extensions}, but does not reference their definition.")]
148    InvalidConstTypes {
149        value: ValueName,
151        missing_extensions: ExtensionSet,
153    },
154}
155
156impl ExtensionResolutionError {
157    pub fn missing_op_extension(
159        node: Option<Node>,
160        op: &OpType,
161        missing_extension: &ExtensionId,
162        extensions: &ExtensionRegistry,
163    ) -> Self {
164        Self::MissingOpExtension {
165            node,
166            op: NamedOp::name(op),
167            missing_extension: missing_extension.clone(),
168            available_extensions: extensions.ids().cloned().collect(),
169        }
170    }
171
172    pub fn missing_type_extension(
174        node: Option<Node>,
175        ty: &TypeName,
176        missing_extension: &ExtensionId,
177        extensions: &WeakExtensionRegistry,
178    ) -> Self {
179        Self::MissingTypeExtension {
180            node,
181            ty: ty.clone(),
182            missing_extension: missing_extension.clone(),
183            available_extensions: extensions.ids().cloned().collect(),
184        }
185    }
186}
187
188#[derive(Debug, Display, Clone, Error, From, PartialEq)]
190#[non_exhaustive]
191pub enum ExtensionCollectionError {
192    #[display(
194        "{op}{} contains custom types for which have lost the reference to their defining extensions. Dropped extensions: {}",
195        if let Some(node) = node { format!(" ({})", node) } else { "".to_string() },
196        missing_extensions.join(", ")
197    )]
198    DroppedOpExtensions {
199        node: Option<Node>,
201        op: OpName,
203        missing_extensions: Vec<ExtensionId>,
205    },
206    #[display(
208        "Signature {signature} contains custom types for which have lost the reference to their defining extensions. Dropped extensions: {}",
209        missing_extensions.join(", ")
210    )]
211    DroppedSignatureExtensions {
212        signature: String,
214        missing_extensions: Vec<ExtensionId>,
216    },
217}
218
219impl ExtensionCollectionError {
220    pub fn dropped_op_extension(
222        node: Option<Node>,
223        op: &OpType,
224        missing_extension: impl IntoIterator<Item = ExtensionId>,
225    ) -> Self {
226        Self::DroppedOpExtensions {
227            node,
228            op: NamedOp::name(op),
229            missing_extensions: missing_extension.into_iter().collect(),
230        }
231    }
232
233    pub fn dropped_signature<RV: MaybeRV>(
235        signature: &FuncTypeBase<RV>,
236        missing_extension: impl IntoIterator<Item = ExtensionId>,
237    ) -> Self {
238        Self::DroppedSignatureExtensions {
239            signature: format!("{signature}"),
240            missing_extensions: missing_extension.into_iter().collect(),
241        }
242    }
243}
244
245#[cfg(test)]
246mod test;