daemonic_error 1.0.0

Errors that compose, predict, and leave receipts - Compose: algebraic combination (in active development) - Predict: Glass/Severity - Receipts: audit trail, position, checksum - Reflection: Runtime Reflection through TopologySegment (in active development)
// use std::backtrace::Backtrace;
// use crate::{DiagCtxtHandle, Subdiagnostic};
// use crate::Color;
// use crate::ColorSpec;
// use std::borrow::Cow;
// use std::cell::Cell;
// use std::fmt;
// use std::fmt::Debug;
// use std::marker::PhantomData;
// use std::ops::{Deref, DerefMut};
// use std::path::{Path, PathBuf};
// use std::thread::panicking;
// use crate::daemonic::daemonic_contract::daemonic_result::diagnostic::EmissionGuarantee;

use alloc::borrow::Cow;
use alloc::boxed::Box;
use alloc::vec::Vec;
use core::marker::PhantomData;

pub mod data_structures;

/// Useful type to use with `Result<>` indicate that an error has already
/// been reported to the user, so no need to continue checking.
///
/// The `()` field is necessary: it is non-`pub`, which means values of this
/// type cannot be constructed outside of this crate.
///
/// #[derive(HashStable_Generic)]
#[derive(
	Clone,
	Copy,
	Debug,
	Hash,
	PartialEq,
	Eq,
	PartialOrd,
	Ord
)] // This technically uses unstable traits in std lib, but presents as stable on the surface.
pub struct ErrorGuaranteed(());
/// This is a marker for a fatal compiler error used with `resume_unwind`.
pub struct FatalErrorMarker;
/// Used as a return value to signify a fatal error occurred.
#[derive(Copy, Clone, Debug)]
#[must_use]
pub struct FatalError;
pub struct FatalRecovery;
/// Simplified version of `FluentValue` that can implement `Encodable` and `Decodable`. Converted
/// to a `FluentValue` by the emitter to be used in diagnostic translation.
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
pub enum DiagArgValue {
	Str(Cow<'static, str>),
	// This gets converted to a `FluentNumber`, which is an `f64`. An `i32`
	// safely fits in an `f64`. Any integers bigger than that will be converted
	// to strings in `into_diag_arg` and stored using the `Str` variant.
	// Fluent is deprecated, fluent was bullshit anyways so im not sure how applicable this is to current state
	Number(i32),
	StrListSepByAnd(Vec<Cow<'static, str>>),
}
/// Used for emitting structured error messages and other diagnostic information.
/// Wraps a `DiagInner`, adding some useful things.
/// - The `dcx` field, allowing it to (a) emit itself, and (b) do a drop check
///   that it has been emitted or cancelled.
/// - The `EmissionGuarantee`, which determines the type returned from `emit`.
///
/// Each constructed `Diag` must be consumed by a function such as `emit`,
/// `cancel`, `delay_as_bug`, or `into_diag`. A panic occurs if a `Diag`
/// is dropped without being consumed by one of these functions.
///
/// If there is some state in a downstream crate you would like to access in
/// the methods of `Diag` here, consider extending `DiagCtxtFlags`.
#[must_use]
pub struct Diag<'a, G: EmissionGuarantee = ErrorGuaranteed> {
	pub dcx: DiagnosticContextHandle<'a>,
	
	/// Why the `Option`? It is always `Some` until the `Diag` is consumed via
	/// `emit`, `cancel`, etc. At that point it is consumed and replaced with
	/// `None`. Then `drop` checks that it is `None`; if not, it panics because
	/// a diagnostic was built but not used.
	///
	/// Why the Box? `DiagInner` is a large type, and `Diag` is often used as a
	/// return value, especially within the frequently-used `PResult` type. In
	/// theory, return value optimization (RVO) should avoid unnecessary
	/// copying. In practice, it does not (at the time of writing).
	/// At time of writing' statements need to be dated, fuck this guy.
	pub(crate) diag: Option<Box<DiagInner>>,
	
	pub(crate) _marker: PhantomData<G>,
}
/// The main part of a diagnostic. Note that `Diag`, which wraps this type, is
/// used for most operations, and should be used instead whenever possible.
/// This type should only be used when `Diag`'s lifetime causes difficulties,
/// e.g. when storing diagnostics within `DiagCtxt`.
#[must_use]
#[derive(Clone, Debug)]
pub struct DiagInner {
	/// NOTE(eddyb) this is private to disallow arbitrary after-the-fact changes,
	/// outside of what methods in this crate themselves allow.
	/// not private anymore, also shit to begin with. Do better eddyb.
	pub level: DiagnosticLevel,
	
	pub messages: Vec<(DiagMessage, Style)>,
	pub code: Option<ErrCode>,
	pub lint_id: Option<LintExpectationId>,
	pub span: MultiSpan,
	pub children: Vec<Subdiag>,
	pub suggestions: Suggestions,
	pub args: DiagArgMap,
	
	/// This is not used for highlighting or rendering any error message. Rather, it can be used
	/// as a sort key to sort a buffer of diagnostics. By default, it is the primary span of
	/// `span` if there is one. Otherwise, it is `DUMMY_SP`.
	pub sort_span: Span,
	
