leo_errors/errors/mod.rs
1// Copyright (C) 2019-2026 Provable Inc.
2// This file is part of the Leo library.
3
4// The Leo library is free software: you can redistribute it and/or modify
5// it under the terms of the GNU General Public License as published by
6// the Free Software Foundation, either version 3 of the License, or
7// (at your option) any later version.
8
9// The Leo library is distributed in the hope that it will be useful,
10// but WITHOUT ANY WARRANTY; without even the implied warranty of
11// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12// GNU General Public License for more details.
13
14// You should have received a copy of the GNU General Public License
15// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
16
17/// The LeoError type that contains all sub error types.
18/// This allows a unified error type throughout the Leo crates.
19#[derive(Debug, Error)]
20pub enum LeoError {
21 #[error(transparent)]
22 Formatted(#[from] crate::Formatted),
23 #[error(transparent)]
24 Backtraced(#[from] crate::Backtraced),
25 #[error("")]
26 LastErrorCode(i32),
27 #[error(transparent)]
28 SnarkVM(#[from] anyhow::Error),
29}
30
31impl LeoError {
32 pub fn error_code(&self) -> String {
33 use LeoError::*;
34 match self {
35 Formatted(e) => e.error_code(),
36 Backtraced(e) => e.error_code(),
37 LastErrorCode(_) => unreachable!(),
38 SnarkVM(_) => "SnarkVM Error".to_string(),
39 }
40 }
41
42 pub fn exit_code(&self) -> i32 {
43 use LeoError::*;
44 match self {
45 Formatted(e) => e.exit_code(),
46 Backtraced(e) => e.exit_code(),
47 LastErrorCode(code) => *code,
48 SnarkVM(_) => 11000,
49 }
50 }
51
52 /// Borrow a structured, LSP-agnostic view of this error.
53 ///
54 /// Only [`LeoError::Formatted`] variants carry a span and labeled
55 /// secondary information, so other variants return `None`. The caller is
56 /// expected to fall back to a synthetic package-level diagnostic in that
57 /// case; see the `leo-lsp` diagnostics module for an example.
58 ///
59 /// [`LeoError::LastErrorCode`] is a sentinel used to signal that an error
60 /// has already been emitted through a handler. It deliberately returns
61 /// `None` so it is never published as a separate diagnostic.
62 pub fn diagnostic_view(&self) -> Option<crate::DiagnosticView<'_>> {
63 match self {
64 LeoError::Formatted(formatted) => Some(formatted.diagnostic_view()),
65 LeoError::Backtraced(_) | LeoError::LastErrorCode(_) | LeoError::SnarkVM(_) => None,
66 }
67 }
68
69 /// Return whether this error is the sentinel raised after a handler emit.
70 ///
71 /// `Handler::last_err` produces [`LeoError::LastErrorCode`] when the
72 /// emitter has already buffered a real diagnostic. Consumers should skip
73 /// the sentinel when collecting structured diagnostics so the original
74 /// error is published exactly once.
75 pub fn is_last_error_code(&self) -> bool {
76 matches!(self, LeoError::LastErrorCode(_))
77 }
78}
79
80/// The LeoWarning type that contains all sub warning types.
81#[derive(Debug, Error)]
82pub enum LeoWarning {
83 #[error(transparent)]
84 Formatted(#[from] crate::Formatted),
85}
86
87impl LeoWarning {
88 pub fn error_code(&self) -> String {
89 use LeoWarning::*;
90 match self {
91 Formatted(w) => w.warning_code(),
92 }
93 }
94
95 /// Borrow a structured, LSP-agnostic view of this warning.
96 ///
97 /// Every variant currently wraps a [`Formatted`] payload, so the view is
98 /// always available. The signature is kept symmetric with
99 /// [`LeoError::diagnostic_view`] so future variants that lack span data
100 /// can opt out without breaking call sites.
101 pub fn diagnostic_view(&self) -> Option<crate::DiagnosticView<'_>> {
102 match self {
103 LeoWarning::Formatted(formatted) => Some(formatted.diagnostic_view()),
104 }
105 }
106}
107
108/// A global result type for all Leo crates, that defaults the errors to be a LeoError.
109pub type Result<T, E = LeoError> = core::result::Result<T, E>;