1mod handler_id;
4mod severity;
5
6pub use self::{handler_id::DiagnosticHandlerId, severity::DiagnosticSeverity};
7use crate::{ir::Location, utility::print_callback, Error};
8use mlir_sys::{
9 mlirDiagnosticGetLocation, mlirDiagnosticGetNote, mlirDiagnosticGetNumNotes,
10 mlirDiagnosticGetSeverity, mlirDiagnosticPrint, MlirDiagnostic,
11};
12use std::{
13 ffi::c_void,
14 fmt::{self, Display, Formatter},
15 marker::PhantomData,
16};
17
18#[derive(Debug)]
19pub struct Diagnostic<'c> {
20 raw: MlirDiagnostic,
21 phantom: PhantomData<&'c ()>,
22}
23
24impl Diagnostic<'_> {
25 pub fn location(&self) -> Location {
26 unsafe { Location::from_raw(mlirDiagnosticGetLocation(self.raw)) }
27 }
28
29 pub fn severity(&self) -> DiagnosticSeverity {
30 DiagnosticSeverity::try_from(unsafe { mlirDiagnosticGetSeverity(self.raw) })
31 .unwrap_or_else(|error| unreachable!("{}", error))
32 }
33
34 pub fn note_count(&self) -> usize {
35 (unsafe { mlirDiagnosticGetNumNotes(self.raw) }) as usize
36 }
37
38 pub fn note(&self, index: usize) -> Result<Self, Error> {
39 if index < self.note_count() {
40 Ok(unsafe { Self::from_raw(mlirDiagnosticGetNote(self.raw, index as isize)) })
41 } else {
42 Err(Error::PositionOutOfBounds {
43 name: "diagnostic note",
44 value: self.to_string(),
45 index,
46 })
47 }
48 }
49
50 pub unsafe fn from_raw(raw: MlirDiagnostic) -> Self {
56 Self {
57 raw,
58 phantom: Default::default(),
59 }
60 }
61}
62
63impl Display for Diagnostic<'_> {
64 fn fmt(&self, formatter: &mut Formatter) -> fmt::Result {
65 let mut data = (formatter, Ok(()));
66
67 unsafe {
68 mlirDiagnosticPrint(
69 self.raw,
70 Some(print_callback),
71 &mut data as *mut _ as *mut c_void,
72 );
73 }
74
75 data.1
76 }
77}
78
79#[cfg(test)]
80mod tests {
81 use crate::{ir::Module, Context};
82
83 #[test]
84 fn handle_diagnostic() {
85 let mut message = None;
86 let context = Context::new();
87
88 context.attach_diagnostic_handler(|diagnostic| {
89 message = Some(diagnostic.to_string());
90 true
91 });
92
93 Module::parse(&context, "foo");
94
95 assert_eq!(
96 message.unwrap(),
97 "custom op 'foo' is unknown (tried 'builtin.foo' as well)"
98 );
99 }
100}