	pub is_lint: Option<IsLint>,
	
	pub long_ty_path: Option<PathBuf>,
	/// With `-Ztrack_diagnostics` enabled,
	/// we print where in rustc this error was emitted.
	pub emitted_at: DiagLocation,
}
/// A "sub"-diagnostic attached to a parent diagnostic.
/// For example, a note attached to an error.
#[derive(Clone, Debug, PartialEq, Hash)]
pub struct Subdiag {
	pub level: DiagnosticLevel,
	pub messages: Vec<(DiagMessage, Style)>,
	pub span: MultiSpan,
}
/// | Level        | is_error | EmissionGuarantee            | Top-level | Sub | Used in lints?
/// | -----        | -------- | -----------------            | --------- | --- | --------------
/// | Bug          | yes      | BugAbort                     | yes       | -   | -
/// | Fatal        | yes      | FatalAbort/FatalError[^star] | yes       | -   | -
/// | Error        | yes      | ErrorGuaranteed              | yes       | -   | yes
/// | DelayedBug   | yes      | ErrorGuaranteed              | yes       | -   | -
/// | ForceWarning | -        | ()                           | yes       | -   | lint-only
/// | Warning      | -        | ()                           | yes       | yes | yes
/// | Note         | -        | ()                           | rare      | yes | -
/// | OnceNote     | -        | ()                           | -         | yes | lint-only
/// | Help         | -        | ()                           | rare      | yes | -
/// | OnceHelp     | -        | ()                           | -         | yes | lint-only
/// | FailureNote  | -        | ()                           | rare      | -   | -
/// | Allow        | -        | ()                           | yes       | -   | lint-only
/// | Expect       | -        | ()                           | yes       | -   | lint-only
///
/// [^star]: `FatalAbort` normally, `FatalError` in the non-aborting "almost fatal" case that is
///     occasionally used.
///    Note for Daemonic Consumers, *DiagnosticLevel is NOT GlassState*
///
/// This is technically a nested trait object from the reference frame of DaemonicError.
/// Most users/devs should never need to directly call this part of the logic solely because its compiler
/// specific in 99% of use cases.
///
/// This is from and originally designed for RustC error and its internal representations for
/// error states, GlassStates encapsulate full state in most cases (or at least should) these do not.
/// Even with a fully constructed Diagnostic message with args and Span arent as rich as
/// A pure Daemonic Error or GlassState derivation of the same state within shared context.
#[derive(Copy, PartialEq, Eq, Clone, Hash, Debug)]
pub enum DiagnosticLevel {
	/// For bugs in the compiler. Manifests as an ICE (internal compiler error) panic.
	Bug,
	
	/// An error that causes an immediate abort. Used for things like configuration errors,
	/// internal overflows, some file operation errors.
	Fatal,
	
	/// An error in the code being compiled, which prevents compilation from finishing. This is the
	/// most common case.
	Error,
	
	/// This is a strange one: lets you register an error without emitting it. If compilation ends
	/// without any other errors occurring, this will be emitted as a bug. Otherwise, it will be
	/// silently dropped. I.e. "expect other errors are emitted" semantics. Useful on code paths
	/// that should only be reached when compiling erroneous code.
	DelayedBug,
	
	/// A `force-warn` lint warning about the code being compiled. Does not prevent compilation
	/// from finishing.
	///
	/// Requires a [`LintExpectationId`] for expected lint diagnostics. In all other cases this
	/// should be `None`.
	ForceWarning,
	
	/// A warning about the code being compiled. Does not prevent compilation from finishing.
	/// Will be skipped if `can_emit_warnings` is false.
	Warning,
	
	/// A message giving additional context.
	Note,
	
	/// A note that is only emitted once.
	OnceNote,
	
	/// A message suggesting how to fix something.
	Help,
	
	/// A help that is only emitted once.
	OnceHelp,
	
	/// Similar to `Note`, but used in cases where compilation has failed. When printed for human
	/// consumption, it doesn't have any kind of `note:` label.
	FailureNote,
	
	/// Only used for lints.
	Allow,
	
	/// Only used for lints. Requires a [`LintExpectationId`] for silencing the lints.
	Expect,
}
#[derive(Copy, Clone)]
pub struct DiagnosticContextHandle<'a> {
	pub dcx: &'a DiagCtxt,
	/// Some contexts create `DiagCtxtHandle` with this field set, and thus all
	/// errors emitted with it will automatically taint when emitting errors.
	pub tainted_with_errors: Option<&'a Cell<Option<ErrorGuaranteed>>>,
}
/// A `DiagCtxt` deals with errors and other compiler output.
/// Certain errors (fatal, bug, unimpl) may cause immediate exit,
/// others log errors for later reporting.
pub struct DiagCtxt {
	pub(crate) inner: Lock<DiagCtxtInner>,
}
// Replacement sketch provided by Ada. Love that girl <3
pub enum EmitOutcome<R> { // todo:: this needs DaemonicRecursionManagement logic attached
	/// Error collected, continue walking
	Continue(R),
	/// Fatal intercepted, recovered to state
	Recovered(RecoveredState),
	/// Truly unrecoverable, must stop
	MustStop(R),
}
pub struct RecoveredState {} // todo: this is stubbed