1 //! This module contains `Diagnostic` and the types/functions it uses for deserialization. 2 3 #[cfg(feature = "builder")] 4 use derive_builder::Builder; 5 use serde::{Deserialize, Serialize}; 6 use std::fmt; 7 8 /// The error code associated to this diagnostic. 9 #[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, Hash)] 10 #[cfg_attr(feature = "builder", derive(Builder))] 11 #[non_exhaustive] 12 #[cfg_attr(feature = "builder", builder(pattern = "owned", setter(into)))] 13 pub struct DiagnosticCode { 14 /// The code itself. 15 pub code: String, 16 /// An explanation for the code 17 pub explanation: Option<String>, 18 } 19 20 /// A line of code associated with the Diagnostic 21 #[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, Hash)] 22 #[cfg_attr(feature = "builder", derive(Builder))] 23 #[non_exhaustive] 24 #[cfg_attr(feature = "builder", builder(pattern = "owned", setter(into)))] 25 pub struct DiagnosticSpanLine { 26 /// The line of code associated with the error 27 pub text: String, 28 /// Start of the section of the line to highlight. 1-based, character offset in self.text 29 pub highlight_start: usize, 30 /// End of the section of the line to highlight. 1-based, character offset in self.text 31 pub highlight_end: usize, 32 } 33 34 /// Macro expansion information associated with a diagnostic. 35 #[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, Hash)] 36 #[cfg_attr(feature = "builder", derive(Builder))] 37 #[non_exhaustive] 38 #[cfg_attr(feature = "builder", builder(pattern = "owned", setter(into)))] 39 pub struct DiagnosticSpanMacroExpansion { 40 /// span where macro was applied to generate this code; note that 41 /// this may itself derive from a macro (if 42 /// `span.expansion.is_some()`) 43 pub span: DiagnosticSpan, 44 45 /// name of macro that was applied (e.g., "foo!" or "#[derive(Eq)]") 46 pub macro_decl_name: String, 47 48 /// span where macro was defined (if known) 49 pub def_site_span: Option<DiagnosticSpan>, 50 } 51 52 /// A section of the source code associated with a Diagnostic 53 #[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, Hash)] 54 #[cfg_attr(feature = "builder", derive(Builder))] 55 #[non_exhaustive] 56 #[cfg_attr(feature = "builder", builder(pattern = "owned", setter(into)))] 57 pub struct DiagnosticSpan { 58 /// The file name or the macro name this diagnostic comes from. 59 pub file_name: String, 60 /// The byte offset in the file where this diagnostic starts from. 61 pub byte_start: u32, 62 /// The byte offset in the file where this diagnostic ends. 63 pub byte_end: u32, 64 /// 1-based. The line in the file. 65 pub line_start: usize, 66 /// 1-based. The line in the file. 67 pub line_end: usize, 68 /// 1-based, character offset. 69 pub column_start: usize, 70 /// 1-based, character offset. 71 pub column_end: usize, 72 /// Is this a "primary" span -- meaning the point, or one of the points, 73 /// where the error occurred? 74 /// 75 /// There are rare cases where multiple spans are marked as primary, 76 /// e.g. "immutable borrow occurs here" and "mutable borrow ends here" can 77 /// be two separate spans both "primary". Top (parent) messages should 78 /// always have at least one primary span, unless it has 0 spans. Child 79 /// messages may have 0 or more primary spans. 80 pub is_primary: bool, 81 /// Source text from the start of line_start to the end of line_end. 82 pub text: Vec<DiagnosticSpanLine>, 83 /// Label that should be placed at this location (if any) 84 pub label: Option<String>, 85 /// If we are suggesting a replacement, this will contain text 86 /// that should be sliced in atop this span. 87 pub suggested_replacement: Option<String>, 88 /// If the suggestion is approximate 89 pub suggestion_applicability: Option<Applicability>, 90 /// Macro invocations that created the code at this span, if any. 91 pub expansion: Option<Box<DiagnosticSpanMacroExpansion>>, 92 } 93 94 /// Whether a suggestion can be safely applied. 95 #[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, Hash)] 96 #[non_exhaustive] 97 pub enum Applicability { 98 /// The suggested replacement can be applied automatically safely 99 MachineApplicable, 100 /// The suggested replacement has placeholders that will need to be manually 101 /// replaced. 102 HasPlaceholders, 103 /// The suggested replacement may be incorrect in some circumstances. Needs 104 /// human review. 105 MaybeIncorrect, 106 /// The suggested replacement will probably not work. 107 Unspecified, 108 } 109 110 /// The diagnostic level 111 #[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq, Eq, Hash)] 112 #[non_exhaustive] 113 #[serde(rename_all = "lowercase")] 114 pub enum DiagnosticLevel { 115 /// Internal compiler error 116 #[serde(rename = "error: internal compiler error")] 117 Ice, 118 /// Error 119 Error, 120 /// Warning 121 Warning, 122 /// Failure note 123 #[serde(rename = "failure-note")] 124 FailureNote, 125 /// Note 126 Note, 127 /// Help 128 Help, 129 } 130 131 /// A diagnostic message generated by rustc 132 #[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, Hash)] 133 #[cfg_attr(feature = "builder", derive(Builder))] 134 #[non_exhaustive] 135 #[cfg_attr(feature = "builder", builder(pattern = "owned", setter(into)))] 136 pub struct Diagnostic { 137 /// The error message of this diagnostic. 138 pub message: String, 139 /// The associated error code for this diagnostic 140 pub code: Option<DiagnosticCode>, 141 /// "error: internal compiler error", "error", "warning", "note", "help" 142 pub level: DiagnosticLevel, 143 /// A list of source code spans this diagnostic is associated with. 144 pub spans: Vec<DiagnosticSpan>, 145 /// Associated diagnostic messages. 146 pub children: Vec<Diagnostic>, 147 /// The message as rustc would render it 148 pub rendered: Option<String>, 149 } 150 151 impl fmt::Display for Diagnostic { fmt(&self, f: &mut fmt::Formatter) -> fmt::Result152 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 153 if let Some(ref rendered) = self.rendered { 154 f.write_str(rendered)?; 155 } else { 156 f.write_str("cargo didn't render this message")?; 157 } 158 Ok(()) 159 } 160 } 161