diff --git a/xilem/src/driver.rs b/xilem/src/driver.rs index 0ba2b3e3..9f5becf1 100644 --- a/xilem/src/driver.rs +++ b/xilem/src/driver.rs @@ -52,8 +52,12 @@ impl RawProxy for MasonryProxy { } } } + fn dyn_debug(&self) -> &dyn std::fmt::Debug { + self + } } +#[derive(Debug)] pub struct MasonryProxy(pub(crate) EventLoopProxy); impl MasonryProxy { diff --git a/xilem_core/src/any_view.rs b/xilem_core/src/any_view.rs index 4b6144ce..9d5d528e 100644 --- a/xilem_core/src/any_view.rs +++ b/xilem_core/src/any_view.rs @@ -166,6 +166,7 @@ where /// The state used by [`AnyView`]. #[doc(hidden)] #[allow(unnameable_types)] // reason: Implementation detail, public because of trait visibility rules +#[derive(Debug)] pub struct AnyViewState { inner_state: Box, /// The generation is the value which is shown diff --git a/xilem_core/src/deferred.rs b/xilem_core/src/deferred.rs index 94f47517..dc0d0f29 100644 --- a/xilem_core/src/deferred.rs +++ b/xilem_core/src/deferred.rs @@ -3,7 +3,7 @@ use alloc::boxed::Box; use alloc::sync::Arc; -use core::fmt::Display; +use core::fmt::{Debug, Display}; use core::marker::PhantomData; use crate::{DynMessage, Message, NoElement, View, ViewId, ViewPathTracker}; @@ -47,9 +47,18 @@ pub trait RawProxy: Send + Sync + 'static { // // e.g. an `Option>`? fn send_message(&self, path: Arc<[ViewId]>, message: Message) -> Result<(), ProxyError>; + /// Get the debug formatter for this proxy type. + fn dyn_debug(&self) -> &dyn Debug; +} + +impl Debug for dyn RawProxy { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + self.dyn_debug().fmt(f) + } } /// A way to send a message of an expected type to a specific view. +#[derive(Debug)] pub struct MessageProxy { proxy: Arc>, path: Arc<[ViewId]>, @@ -109,10 +118,8 @@ pub enum ProxyError { /// /// This likely requires async error handling to happen. ViewExpired(DynMessage, Arc<[ViewId]>), - #[allow(missing_docs)] - Other(&'static str), - // TODO: When core::error::Error is stabilised - // Other(Box), + /// An error specific to the driver being used. + Other(Box), } // Is it fine to use thiserror in this crate? @@ -123,17 +130,16 @@ impl Display for ProxyError { ProxyError::ViewExpired(_, _) => { f.write_fmt(format_args!("the corresponding view is no longer present")) } - - ProxyError::Other(inner) => inner.fmt(f), + ProxyError::Other(inner) => Display::fmt(inner, f), } } } -// impl std::error::Error for ProxyError { -// fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { -// match self { -// ProxyError::Other(inner) => inner.source(), -// _ => None, -// } -// } -// } +impl core::error::Error for ProxyError { + fn source(&self) -> Option<&(dyn core::error::Error + 'static)> { + match self { + ProxyError::Other(inner) => inner.source(), + _ => None, + } + } +} diff --git a/xilem_core/src/docs.rs b/xilem_core/src/docs.rs index b1ff5801..214d44a7 100644 --- a/xilem_core/src/docs.rs +++ b/xilem_core/src/docs.rs @@ -38,6 +38,7 @@ use crate::{run_once, View, ViewPathTracker}; /// A type used for documentation +#[derive(Debug)] pub enum Fake {} impl ViewPathTracker for Fake { @@ -63,6 +64,7 @@ pub trait DocsView: View {} impl DocsView for V where V: View {} /// A state type usable in a component +#[derive(Debug)] pub struct State; /// A minimal component. diff --git a/xilem_core/src/element.rs b/xilem_core/src/element.rs index 9fbb7541..e1a33d06 100644 --- a/xilem_core/src/element.rs +++ b/xilem_core/src/element.rs @@ -87,6 +87,7 @@ where /// correct `State` and `Action` types), as they do not need to actually add an element to the sequence. /// /// These views can also as the `alongside_view` in [`fork`](crate::fork). +#[derive(Debug)] pub struct NoElement; impl ViewElement for NoElement { diff --git a/xilem_core/src/lib.rs b/xilem_core/src/lib.rs index 4007b0c4..6a24e636 100644 --- a/xilem_core/src/lib.rs +++ b/xilem_core/src/lib.rs @@ -24,7 +24,6 @@ #![warn(clippy::print_stdout, clippy::print_stderr)] // TODO: Remove any items listed as "Deferred" #![deny(clippy::trivially_copy_pass_by_ref)] -#![expect(missing_debug_implementations, reason = "Deferred: Noisy")] #![expect(unused_qualifications, reason = "Deferred: Noisy")] #![expect(single_use_lifetimes, reason = "Deferred: Noisy")] #![expect(clippy::exhaustive_enums, reason = "Deferred: Noisy")] diff --git a/xilem_core/src/message.rs b/xilem_core/src/message.rs index 383f568e..c384b180 100644 --- a/xilem_core/src/message.rs +++ b/xilem_core/src/message.rs @@ -11,7 +11,7 @@ use core::ops::Deref; /// The possible outcomes from a [`View::message`] /// /// [`View::message`]: crate::View::message -#[derive(Default)] +#[derive(Default, Debug)] pub enum MessageResult { /// An action for a parent message handler to use /// diff --git a/xilem_core/src/sequence.rs b/xilem_core/src/sequence.rs index 35542e81..525192a3 100644 --- a/xilem_core/src/sequence.rs +++ b/xilem_core/src/sequence.rs @@ -197,6 +197,7 @@ where /// The state used to implement `ViewSequence` for `Option` #[allow(unnameable_types)] // reason: Implementation detail, public because of trait visibility rules +#[derive(Debug)] pub struct OptionSeqState { /// The current state. /// @@ -341,6 +342,7 @@ where // This is managed in [`create_generational_view_id`] and [`view_id_to_index_generation`] #[doc(hidden)] #[allow(unnameable_types)] // reason: Implementation detail, public because of trait visibility rules +#[derive(Debug)] pub struct VecViewState { inner_states: Vec, diff --git a/xilem_core/src/view.rs b/xilem_core/src/view.rs index 7f2a9f4e..84296e72 100644 --- a/xilem_core/src/view.rs +++ b/xilem_core/src/view.rs @@ -206,6 +206,7 @@ where } #[allow(unnameable_types)] // reason: Implementation detail, public because of trait visibility rules +#[derive(Debug)] pub struct RcState { view_state: ViewState, /// This is a flag that is set, when an inner view signifies that it requires a rebuild (via [`MessageResult::RequestRebuild`]). diff --git a/xilem_core/src/views/adapt.rs b/xilem_core/src/views/adapt.rs index 29c75c3d..d92155de 100644 --- a/xilem_core/src/views/adapt.rs +++ b/xilem_core/src/views/adapt.rs @@ -6,6 +6,7 @@ use core::marker::PhantomData; use crate::{MessageResult, Mut, View, ViewId, ViewMarker, ViewPathTracker}; /// A view that wraps a child view and modifies the state that callbacks have access to. +#[derive(Debug)] pub struct Adapt< ParentState, ParentAction, @@ -37,6 +38,7 @@ pub struct Adapt< /// /// The closure passed to [`Adapt`] should call this thunk with the child's /// app state. +#[derive(Debug)] pub struct AdaptThunk<'a, ChildState, ChildAction, Context, ChildView, Message> where Context: ViewPathTracker, diff --git a/xilem_core/src/views/fork.rs b/xilem_core/src/views/fork.rs index ace5b8cc..1ef634de 100644 --- a/xilem_core/src/views/fork.rs +++ b/xilem_core/src/views/fork.rs @@ -20,6 +20,7 @@ pub fn fork( } /// The view for [`fork`]. +#[derive(Debug)] pub struct Fork { active_view: Active, alongside_view: Alongside, diff --git a/xilem_core/src/views/map_action.rs b/xilem_core/src/views/map_action.rs index 59548944..cb95906e 100644 --- a/xilem_core/src/views/map_action.rs +++ b/xilem_core/src/views/map_action.rs @@ -1,23 +1,38 @@ // Copyright 2024 the Xilem Authors // SPDX-License-Identifier: Apache-2.0 -use core::marker::PhantomData; +use core::{fmt::Debug, marker::PhantomData}; use crate::{Mut, View, ViewId, ViewMarker, ViewPathTracker}; /// A view that maps a child [`View`] to [`View`] while providing mutable access to `State` in the map function. /// -/// This is very similar to the Elm architecture, where the parent view can update state based on the action message from the child view. +/// This is very similar to the Elm architecture, where the parent view can update state based on the action message from the child view pub struct MapAction< + V, State, ParentAction, ChildAction, - V, + Context, + Message, + // This default only exists for documentation purposes. F = fn(&mut State, ChildAction) -> ParentAction, > { map_fn: F, child: V, - phantom: PhantomData (State, ParentAction, ChildAction)>, + phantom: PhantomData (State, ParentAction, ChildAction, Context, Message)>, +} + +impl Debug + for MapAction +where + V: Debug, +{ + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + f.debug_struct("MapAction") + .field("child", &self.child) + .finish_non_exhaustive() + } } /// A view that maps a child [`View`] to [`View`] while providing mutable access to `State` in the map function. @@ -52,7 +67,7 @@ pub struct MapAction< pub fn map_action( view: V, map_fn: F, -) -> MapAction +) -> MapAction where State: 'static, ParentAction: 'static, @@ -67,19 +82,21 @@ where } } -impl ViewMarker - for MapAction +impl ViewMarker + for MapAction { } -impl +impl View - for MapAction + for MapAction where + V: View, State: 'static, ParentAction: 'static, ChildAction: 'static, - V: View, F: Fn(&mut State, ChildAction) -> ParentAction + 'static, + Context: ViewPathTracker + 'static, + Message: 'static, { type ViewState = V::ViewState; type Element = V::Element; diff --git a/xilem_core/src/views/map_state.rs b/xilem_core/src/views/map_state.rs index a70079f4..713d8947 100644 --- a/xilem_core/src/views/map_state.rs +++ b/xilem_core/src/views/map_state.rs @@ -1,7 +1,7 @@ // Copyright 2024 the Xilem Authors // SPDX-License-Identifier: Apache-2.0 -use core::marker::PhantomData; +use core::{fmt::Debug, marker::PhantomData}; use crate::{MessageResult, Mut, View, ViewId, ViewMarker, ViewPathTracker}; @@ -14,6 +14,18 @@ pub struct MapState { phantom: PhantomData (ChildState, Action, Context, Message)>, } +impl Debug + for MapState +where + V: Debug, +{ + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + f.debug_struct("MapAction") + .field("child", &self.child) + .finish_non_exhaustive() + } +} + /// A view that "extracts" state from a [`View`] to [`View`]. /// This allows modularization of views based on their state. /// diff --git a/xilem_core/src/views/memoize.rs b/xilem_core/src/views/memoize.rs index 1716bb5f..f68c3eae 100644 --- a/xilem_core/src/views/memoize.rs +++ b/xilem_core/src/views/memoize.rs @@ -1,8 +1,8 @@ // Copyright 2024 the Xilem Authors // SPDX-License-Identifier: Apache-2.0 -use core::marker::PhantomData; use core::mem::size_of; +use core::{fmt::Debug, marker::PhantomData}; use crate::{MessageResult, Mut, View, ViewId, ViewMarker, ViewPathTracker}; @@ -10,10 +10,22 @@ use crate::{MessageResult, Mut, View, ViewId, ViewMarker, ViewPathTracker}; /// /// The story of Memoization in Xilem is still being worked out, /// so the details of this view might change. -pub struct Memoize { +pub struct Memoize { data: Data, init_view: InitView, - phantom: PhantomData (State, Action)>, + phantom: PhantomData (State, Action, Context, Message)>, +} + +impl Debug + for Memoize +where + Data: Debug, +{ + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + f.debug_struct("Memoize") + .field("data", &self.data) + .finish_non_exhaustive() + } } const NON_CAPTURING_CLOSURE: &str = " @@ -41,7 +53,7 @@ It's not possible in Rust currently to check whether the (content of the) callba pub fn memoize( data: Data, init_view: InitView, -) -> Memoize +) -> Memoize where Data: PartialEq + 'static, InitView: Fn(&Data) -> V + 'static, @@ -59,19 +71,24 @@ where } #[allow(unnameable_types)] // reason: Implementation detail, public because of trait visibility rules +#[derive(Debug)] pub struct MemoizeState { view: V, view_state: VState, dirty: bool, } -impl ViewMarker for Memoize {} +impl ViewMarker + for Memoize +{ +} impl View - for Memoize + for Memoize where State: 'static, Action: 'static, - Context: ViewPathTracker, + Context: ViewPathTracker + 'static, + Message: 'static, Data: PartialEq + 'static, V: View, ViewFn: Fn(&Data) -> V + 'static, @@ -140,6 +157,12 @@ pub struct Frozen { phantom: PhantomData (State, Action)>, } +impl Debug for Frozen { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + f.debug_struct("Frozen").finish_non_exhaustive() + } +} + /// This view can be used, when the view returned by `init_view` doesn't access the `State`, other than in event callbacks /// It only evaluates the `init_view` once, when it's being created. /// diff --git a/xilem_core/src/views/one_of.rs b/xilem_core/src/views/one_of.rs index d123b994..23cdf245 100644 --- a/xilem_core/src/views/one_of.rs +++ b/xilem_core/src/views/one_of.rs @@ -22,6 +22,7 @@ pub trait PhantomElementCtx: ViewPathTracker { /// A [`View`] which can be one of nine inner view types. #[allow(missing_docs)] // On variants +#[derive(Debug)] pub enum OneOf { A(A), B(B), @@ -552,6 +553,7 @@ mod hidden { use crate::{View, ViewMarker}; #[allow(unnameable_types)] // reason: Implementation detail, public because of trait visibility rules + #[derive(Debug)] pub enum Never {} impl ViewMarker for Never {} @@ -592,6 +594,7 @@ mod hidden { } /// The state used to implement `View` for `OneOfN` #[allow(unnameable_types)] // reason: Implementation detail, public because of trait visibility rules + #[derive(Debug)] pub struct OneOfState { /// The current state of the inner view or view sequence. pub(super) inner_state: super::OneOf, diff --git a/xilem_core/src/views/run_once.rs b/xilem_core/src/views/run_once.rs index 223aa9b8..d5ecd082 100644 --- a/xilem_core/src/views/run_once.rs +++ b/xilem_core/src/views/run_once.rs @@ -75,6 +75,12 @@ pub struct RunOnce { once: F, } +impl Debug for RunOnce { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + f.debug_struct("RunOnce").finish_non_exhaustive() + } +} + impl ViewMarker for RunOnce {} impl View for RunOnce where diff --git a/xilem_web/src/lib.rs b/xilem_web/src/lib.rs index 34414928..41863c59 100644 --- a/xilem_web/src/lib.rs +++ b/xilem_web/src/lib.rs @@ -218,7 +218,10 @@ pub trait DomView: } /// See [`map_action`](`core::map_action`) - fn map_action(self, f: F) -> MapAction + fn map_action( + self, + f: F, + ) -> MapAction where State: 'static, ParentAction: 'static,