Make Xilem Views `must_use` (#742)

Also fixes `unused_qualifications` as an easy fix.

---------

Co-authored-by: Kaur Kuut <strom@nevermore.ee>
This commit is contained in:
Daniel McNab 2024-11-12 11:12:27 +00:00 committed by GitHub
parent 751bd62765
commit 41207effce
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
24 changed files with 37 additions and 23 deletions

View File

@ -33,12 +33,10 @@ type MessagePackage = (Arc<[ViewId]>, DynMessage);
impl RawProxy for MasonryProxy {
fn send_message(&self, path: Arc<[ViewId]>, message: DynMessage) -> Result<(), ProxyError> {
match self
.0
.send_event(event_loop_runner::MasonryUserEvent::Action(
async_action(path, message),
ASYNC_MARKER_WIDGET,
)) {
match self.0.send_event(MasonryUserEvent::Action(
async_action(path, message),
ASYNC_MARKER_WIDGET,
)) {
Ok(()) => Ok(()),
Err(err) => {
let MasonryUserEvent::Action(masonry::Action::Other(res), _) = err.0 else {
@ -74,7 +72,7 @@ where
fn on_action(
&mut self,
masonry_ctx: &mut masonry::DriverCtx<'_>,
widget_id: masonry::WidgetId,
widget_id: WidgetId,
action: masonry::Action,
) {
let message_result = if widget_id == ASYNC_MARKER_WIDGET {

View File

@ -18,12 +18,13 @@
)]
// TODO: Remove any items listed as "Deferred"
#![cfg_attr(not(debug_assertions), allow(unused))]
#![expect(missing_debug_implementations, reason = "Deferred: Noisy")]
#![expect(unused_qualifications, reason = "Deferred: Noisy")]
#![expect(
missing_debug_implementations,
reason = "Deferred: Noisy. Requires same lint to be addressed in Masonry"
)]
#![expect(clippy::exhaustive_enums, reason = "Deferred: Noisy")]
#![expect(clippy::match_same_arms, reason = "Deferred: Noisy")]
#![expect(clippy::missing_assert_message, reason = "Deferred: Noisy")]
#![expect(clippy::return_self_not_must_use, reason = "Deferred: Noisy")]
#![expect(elided_lifetimes_in_paths, reason = "Deferred: Noisy")]
#![expect(clippy::use_self, reason = "Deferred: Noisy")]
// https://github.com/rust-lang/rust/pull/130025
@ -65,6 +66,7 @@ pub mod view;
pub use any_view::AnyWidgetView;
pub use driver::{async_action, MasonryDriver, MasonryProxy, ASYNC_MARKER_WIDGET};
#[must_use = "A Xilem app does nothing unless ran."]
pub struct Xilem<State, Logic> {
state: State,
logic: Logic,

View File

@ -35,6 +35,7 @@ pub fn button_any_pointer<State, Action>(
}
}
#[must_use = "View values do nothing unless provided to Xilem."]
pub struct Button<F> {
label: ArcStr,
callback: F,

View File

@ -22,6 +22,7 @@ where
}
}
#[must_use = "View values do nothing unless provided to Xilem."]
pub struct Checkbox<F> {
label: ArcStr,
checked: bool,
@ -38,10 +39,7 @@ where
fn build(&self, ctx: &mut ViewCtx) -> (Self::Element, Self::ViewState) {
ctx.with_leaf_action_widget(|ctx| {
ctx.new_pod(masonry::widget::Checkbox::new(
self.checked,
self.label.clone(),
))
ctx.new_pod(widget::Checkbox::new(self.checked, self.label.clone()))
})
}

View File

@ -27,6 +27,7 @@ pub fn flex<State, Action, Seq: FlexSequence<State, Action>>(
}
}
#[must_use = "View values do nothing unless provided to Xilem."]
pub struct Flex<Seq, State, Action = ()> {
sequence: Seq,
axis: Axis,

View File

@ -26,6 +26,7 @@ pub fn grid<State, Action, Seq: GridSequence<State, Action>>(
}
}
#[must_use = "View values do nothing unless provided to Xilem."]
pub struct Grid<Seq, State, Action = ()> {
sequence: Seq,
spacing: f64,

View File

@ -31,6 +31,7 @@ pub fn image(image: &vello::peniko::Image) -> Image {
/// The [`View`] created by [`image`].
///
/// See `image`'s docs for more details.
#[must_use = "View values do nothing unless provided to Xilem."]
pub struct Image {
image: vello::peniko::Image,
object_fit: ObjectFit,

View File

@ -17,6 +17,7 @@ pub fn label(label: impl Into<ArcStr>) -> Label {
}
}
#[must_use = "View values do nothing unless provided to Xilem."]
pub struct Label {
label: ArcStr,
@ -99,7 +100,7 @@ impl<State, Action> View<State, Action, ViewCtx> for Label {
_id_path: &[ViewId],
message: DynMessage,
_app_state: &mut State,
) -> crate::MessageResult<Action> {
) -> MessageResult<Action> {
tracing::error!("Message arrived in Label::message, but Label doesn't consume any messages, this is a bug");
MessageResult::Stale(message)
}

View File

@ -21,6 +21,7 @@ where
}
}
#[must_use = "View values do nothing unless provided to Xilem."]
pub struct Portal<V, State, Action> {
child: V,
phantom: PhantomData<(State, Action)>,

View File

@ -20,9 +20,7 @@ impl<State, Action> View<State, Action, ViewCtx> for ProgressBar {
type ViewState = ();
fn build(&self, ctx: &mut ViewCtx) -> (Self::Element, Self::ViewState) {
ctx.with_leaf_action_widget(|ctx| {
ctx.new_pod(masonry::widget::ProgressBar::new(self.progress))
})
ctx.with_leaf_action_widget(|ctx| ctx.new_pod(widget::ProgressBar::new(self.progress)))
}
fn rebuild(

View File

@ -27,6 +27,7 @@ pub fn inline_prose(content: impl Into<ArcStr>) -> Prose {
prose(content).line_break_mode(LineBreaking::Overflow)
}
#[must_use = "View values do nothing unless provided to Xilem."]
pub struct Prose {
content: ArcStr,
@ -109,7 +110,7 @@ impl<State, Action> View<State, Action, ViewCtx> for Prose {
_id_path: &[ViewId],
message: DynMessage,
_app_state: &mut State,
) -> crate::MessageResult<Action> {
) -> MessageResult<Action> {
tracing::error!("Message arrived in Prose::message, but Prose doesn't consume any messages, this is a bug");
MessageResult::Stale(message)
}

View File

@ -30,6 +30,7 @@ where
}
}
#[must_use = "View values do nothing unless provided to Xilem."]
pub struct SizedBox<V, State, Action = ()> {
inner: V,
width: Option<f64>,

View File

@ -38,6 +38,7 @@ pub fn spinner() -> Spinner {
/// The [`View`] created by [`spinner`].
///
/// See `spinner`'s docs for more details.
#[must_use = "View values do nothing unless provided to Xilem."]
pub struct Spinner {
color: Option<Color>,
}

View File

@ -33,7 +33,7 @@ where
{
const {
assert!(
core::mem::size_of::<F>() == 0,
size_of::<F>() == 0,
"`task` will not be ran again when its captured variables are updated.\n\
To ignore this warning, use `task_raw`."
);

View File

@ -28,6 +28,7 @@ where
}
}
#[must_use = "View values do nothing unless provided to Xilem."]
pub struct Textbox<State, Action> {
contents: String,
on_changed: Callback<State, Action>,
@ -72,7 +73,7 @@ impl<State: 'static, Action: 'static> View<State, Action, ViewCtx> for Textbox<S
fn build(&self, ctx: &mut ViewCtx) -> (Self::Element, Self::ViewState) {
ctx.with_leaf_action_widget(|ctx| {
ctx.new_pod(
masonry::widget::Textbox::new(self.contents.clone())
widget::Textbox::new(self.contents.clone())
.with_text_brush(self.text_brush.clone())
.with_text_alignment(self.alignment),
)

View File

@ -22,6 +22,7 @@ pub fn variable_label(label: impl Into<ArcStr>) -> VariableLabel {
}
}
#[must_use = "View values do nothing unless provided to Xilem."]
pub struct VariableLabel {
label: ArcStr,
@ -149,7 +150,7 @@ impl<State, Action> View<State, Action, ViewCtx> for VariableLabel {
_id_path: &[ViewId],
message: DynMessage,
_app_state: &mut State,
) -> crate::MessageResult<Action> {
) -> MessageResult<Action> {
tracing::error!("Message arrived in Label::message, but Label doesn't consume any messages, this is a bug");
MessageResult::Stale(message)
}

View File

@ -39,7 +39,7 @@ where
{
const {
assert!(
core::mem::size_of::<F>() == 0,
size_of::<F>() == 0,
"`worker` will not be ran again when its captured variables are updated.\n\
To ignore this warning, use `worker_raw`.
To provide an updating value to this task, use the "

View File

@ -7,6 +7,7 @@ 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)]
#[must_use = "View values do nothing unless provided to Xilem."]
pub struct Adapt<
ParentState,
ParentAction,

View File

@ -21,6 +21,7 @@ pub fn fork<Active, Alongside>(
/// The view for [`fork`].
#[derive(Debug)]
#[must_use = "View values do nothing unless provided to Xilem."]
pub struct Fork<Active, Alongside> {
active_view: Active,
alongside_view: Alongside,

View File

@ -8,6 +8,7 @@ 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.
///
/// This is very similar to the Elm architecture, where the parent view can update state based on the action message from the child view
#[must_use = "View values do nothing unless provided to Xilem."]
pub struct MapAction<
V,
State,

View File

@ -8,6 +8,7 @@ use crate::{MessageResult, Mut, View, ViewId, ViewMarker, ViewPathTracker};
/// The View for [`map_state`] and [`lens`].
///
/// See their documentation for more context.
#[must_use = "View values do nothing unless provided to Xilem."]
pub struct MapState<V, F, ParentState, ChildState, Action, Context, Message> {
map_state: F,
child: V,

View File

@ -10,6 +10,7 @@ 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.
#[must_use = "View values do nothing unless provided to Xilem."]
pub struct Memoize<Data, InitView, State, Action, Context, Message> {
data: Data,
init_view: InitView,

View File

@ -23,6 +23,7 @@ pub trait PhantomElementCtx: ViewPathTracker {
/// A [`View`] which can be one of nine inner view types.
#[allow(missing_docs)] // On variants
#[derive(Debug)]
#[must_use = "View values do nothing unless provided to Xilem."]
pub enum OneOf<A = (), B = (), C = (), D = (), E = (), F = (), G = (), H = (), I = ()> {
A(A),
B(B),

View File

@ -71,6 +71,7 @@ where
/// The view type for [`run_once`].
///
/// This is a [`NoElement`] view.
#[must_use = "View values do nothing unless provided to Xilem."]
pub struct RunOnce<F> {
once: F,
}