Skip to main content

hax_rust_engine/ast/
diagnostics.rs

1//! Diagnostic types used to represent and propagate errors (or warnings, notes,
2//! etc.) within the AST.
3//!
4//! This module is used to attach semantic or translation errors to AST nodes.
5
6use crate::ast::*;
7use hax_rust_engine_macros::*;
8
9pub use hax_types::diagnostics::Kind as DiagnosticInfoKind;
10
11/// Error diagnostic
12#[derive_group_for_ast]
13pub struct Diagnostic {
14    node: Box<Fragment>,
15    info: DiagnosticInfo,
16}
17
18/// Error description and location
19#[derive_group_for_ast]
20#[must_use]
21pub struct DiagnosticInfo {
22    /// Diagnostic context
23    pub context: Context,
24    /// Location in the source code
25    pub span: Span,
26    /// Error type
27    pub kind: DiagnosticInfoKind,
28}
29
30impl DiagnosticInfo {
31    /// Emits the diagnostic information.
32    pub fn emit(&self) {
33        crate::hax_io::write(&hax_types::engine_api::protocol::FromEngine::Diagnostic(
34            hax_types::diagnostics::Diagnostics {
35                kind: self.kind.clone(),
36                span: self.span.as_frontend_spans().to_vec(),
37                context: format!("{}", self.context),
38                owner_id: None,
39            },
40        ))
41    }
42}
43
44impl Diagnostic {
45    /// Get diagnostic information
46    pub fn info(&self) -> &DiagnosticInfo {
47        &self.info
48    }
49    /// Get diagnostic node of origin
50    pub fn node(&self) -> &Fragment {
51        &self.node
52    }
53    /// Report an error
54    pub fn new(node: impl Into<Fragment>, info: DiagnosticInfo) -> Self {
55        let node = node.into();
56        info.emit();
57        Self {
58            node: Box::new(node),
59            info,
60        }
61    }
62}
63
64/// Context of an error
65#[derive_group_for_ast]
66pub enum Context {
67    /// Error during import from THIR
68    Import,
69    /// Error during the projection from idenitfiers to views
70    NameView,
71    /// Error in a printer
72    Printer(String),
73    /// Error in an engine phase
74    Phase(String),
75    /// Debugger
76    Debugger,
77    /// Unknown
78    Unknown,
79}
80
81impl std::fmt::Display for Context {
82    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
83        match self {
84            Context::Import => write!(f, "Importer"),
85            Context::NameView => write!(f, "Name rendering"),
86            Context::Printer(p) => write!(f, "{p} Printer"),
87            Context::Phase(p) => write!(f, "Engine phase ({p})"),
88            Context::Debugger => write!(f, "Debugger"),
89            Context::Unknown => write!(f, "Unknown"),
90        }
91    }
92}