hax_types/diagnostics/
mod.rs

1use crate::prelude::*;
2use colored::Colorize;
3
4pub mod message;
5pub mod report;
6
7#[derive_group(Serializers)]
8#[derive(Debug, Clone, JsonSchema, Eq, PartialEq, Hash)]
9pub struct Diagnostics {
10    pub kind: Kind,
11    pub span: Vec<hax_frontend_exporter::Span>,
12    pub context: String,
13    pub owner_id: Option<hax_frontend_exporter::DefId>,
14}
15
16impl std::fmt::Display for Diagnostics {
17    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
18        match &self.kind {
19            Kind::Unimplemented { issue_id, details } => write!(
20                f,
21                "something is not implemented yet.{}{}",
22                match issue_id {
23                    Some(id) => format!("This is discussed in issue https://github.com/hacspec/hax/issues/{id}.\nPlease upvote or comment this issue if you see this error message."),
24                    _ => "".to_string(),
25                },
26                match details {
27                    Some(details) => format!("\n{}", details),
28                    _ => "".to_string(),
29                }
30            ),
31            Kind::UnsupportedMacro { id } => write!(
32                f,
33                "The unexpanded macro {} is not supported by this backend.\nPlease verify the argument you passed to the {} (or {}) option.",
34                id.bold(),
35                "--inline-macro-call".bold(), "-i".bold()
36            ),
37            Kind::UnsafeBlock => write!(f, "Unsafe blocks are not allowed."),
38            Kind::AssertionFailure {details} => write!(
39                f,
40                "Fatal error: something we considered as impossible occurred! {}\nDetails: {}",
41                "Please report this by submitting an issue on GitHub!".bold(),
42                details
43            ),
44            Kind::UnallowedMutRef => write!(
45                f,
46                "The mutation of this {} is not allowed here.",
47                "&mut".bold()
48            ),
49            Kind::ExpectedMutRef => write!(
50                f,
51                "At this position, Hax was expecting an expression of the shape `&mut _`.\nHax forbids `f(x)` (where `f` expects a mutable reference as input) when `x` is not a {}{} or when it is a dereference expression.
52
53{}",
54                "place expression".bold(),
55                "[1]".bright_black(),
56                "[1]: https://doc.rust-lang.org/reference/expressions.html#place-expressions-and-value-expressions"
57            ),
58            Kind::ClosureMutatesParentBindings {bindings} => write!(
59                f,
60                "The bindings {:?} cannot be mutated here: they don't belong to the closure scope, and this is not allowed.",
61                bindings
62            ),
63            Kind::ArbitraryLHS => write!(f, "Assignation of an arbitrary left-hand side is not supported.\n`lhs = e` is fine only when `lhs` is a combination of local identifiers, field accessors and index accessors."),
64
65            Kind::AttributeRejected {reason} => write!(f, "Here, this attribute cannot be used: {reason}."),
66
67            Kind::NonTrivialAndMutFnInput => write!(f, "The support in hax of function with one or more inputs of type `&mut _` is limited.\nOnly trivial patterns are allowed there: `fn f(x: &mut (T, U)) ...` is allowed while `f((x, y): &mut (T, U))` is rejected."),
68
69            Kind::FStarParseError { fstar_snippet, details: _ } => write!(f, "The following code snippet could not be parsed as valid F*:\n```\n{fstar_snippet}\n```"),
70
71            _ => write!(f, "{:?}", self.kind),
72        }?;
73        write!(f, "\n\n")?;
74        if let Some(issue) = self.kind.issue_number() {
75            write!(
76                f,
77                "This is discussed in issue https://github.com/hacspec/hax/issues/{issue}.\nPlease upvote or comment this issue if you see this error message."
78            )?;
79        }
80        write!(
81            f,
82            "{}",
83            format!(
84                "\nNote: the error was labeled with context `{}`.\n",
85                self.context
86            )
87            .bright_black()
88        )?;
89        Ok(())
90    }
91}
92
93impl Kind {
94    fn issue_number(&self) -> Option<u32> {
95        match self {
96            Kind::UnsafeBlock => None,
97            Kind::Unimplemented { issue_id, .. } => issue_id.clone(),
98            Kind::AssertionFailure { .. } => None,
99            Kind::UnallowedMutRef => Some(420),
100            Kind::UnsupportedMacro { .. } => None,
101            Kind::ErrorParsingMacroInvocation { .. } => None,
102            Kind::ClosureMutatesParentBindings { .. } => Some(1060),
103            Kind::ArbitraryLHS => None,
104            Kind::ExplicitRejection { .. } => None,
105            Kind::UnsupportedTupleSize { .. } => None,
106            Kind::ExpectedMutRef => Some(420),
107            Kind::NonTrivialAndMutFnInput => Some(1405),
108            Kind::AttributeRejected { .. } => None,
109            Kind::FStarParseError { .. } => todo!(),
110        }
111    }
112}
113
114#[derive_group(Serializers)]
115#[derive(Debug, Clone, Hash, Eq, PartialEq, Ord, PartialOrd, JsonSchema)]
116#[repr(u16)]
117pub enum Kind {
118    /// Unsafe code is not supported
119    UnsafeBlock = 0,
120
121    /// A feature is not currently implemented, but
122    Unimplemented {
123        /// Issue on the GitHub repository
124        issue_id: Option<u32>,
125        details: Option<String>,
126    } = 1,
127
128    /// Unknown error
129    // This is useful when doing sanity checks (i.e. one can yield
130    // this error kind for cases that should never happen)
131    AssertionFailure {
132        details: String,
133    } = 2,
134
135    /// Unallowed mutable reference
136    UnallowedMutRef = 3,
137
138    /// Unsupported macro invokation
139    UnsupportedMacro {
140        id: String,
141    } = 4,
142
143    /// Error parsing a macro invocation to a macro treated specifcially by a backend
144    ErrorParsingMacroInvocation {
145        macro_id: String,
146        details: String,
147    } = 5,
148
149    /// Mutation of bindings living outside a closure scope are not supported
150    ClosureMutatesParentBindings {
151        bindings: Vec<String>,
152    } = 6,
153
154    /// Assignation of an arbitrary left-hand side is not supported. `lhs = e` is fine only when `lhs` is a combination of local identifiers, field accessors and index accessors.
155    ArbitraryLHS = 7,
156
157    /// A phase explicitely rejected this chunk of code
158    ExplicitRejection {
159        reason: String,
160    } = 8,
161
162    /// A backend doesn't support a tuple size
163    UnsupportedTupleSize {
164        tuple_size: u32,
165        reason: String,
166    } = 9,
167
168    ExpectedMutRef = 10,
169
170    /// &mut inputs should be trivial patterns
171    NonTrivialAndMutFnInput = 11,
172
173    /// An hax attribute (from `hax-lib-macros`) was rejected
174    AttributeRejected {
175        reason: String,
176    } = 12,
177
178    /// A snippet of F* code could not be parsed
179    FStarParseError {
180        fstar_snippet: String,
181        details: String,
182    } = 13,
183}
184
185impl Kind {
186    // https://doc.rust-lang.org/reference/items/enumerations.html#pointer-casting
187    pub fn discriminant(&self) -> u16 {
188        unsafe { *(self as *const Self as *const u16) }
189    }
190
191    pub fn code(&self) -> String {
192        format!("HAX{:0>4}", self.discriminant())
193    }
194}