Fix `missing_debug_implementations` in Xilem Core (#739)

This also updates to use `core::error::Error` now that it is stable.
This commit is contained in:
Daniel McNab 2024-11-11 16:51:27 +00:00 committed by GitHub
parent 23f04ca370
commit 5c61ac195b
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
17 changed files with 119 additions and 36 deletions

View File

@ -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); pub struct MasonryProxy(pub(crate) EventLoopProxy);
impl MasonryProxy { impl MasonryProxy {

View File

@ -166,6 +166,7 @@ where
/// The state used by [`AnyView`]. /// The state used by [`AnyView`].
#[doc(hidden)] #[doc(hidden)]
#[allow(unnameable_types)] // reason: Implementation detail, public because of trait visibility rules #[allow(unnameable_types)] // reason: Implementation detail, public because of trait visibility rules
#[derive(Debug)]
pub struct AnyViewState { pub struct AnyViewState {
inner_state: Box<dyn Any>, inner_state: Box<dyn Any>,
/// The generation is the value which is shown /// The generation is the value which is shown

View File

@ -3,7 +3,7 @@
use alloc::boxed::Box; use alloc::boxed::Box;
use alloc::sync::Arc; use alloc::sync::Arc;
use core::fmt::Display; use core::fmt::{Debug, Display};
use core::marker::PhantomData; use core::marker::PhantomData;
use crate::{DynMessage, Message, NoElement, View, ViewId, ViewPathTracker}; use crate::{DynMessage, Message, NoElement, View, ViewId, ViewPathTracker};
@ -47,9 +47,18 @@ pub trait RawProxy<Message = DynMessage>: Send + Sync + 'static {
// //
// e.g. an `Option<Arc<dyn FnMut(ProxyError, ProxyMessageId?)>>`? // e.g. an `Option<Arc<dyn FnMut(ProxyError, ProxyMessageId?)>>`?
fn send_message(&self, path: Arc<[ViewId]>, message: Message) -> Result<(), ProxyError>; 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<Message: 'static> Debug for dyn RawProxy<Message> {
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. /// A way to send a message of an expected type to a specific view.
#[derive(Debug)]
pub struct MessageProxy<M: Message> { pub struct MessageProxy<M: Message> {
proxy: Arc<dyn RawProxy<DynMessage>>, proxy: Arc<dyn RawProxy<DynMessage>>,
path: Arc<[ViewId]>, path: Arc<[ViewId]>,
@ -109,10 +118,8 @@ pub enum ProxyError {
/// ///
/// This likely requires async error handling to happen. /// This likely requires async error handling to happen.
ViewExpired(DynMessage, Arc<[ViewId]>), ViewExpired(DynMessage, Arc<[ViewId]>),
#[allow(missing_docs)] /// An error specific to the driver being used.
Other(&'static str), Other(Box<dyn core::error::Error + Send>),
// TODO: When core::error::Error is stabilised
// Other(Box<dyn core::error::Error + Send>),
} }
// Is it fine to use thiserror in this crate? // Is it fine to use thiserror in this crate?
@ -123,17 +130,16 @@ impl Display for ProxyError {
ProxyError::ViewExpired(_, _) => { ProxyError::ViewExpired(_, _) => {
f.write_fmt(format_args!("the corresponding view is no longer present")) f.write_fmt(format_args!("the corresponding view is no longer present"))
} }
ProxyError::Other(inner) => Display::fmt(inner, f),
ProxyError::Other(inner) => inner.fmt(f),
} }
} }
} }
// impl std::error::Error for ProxyError { impl core::error::Error for ProxyError {
// fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { fn source(&self) -> Option<&(dyn core::error::Error + 'static)> {
// match self { match self {
// ProxyError::Other(inner) => inner.source(), ProxyError::Other(inner) => inner.source(),
// _ => None, _ => None,
// } }
// } }
// } }

View File

@ -38,6 +38,7 @@
use crate::{run_once, View, ViewPathTracker}; use crate::{run_once, View, ViewPathTracker};
/// A type used for documentation /// A type used for documentation
#[derive(Debug)]
pub enum Fake {} pub enum Fake {}
impl ViewPathTracker for Fake { impl ViewPathTracker for Fake {
@ -63,6 +64,7 @@ pub trait DocsView<State, Action = ()>: View<State, Action, Fake> {}
impl<V, State, Action> DocsView<State, Action> for V where V: View<State, Action, Fake> {} impl<V, State, Action> DocsView<State, Action> for V where V: View<State, Action, Fake> {}
/// A state type usable in a component /// A state type usable in a component
#[derive(Debug)]
pub struct State; pub struct State;
/// A minimal component. /// A minimal component.

View File

@ -87,6 +87,7 @@ where
/// correct `State` and `Action` types), as they do not need to actually add an element to the sequence. /// 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). /// These views can also as the `alongside_view` in [`fork`](crate::fork).
#[derive(Debug)]
pub struct NoElement; pub struct NoElement;
impl ViewElement for NoElement { impl ViewElement for NoElement {

View File

@ -24,7 +24,6 @@
#![warn(clippy::print_stdout, clippy::print_stderr)] #![warn(clippy::print_stdout, clippy::print_stderr)]
// TODO: Remove any items listed as "Deferred" // TODO: Remove any items listed as "Deferred"
#![deny(clippy::trivially_copy_pass_by_ref)] #![deny(clippy::trivially_copy_pass_by_ref)]
#![expect(missing_debug_implementations, reason = "Deferred: Noisy")]
#![expect(unused_qualifications, reason = "Deferred: Noisy")] #![expect(unused_qualifications, reason = "Deferred: Noisy")]
#![expect(single_use_lifetimes, reason = "Deferred: Noisy")] #![expect(single_use_lifetimes, reason = "Deferred: Noisy")]
#![expect(clippy::exhaustive_enums, reason = "Deferred: Noisy")] #![expect(clippy::exhaustive_enums, reason = "Deferred: Noisy")]

View File

@ -11,7 +11,7 @@ use core::ops::Deref;
/// The possible outcomes from a [`View::message`] /// The possible outcomes from a [`View::message`]
/// ///
/// [`View::message`]: crate::View::message /// [`View::message`]: crate::View::message
#[derive(Default)] #[derive(Default, Debug)]
pub enum MessageResult<Action, Message = DynMessage> { pub enum MessageResult<Action, Message = DynMessage> {
/// An action for a parent message handler to use /// An action for a parent message handler to use
/// ///

View File

@ -197,6 +197,7 @@ where
/// The state used to implement `ViewSequence` for `Option<impl ViewSequence>` /// The state used to implement `ViewSequence` for `Option<impl ViewSequence>`
#[allow(unnameable_types)] // reason: Implementation detail, public because of trait visibility rules #[allow(unnameable_types)] // reason: Implementation detail, public because of trait visibility rules
#[derive(Debug)]
pub struct OptionSeqState<InnerState> { pub struct OptionSeqState<InnerState> {
/// The current state. /// The current state.
/// ///
@ -341,6 +342,7 @@ where
// This is managed in [`create_generational_view_id`] and [`view_id_to_index_generation`] // This is managed in [`create_generational_view_id`] and [`view_id_to_index_generation`]
#[doc(hidden)] #[doc(hidden)]
#[allow(unnameable_types)] // reason: Implementation detail, public because of trait visibility rules #[allow(unnameable_types)] // reason: Implementation detail, public because of trait visibility rules
#[derive(Debug)]
pub struct VecViewState<InnerState> { pub struct VecViewState<InnerState> {
inner_states: Vec<InnerState>, inner_states: Vec<InnerState>,

View File

@ -206,6 +206,7 @@ where
} }
#[allow(unnameable_types)] // reason: Implementation detail, public because of trait visibility rules #[allow(unnameable_types)] // reason: Implementation detail, public because of trait visibility rules
#[derive(Debug)]
pub struct RcState<ViewState> { pub struct RcState<ViewState> {
view_state: ViewState, view_state: ViewState,
/// This is a flag that is set, when an inner view signifies that it requires a rebuild (via [`MessageResult::RequestRebuild`]). /// This is a flag that is set, when an inner view signifies that it requires a rebuild (via [`MessageResult::RequestRebuild`]).

View File

@ -6,6 +6,7 @@ use core::marker::PhantomData;
use crate::{MessageResult, Mut, View, ViewId, ViewMarker, ViewPathTracker}; use crate::{MessageResult, Mut, View, ViewId, ViewMarker, ViewPathTracker};
/// A view that wraps a child view and modifies the state that callbacks have access to. /// A view that wraps a child view and modifies the state that callbacks have access to.
#[derive(Debug)]
pub struct Adapt< pub struct Adapt<
ParentState, ParentState,
ParentAction, ParentAction,
@ -37,6 +38,7 @@ pub struct Adapt<
/// ///
/// The closure passed to [`Adapt`] should call this thunk with the child's /// The closure passed to [`Adapt`] should call this thunk with the child's
/// app state. /// app state.
#[derive(Debug)]
pub struct AdaptThunk<'a, ChildState, ChildAction, Context, ChildView, Message> pub struct AdaptThunk<'a, ChildState, ChildAction, Context, ChildView, Message>
where where
Context: ViewPathTracker, Context: ViewPathTracker,

View File

@ -20,6 +20,7 @@ pub fn fork<Active, Alongside>(
} }
/// The view for [`fork`]. /// The view for [`fork`].
#[derive(Debug)]
pub struct Fork<Active, Alongside> { pub struct Fork<Active, Alongside> {
active_view: Active, active_view: Active,
alongside_view: Alongside, alongside_view: Alongside,

View File

@ -1,23 +1,38 @@
// Copyright 2024 the Xilem Authors // Copyright 2024 the Xilem Authors
// SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: Apache-2.0
use core::marker::PhantomData; use core::{fmt::Debug, marker::PhantomData};
use crate::{Mut, View, ViewId, ViewMarker, ViewPathTracker}; use crate::{Mut, View, ViewId, ViewMarker, ViewPathTracker};
/// A view that maps a child [`View<State,ChildAction,_>`] to [`View<State,ParentAction,_>`] while providing mutable access to `State` in the map function. /// A view that maps a child [`View<State,ChildAction,_>`] to [`View<State,ParentAction,_>`] 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< pub struct MapAction<
V,
State, State,
ParentAction, ParentAction,
ChildAction, ChildAction,
V, Context,
Message,
// This default only exists for documentation purposes.
F = fn(&mut State, ChildAction) -> ParentAction, F = fn(&mut State, ChildAction) -> ParentAction,
> { > {
map_fn: F, map_fn: F,
child: V, child: V,
phantom: PhantomData<fn() -> (State, ParentAction, ChildAction)>, phantom: PhantomData<fn() -> (State, ParentAction, ChildAction, Context, Message)>,
}
impl<V, State, ParentAction, ChildAction, Context, Message, F> Debug
for MapAction<V, State, ParentAction, ChildAction, Context, Message, F>
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<State,ChildAction,_>`] to [`View<State,ParentAction,_>`] while providing mutable access to `State` in the map function. /// A view that maps a child [`View<State,ChildAction,_>`] to [`View<State,ParentAction,_>`] while providing mutable access to `State` in the map function.
@ -52,7 +67,7 @@ pub struct MapAction<
pub fn map_action<State, ParentAction, ChildAction, Context: ViewPathTracker, Message, V, F>( pub fn map_action<State, ParentAction, ChildAction, Context: ViewPathTracker, Message, V, F>(
view: V, view: V,
map_fn: F, map_fn: F,
) -> MapAction<State, ParentAction, ChildAction, V, F> ) -> MapAction<V, State, ParentAction, ChildAction, Context, Message, F>
where where
State: 'static, State: 'static,
ParentAction: 'static, ParentAction: 'static,
@ -67,19 +82,21 @@ where
} }
} }
impl<State, ParentAction, ChildAction, V, F> ViewMarker impl<V, State, ParentAction, ChildAction, F, Context, Message> ViewMarker
for MapAction<State, ParentAction, ChildAction, V, F> for MapAction<V, State, ParentAction, ChildAction, Context, Message, F>
{ {
} }
impl<State, ParentAction, ChildAction, Context: ViewPathTracker, Message, V, F> impl<V, State, ParentAction, ChildAction, Context, Message, F>
View<State, ParentAction, Context, Message> View<State, ParentAction, Context, Message>
for MapAction<State, ParentAction, ChildAction, V, F> for MapAction<V, State, ParentAction, ChildAction, Context, Message, F>
where where
V: View<State, ChildAction, Context, Message>,
State: 'static, State: 'static,
ParentAction: 'static, ParentAction: 'static,
ChildAction: 'static, ChildAction: 'static,
V: View<State, ChildAction, Context, Message>,
F: Fn(&mut State, ChildAction) -> ParentAction + 'static, F: Fn(&mut State, ChildAction) -> ParentAction + 'static,
Context: ViewPathTracker + 'static,
Message: 'static,
{ {
type ViewState = V::ViewState; type ViewState = V::ViewState;
type Element = V::Element; type Element = V::Element;

View File

@ -1,7 +1,7 @@
// Copyright 2024 the Xilem Authors // Copyright 2024 the Xilem Authors
// SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: Apache-2.0
use core::marker::PhantomData; use core::{fmt::Debug, marker::PhantomData};
use crate::{MessageResult, Mut, View, ViewId, ViewMarker, ViewPathTracker}; use crate::{MessageResult, Mut, View, ViewId, ViewMarker, ViewPathTracker};
@ -14,6 +14,18 @@ pub struct MapState<V, F, ParentState, ChildState, Action, Context, Message> {
phantom: PhantomData<fn(ParentState) -> (ChildState, Action, Context, Message)>, phantom: PhantomData<fn(ParentState) -> (ChildState, Action, Context, Message)>,
} }
impl<V, F, ParentState, ChildState, Action, Context, Message> Debug
for MapState<V, F, ParentState, ChildState, Action, Context, Message>
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<ParentState,_,_>`] to [`View<ChildState,_,_>`]. /// A view that "extracts" state from a [`View<ParentState,_,_>`] to [`View<ChildState,_,_>`].
/// This allows modularization of views based on their state. /// This allows modularization of views based on their state.
/// ///

View File

@ -1,8 +1,8 @@
// Copyright 2024 the Xilem Authors // Copyright 2024 the Xilem Authors
// SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: Apache-2.0
use core::marker::PhantomData;
use core::mem::size_of; use core::mem::size_of;
use core::{fmt::Debug, marker::PhantomData};
use crate::{MessageResult, Mut, View, ViewId, ViewMarker, ViewPathTracker}; 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, /// The story of Memoization in Xilem is still being worked out,
/// so the details of this view might change. /// so the details of this view might change.
pub struct Memoize<Data, InitView, State, Action> { pub struct Memoize<Data, InitView, State, Action, Context, Message> {
data: Data, data: Data,
init_view: InitView, init_view: InitView,
phantom: PhantomData<fn() -> (State, Action)>, phantom: PhantomData<fn() -> (State, Action, Context, Message)>,
}
impl<Data, InitView, State, Action, Context, Message> Debug
for Memoize<Data, InitView, State, Action, Context, Message>
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 = " 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<State, Action, Context, Message, Data, V, InitView>( pub fn memoize<State, Action, Context, Message, Data, V, InitView>(
data: Data, data: Data,
init_view: InitView, init_view: InitView,
) -> Memoize<Data, InitView, State, Action> ) -> Memoize<Data, InitView, State, Action, Context, Message>
where where
Data: PartialEq + 'static, Data: PartialEq + 'static,
InitView: Fn(&Data) -> V + 'static, InitView: Fn(&Data) -> V + 'static,
@ -59,19 +71,24 @@ where
} }
#[allow(unnameable_types)] // reason: Implementation detail, public because of trait visibility rules #[allow(unnameable_types)] // reason: Implementation detail, public because of trait visibility rules
#[derive(Debug)]
pub struct MemoizeState<V, VState> { pub struct MemoizeState<V, VState> {
view: V, view: V,
view_state: VState, view_state: VState,
dirty: bool, dirty: bool,
} }
impl<Data, ViewFn, State, Action> ViewMarker for Memoize<Data, ViewFn, State, Action> {} impl<Data, ViewFn, State, Action, Context, Message> ViewMarker
for Memoize<Data, ViewFn, State, Action, Context, Message>
{
}
impl<State, Action, Context, Data, V, ViewFn, Message> View<State, Action, Context, Message> impl<State, Action, Context, Data, V, ViewFn, Message> View<State, Action, Context, Message>
for Memoize<Data, ViewFn, State, Action> for Memoize<Data, ViewFn, State, Action, Context, Message>
where where
State: 'static, State: 'static,
Action: 'static, Action: 'static,
Context: ViewPathTracker, Context: ViewPathTracker + 'static,
Message: 'static,
Data: PartialEq + 'static, Data: PartialEq + 'static,
V: View<State, Action, Context, Message>, V: View<State, Action, Context, Message>,
ViewFn: Fn(&Data) -> V + 'static, ViewFn: Fn(&Data) -> V + 'static,
@ -140,6 +157,12 @@ pub struct Frozen<InitView, State, Action> {
phantom: PhantomData<fn() -> (State, Action)>, phantom: PhantomData<fn() -> (State, Action)>,
} }
impl<InitView, State, Action> Debug for Frozen<InitView, State, Action> {
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 /// 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. /// It only evaluates the `init_view` once, when it's being created.
/// ///

View File

@ -22,6 +22,7 @@ pub trait PhantomElementCtx: ViewPathTracker {
/// A [`View`] which can be one of nine inner view types. /// A [`View`] which can be one of nine inner view types.
#[allow(missing_docs)] // On variants #[allow(missing_docs)] // On variants
#[derive(Debug)]
pub enum OneOf<A = (), B = (), C = (), D = (), E = (), F = (), G = (), H = (), I = ()> { pub enum OneOf<A = (), B = (), C = (), D = (), E = (), F = (), G = (), H = (), I = ()> {
A(A), A(A),
B(B), B(B),
@ -552,6 +553,7 @@ mod hidden {
use crate::{View, ViewMarker}; use crate::{View, ViewMarker};
#[allow(unnameable_types)] // reason: Implementation detail, public because of trait visibility rules #[allow(unnameable_types)] // reason: Implementation detail, public because of trait visibility rules
#[derive(Debug)]
pub enum Never {} pub enum Never {}
impl ViewMarker for Never {} impl ViewMarker for Never {}
@ -592,6 +594,7 @@ mod hidden {
} }
/// The state used to implement `View` for `OneOfN` /// The state used to implement `View` for `OneOfN`
#[allow(unnameable_types)] // reason: Implementation detail, public because of trait visibility rules #[allow(unnameable_types)] // reason: Implementation detail, public because of trait visibility rules
#[derive(Debug)]
pub struct OneOfState<A, B, C, D, E, F, G, H, I> { pub struct OneOfState<A, B, C, D, E, F, G, H, I> {
/// The current state of the inner view or view sequence. /// The current state of the inner view or view sequence.
pub(super) inner_state: super::OneOf<A, B, C, D, E, F, G, H, I>, pub(super) inner_state: super::OneOf<A, B, C, D, E, F, G, H, I>,

View File

@ -75,6 +75,12 @@ pub struct RunOnce<F> {
once: F, once: F,
} }
impl<F> Debug for RunOnce<F> {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
f.debug_struct("RunOnce").finish_non_exhaustive()
}
}
impl<F> ViewMarker for RunOnce<F> {} impl<F> ViewMarker for RunOnce<F> {}
impl<F, State, Action, Context, Message> View<State, Action, Context, Message> for RunOnce<F> impl<F, State, Action, Context, Message> View<State, Action, Context, Message> for RunOnce<F>
where where

View File

@ -218,7 +218,10 @@ pub trait DomView<State, Action = ()>:
} }
/// See [`map_action`](`core::map_action`) /// See [`map_action`](`core::map_action`)
fn map_action<ParentAction, F>(self, f: F) -> MapAction<State, ParentAction, Action, Self, F> fn map_action<ParentAction, F>(
self,
f: F,
) -> MapAction<Self, State, ParentAction, Action, ViewCtx, DynMessage, F>
where where
State: 'static, State: 'static,
ParentAction: 'static, ParentAction: 'static,