rune/diagnostics/
fatal.rs

1use core::fmt;
2
3use crate::alloc::{Box, String};
4#[cfg(feature = "emit")]
5use crate::ast::{Span, Spanned};
6use crate::compile::{self, LinkerError};
7use crate::SourceId;
8
9/// Fatal diagnostic emitted during compilation. Fatal diagnostics indicates an
10/// unrecoverable issue.
11#[derive(Debug)]
12pub struct FatalDiagnostic {
13    /// The source id of the error.
14    pub(crate) source_id: SourceId,
15    /// The kind of the load error.
16    pub(crate) kind: Box<FatalDiagnosticKind>,
17}
18
19impl FatalDiagnostic {
20    /// The source id where the error originates from.
21    pub fn source_id(&self) -> SourceId {
22        self.source_id
23    }
24
25    /// If this fatal diagnostic is a compile error, return it.
26    pub fn as_compile_error(&self) -> Option<&compile::Error> {
27        match &*self.kind {
28            FatalDiagnosticKind::CompileError(error) => Some(error),
29            _ => None,
30        }
31    }
32
33    /// If this fatal diagnostic is a link error, return it.
34    pub fn as_link_error(&self) -> Option<&LinkerError> {
35        match &*self.kind {
36            FatalDiagnosticKind::LinkError(error) => Some(error),
37            _ => None,
38        }
39    }
40
41    /// The kind of the load error.
42    #[cfg(any(feature = "emit", feature = "languageserver"))]
43    pub(crate) fn kind(&self) -> &FatalDiagnosticKind {
44        &self.kind
45    }
46
47    /// The kind of the load error.
48    #[cfg(test)]
49    pub(crate) fn into_kind(self) -> FatalDiagnosticKind {
50        Box::into_inner(self.kind)
51    }
52
53    #[cfg(feature = "emit")]
54    pub(crate) fn span(&self) -> Option<Span> {
55        match &*self.kind {
56            FatalDiagnosticKind::CompileError(error) => Some(error.span()),
57            FatalDiagnosticKind::LinkError(..) => None,
58            FatalDiagnosticKind::Custom(..) => None,
59        }
60    }
61}
62
63impl fmt::Display for FatalDiagnostic {
64    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
65        self.kind.fmt(f)
66    }
67}
68
69impl core::error::Error for FatalDiagnostic {
70    #[inline]
71    fn source(&self) -> Option<&(dyn core::error::Error + 'static)> {
72        match &*self.kind {
73            FatalDiagnosticKind::CompileError(error) => Some(error),
74            FatalDiagnosticKind::LinkError(error) => Some(error),
75            _ => None,
76        }
77    }
78}
79
80/// The kind of a [FatalDiagnostic].
81#[derive(Debug)]
82#[allow(missing_docs)]
83#[non_exhaustive]
84pub(crate) enum FatalDiagnosticKind {
85    /// A compilation error.
86    CompileError(compile::Error),
87    /// A linking error.
88    LinkError(LinkerError),
89    /// An internal error.
90    Custom(String),
91}
92
93impl fmt::Display for FatalDiagnosticKind {
94    #[inline]
95    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
96        match self {
97            FatalDiagnosticKind::CompileError(error) => error.fmt(f),
98            FatalDiagnosticKind::LinkError(error) => error.fmt(f),
99            FatalDiagnosticKind::Custom(message) => message.fmt(f),
100        }
101    }
102}
103
104impl From<compile::Error> for FatalDiagnosticKind {
105    #[inline]
106    fn from(error: compile::Error) -> Self {
107        FatalDiagnosticKind::CompileError(error)
108    }
109}
110
111impl From<LinkerError> for FatalDiagnosticKind {
112    #[inline]
113    fn from(error: LinkerError) -> Self {
114        FatalDiagnosticKind::LinkError(error)
115    }
116}