rune/compile/
context_error.rs

1use core::fmt;
2
3use crate::alloc;
4use crate::alloc::prelude::*;
5use crate::compile::meta::AssociatedKind;
6use crate::runtime::{RuntimeError, TypeInfo};
7use crate::{Hash, ItemBuf};
8
9/// An error raised when building the context.
10#[derive(Debug)]
11#[allow(missing_docs)]
12#[non_exhaustive]
13pub enum ContextError {
14    AllocError {
15        error: alloc::Error,
16    },
17    InvalidConstValue {
18        item: ItemBuf,
19        error: Box<RuntimeError>,
20    },
21    InvalidAssociatedConstValue {
22        container: TypeInfo,
23        kind: Box<AssociatedKind>,
24        error: Box<RuntimeError>,
25    },
26    UnitAlreadyPresent,
27    InternalAlreadyPresent {
28        name: &'static str,
29    },
30    ConflictingFunction {
31        part: Box<str>,
32        hash: Hash,
33    },
34    ConflictingFunctionName {
35        item: ItemBuf,
36        hash: Hash,
37    },
38    ConflictingMacroName {
39        item: ItemBuf,
40        hash: Hash,
41    },
42    ConflictingConstantName {
43        item: ItemBuf,
44        hash: Hash,
45    },
46    ConflictingInstanceFunction {
47        type_info: TypeInfo,
48        name: Box<str>,
49    },
50    ConflictingProtocolFunction {
51        type_info: TypeInfo,
52        name: Box<str>,
53    },
54    ConflictingFieldFunction {
55        type_info: TypeInfo,
56        name: Box<str>,
57        field: Box<str>,
58    },
59    ConflictingIndexFunction {
60        type_info: TypeInfo,
61        name: Box<str>,
62        index: usize,
63    },
64    ConflictingModule {
65        item: ItemBuf,
66        hash: Hash,
67    },
68    ConflictingType {
69        item: ItemBuf,
70        type_info: TypeInfo,
71        hash: Hash,
72    },
73    ConflictingReexport {
74        item: ItemBuf,
75        hash: Hash,
76        to: ItemBuf,
77    },
78    ConflictingTrait {
79        item: ItemBuf,
80        hash: Hash,
81    },
82    ConflictingTraitImpl {
83        trait_item: ItemBuf,
84        trait_hash: Hash,
85        item: ItemBuf,
86        hash: Hash,
87    },
88    MissingTraitFunction {
89        name: String,
90        item: ItemBuf,
91        hash: Hash,
92        trait_item: ItemBuf,
93        trait_hash: Hash,
94    },
95    MissingTrait {
96        item: ItemBuf,
97        hash: Hash,
98        impl_item: ItemBuf,
99        impl_hash: Hash,
100    },
101    ConflictingTypeMeta {
102        item: ItemBuf,
103        type_info: TypeInfo,
104    },
105    ConflictingVariantMeta {
106        type_info: TypeInfo,
107        name: &'static str,
108    },
109    ConflictingMetaHash {
110        item: ItemBuf,
111        hash: Hash,
112        existing: Hash,
113    },
114    ConflictingTypeHash {
115        hash: Hash,
116        existing: Hash,
117    },
118    ConflictingVariant {
119        item: ItemBuf,
120    },
121    ConstructorConflict {
122        type_info: TypeInfo,
123    },
124    VariantConstructorConflict {
125        type_info: TypeInfo,
126        name: &'static str,
127    },
128    ConflictingConstConstruct {
129        type_info: TypeInfo,
130        hash: Hash,
131    },
132    MissingType {
133        item: ItemBuf,
134        type_info: TypeInfo,
135    },
136    MissingEnum {
137        item: ItemBuf,
138        type_info: TypeInfo,
139    },
140    MissingContainer {
141        container: TypeInfo,
142    },
143    MissingVariant {
144        index: usize,
145        type_info: TypeInfo,
146    },
147    ExpectedAssociated,
148    TypeHashMismatch {
149        type_info: TypeInfo,
150        item: ItemBuf,
151        hash: Hash,
152        item_hash: Hash,
153    },
154    StaticTypeHashMismatch {
155        type_info: TypeInfo,
156        item: ItemBuf,
157        hash: Hash,
158        item_hash: Hash,
159    },
160}
161
162impl From<alloc::Error> for ContextError {
163    #[inline]
164    fn from(error: alloc::Error) -> Self {
165        ContextError::AllocError { error }
166    }
167}
168
169impl From<alloc::alloc::AllocError> for ContextError {
170    #[inline]
171    fn from(error: alloc::alloc::AllocError) -> Self {
172        ContextError::AllocError {
173            error: error.into(),
174        }
175    }
176}
177
178impl fmt::Display for ContextError {
179    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
180        match self {
181            ContextError::AllocError { error } => {
182                error.fmt(f)?;
183            }
184            ContextError::InvalidConstValue { item, error } => {
185                write!(f, "Error when building constant {item}: {error}")?;
186            }
187            ContextError::InvalidAssociatedConstValue {
188                container,
189                kind,
190                error,
191            } => {
192                write!(
193                    f,
194                    "Error when building associated constant in {container}::{kind}: {error}"
195                )?;
196            }
197            ContextError::UnitAlreadyPresent => {
198                write!(f, "Unit `()` type is already present")?;
199            }
200            ContextError::InternalAlreadyPresent { name } => {
201                write!(f, "Type for name `{name}` is already present")?;
202            }
203            ContextError::ConflictingFunction { part, hash } => {
204                write!(
205                    f,
206                    "Function with hash `{hash}` part of `{part}` already exists"
207                )?;
208            }
209            ContextError::ConflictingFunctionName { item, hash } => {
210                write!(f, "Function `{item}` already exists with hash `{hash}`")?;
211            }
212            ContextError::ConflictingMacroName { item, hash } => {
213                write!(f, "Macro `{item}` already exists with hash `{hash}`")?;
214            }
215            ContextError::ConflictingConstantName { item, hash } => {
216                write!(f, "Constant `{item}` already exists with hash `{hash}`")?;
217            }
218            ContextError::ConflictingInstanceFunction { type_info, name } => {
219                write!(
220                    f,
221                    "Instance function `{name}` for type `{type_info}` already exists"
222                )?;
223            }
224            ContextError::ConflictingProtocolFunction { type_info, name } => {
225                write!(
226                    f,
227                    "Protocol function `{name}` for type `{type_info}` already exists"
228                )?;
229            }
230            ContextError::ConflictingFieldFunction {
231                type_info,
232                name,
233                field,
234            } => {
235                write!(f,"Field function `{name}` for field `{field}` and type `{type_info}` already exists")?;
236            }
237            ContextError::ConflictingIndexFunction {
238                type_info,
239                name,
240                index,
241            } => {
242                write!(f,"Index function `{name}` for index `{index}` and type `{type_info}` already exists")?;
243            }
244            ContextError::ConflictingModule { item, hash } => {
245                write!(f, "Module `{item}` with hash `{hash}` already exists")?;
246            }
247            ContextError::ConflictingType {
248                item,
249                type_info,
250                hash,
251            } => {
252                write!(
253                    f,
254                    "Type `{item}` already exists `{type_info}` with hash `{hash}`"
255                )?;
256            }
257            ContextError::ConflictingReexport { item, hash, to } => {
258                write!(
259                    f,
260                    "Reexport at `{item}` with hash `{hash}` to `{to}` already exists"
261                )?;
262            }
263            ContextError::ConflictingTrait { item, hash } => {
264                write!(
265                    f,
266                    "Trait `{item}` with hash `{hash}` conflicts with other item in module"
267                )?;
268            }
269            ContextError::ConflictingTraitImpl {
270                trait_item,
271                trait_hash,
272                item,
273                hash,
274            } => {
275                write!(
276                    f,
277                    "Trait `{trait_item}` with hash `{trait_hash}` is implemented multiple types for type `{item}` with hash `{hash}`"
278                )?;
279            }
280            ContextError::MissingTraitFunction {
281                name,
282                item,
283                hash,
284                trait_item,
285                trait_hash,
286            } => {
287                write!(
288                    f,
289                    "Missing required associated `{name}` for type `{item}` with hash `{hash}` when implementing trait `{trait_item}` with hash `{trait_hash}`"
290                )?;
291            }
292            ContextError::MissingTrait {
293                item,
294                hash,
295                impl_item,
296                impl_hash,
297            } => {
298                write!(
299                    f,
300                    "Missing trait `{item}` with hash `{hash}` when implementing it for `{impl_item}` with hash `{impl_hash}`"
301                )?;
302            }
303            ContextError::ConflictingTypeMeta { item, type_info } => {
304                write!(
305                    f,
306                    "Type `{item}` at `{type_info}` already has a specification"
307                )?;
308            }
309            ContextError::ConflictingVariantMeta { type_info, name } => {
310                write!(
311                    f,
312                    "Variant `{name}` for `{type_info}` already has a specification"
313                )?;
314            }
315            ContextError::ConflictingMetaHash {
316                item,
317                hash,
318                existing,
319            } => {
320                write!(f,"Conflicting meta hash `{hash}` for existing `{existing}` when inserting item `{item}`")?;
321            }
322            ContextError::ConflictingTypeHash { hash, existing } => {
323                write!(
324                    f,
325                    "Tried to insert conflicting hash `{hash}` for `{existing}`"
326                )?;
327            }
328            ContextError::ConflictingVariant { item } => {
329                write!(f, "Variant with `{item}` already exists")?;
330            }
331            ContextError::ConstructorConflict { type_info } => {
332                write!(f, "Constructor for `{type_info}` already exists")?;
333            }
334            ContextError::VariantConstructorConflict { type_info, name } => {
335                write!(
336                    f,
337                    "Constructor for variant `{name}` for `{type_info}` already exists"
338                )?;
339            }
340            ContextError::ConflictingConstConstruct { type_info, hash } => {
341                write!(
342                    f,
343                    "Constant constructor with hash {hash} for `{type_info}` already exists"
344                )?;
345            }
346            ContextError::MissingType { item, type_info } => {
347                write!(f, "Type `{item}` with info `{type_info}` isn't registered")?;
348            }
349            ContextError::MissingEnum { item, type_info } => {
350                write!(
351                    f,
352                    "Type `{item}` with info `{type_info}` is registered but is not an enum"
353                )?;
354            }
355            ContextError::MissingContainer { container } => {
356                write!(f, "Container `{container}` is not registered")?;
357            }
358            ContextError::MissingVariant { index, type_info } => {
359                write!(f, "Missing variant {index} for `{type_info}`")?;
360            }
361            ContextError::ExpectedAssociated => {
362                write!(f, "Expected associated function")?;
363            }
364            ContextError::TypeHashMismatch {
365                type_info,
366                item,
367                hash,
368                item_hash,
369            } => {
370                let expected = item.parent().unwrap_or_default();
371
372                write! {
373                    f,
374                    "Type hash mismatch for `{type_info}`, from module is `{hash}` while from item `{item}` is `{item_hash}`.\n\
375                    You might not have the #[rune(item = {expected})] attribute set."
376                }?;
377            }
378            ContextError::StaticTypeHashMismatch {
379                type_info,
380                item,
381                hash,
382                item_hash,
383            } => {
384                write!(f, "Static type hash mismatch for `{type_info}`, from module is `{hash}` while from item `{item}` is `{item_hash}`. The static item might be registered in the wrong module, or that the static type hash is miscalculated.")?;
385            }
386        }
387
388        Ok(())
389    }
390}
391
392impl core::error::Error for ContextError {}