Skip to main content

lattice_mode/
error.rs

1//! Errors surfaced by the registry's activation / deactivation
2//! path.
3
4use thiserror::Error;
5
6use crate::capability::CapabilitySet;
7use crate::mode::ModeId;
8
9/// Why an activation failed.
10///
11/// Two routes, and they reach different places. The registry validates
12/// registration, kind, capabilities, conflicts and dependency presence
13/// **synchronously** before any lifecycle hook runs: those variants are the
14/// `Err` of `activate_major` / `activate_minor`, nothing ran, nothing was
15/// published, and the active set is unchanged. An error returned **by
16/// `on_activate`** (normally [`LifecycleFailed`](Self::LifecycleFailed))
17/// arrives after the activate call has already returned `Ok`; it is
18/// published as [`ModeEvent::ModeActivationFailed`](crate::ModeEvent::ModeActivationFailed)
19/// and the host rolls back.
20#[derive(Debug, Error, Clone, PartialEq, Eq)]
21pub enum ModeActivationError {
22    /// `mode` is not in the registry. Either typo'd or not
23    /// registered yet.
24    #[error("mode `{0}` is not registered")]
25    NotRegistered(ModeId),
26
27    /// Buffer lacks one or more capabilities the mode requires.
28    /// `missing` is the bitfield of the absent capabilities
29    /// (i.e. `mode.required_capabilities() - buffer_capabilities`).
30    #[error("mode `{mode}` requires capabilities `{missing:?}` that the buffer lacks")]
31    MissingCapability {
32        /// The mode that could not activate.
33        mode: ModeId,
34        /// The required capabilities the buffer does not offer.
35        missing: CapabilitySet,
36    },
37
38    /// Activating `mode` would conflict with `active` -- a
39    /// declared `conflicts_with` entry on either side. Raised when
40    /// activating a minor (directly or via an `implies` cascade); the
41    /// registry never auto-deactivates the other mode, so the caller
42    /// must deactivate it and retry if the swap is wanted.
43    #[error("mode `{mode}` conflicts with active mode `{active}`")]
44    Conflict {
45        /// The mode being activated.
46        mode: ModeId,
47        /// The already-active mode it conflicts with.
48        active: ModeId,
49    },
50
51    /// `mode` declares an `implies` dependency on `dep`, but
52    /// `dep` is not registered. Indicates a build-config bug
53    /// (a feature crate registered the parent without its
54    /// dependency).
55    #[error("mode `{mode}` implies `{dep}` which is not registered")]
56    UnregisteredDependency {
57        /// The mode declaring the dependency.
58        mode: ModeId,
59        /// The implied mode that is not registered.
60        dep: ModeId,
61    },
62
63    /// Wrong kind: caller invoked `activate_major` on a minor
64    /// mode or vice versa. Indicates a type-bug in the caller;
65    /// the trait's `kind()` answers what's expected.
66    #[error("mode `{mode}` is the wrong kind for this operation")]
67    WrongKind {
68        /// The mode whose kind did not match the call.
69        mode: ModeId,
70    },
71
72    /// A mode's `on_activate` failed. The variant a mode constructs
73    /// itself (with its own id and a human-readable reason) when setup
74    /// cannot complete — return it rather than panicking.
75    #[error("mode `{mode}` lifecycle hook failed: {reason}")]
76    LifecycleFailed {
77        /// The mode whose hook failed.
78        mode: ModeId,
79        /// Why, for the user and the log.
80        reason: String,
81    },
82
83    /// A mode tried to write a buffer-local owned by a
84    /// different mode (M.3.2.a). Reserved for the checked
85    /// `ModeContext::set_local` / `remove_local` surface the design
86    /// describes (comparing `T::OWNER_MODE` against the activating mode's
87    /// id); that surface is not implemented, so nothing constructs this
88    /// variant today. See [`BufferLocal`](crate::BufferLocal).
89    #[error("mode `{current}` cannot write buffer-local `{local}` (owner is `{owner}`)")]
90    WrongOwnerMode {
91        /// The currently-activating mode that attempted the
92        /// write.
93        current: ModeId,
94        /// The local's display name (`T::NAME`).
95        local: &'static str,
96        /// The local's declared owner mode (`T::OWNER_MODE`).
97        owner: &'static str,
98    },
99}