Skip to content

Commit

Permalink
Require View: ViewMarker to avoid the leaky abstraction `fn view() …
Browse files Browse the repository at this point in the history
…-> impl View + ViewMarker`

Motivation: to avoid requiring `fn view() -> impl View + ViewMarker` and instead just using `fn view() -> impl View`

I don't see a reason for types that implement `View`, but not `ViewMarker`. This requirement has the neat side-effect of avoiding weird error-messages otherwise, in case `impl ViewMarker for T` has been forgotten for `impl View for T`.

The whole purpose AFAIK of `ViewMarker` is a workaround of the orphan rule, that something like this:
```rust
impl<T, A, V: View<T, A> + ViewMarker> ViewSequence<T, A> for V
```
is possible.

So I tried adding this as super trait requirement and it seems to be possible.
I think this makes the leaky abstraction/workaround much more feasible as it's only required now for actual `View` implementations.
  • Loading branch information
Philipp-M committed Jan 19, 2024
1 parent ea45b9f commit fe8f9b8
Show file tree
Hide file tree
Showing 4 changed files with 11 additions and 9 deletions.
12 changes: 7 additions & 5 deletions crates/xilem_core/src/view/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,16 +9,18 @@ mod memoize;
/// Arguments are
///
/// - `$viewtrait` - The name of the view trait we want to generate.
/// - `$viewmarker` - The name of the viewmarker trait as a workaround for Rust's orphan rules,
/// to allow views to be also viewsequences.
/// - `$bound` - A bound on all element types that will be used.
/// - `$cx` - The name of text context type that will be passed to the `build`/`rebuild`
/// methods, and be responsible for managing element creation & deletion.
/// - `$changeflags` - The type that reports down/up the tree. Can be used to avoid
/// doing work when we can prove nothing needs doing.
/// - `$ss` - (optional) parent traits to this trait (e.g. `:Send`). Also applied to
/// the state type requirements
/// - `$super_bounds` - (optional) parent traits to this trait (e.g. `+ Send`).
/// - `$state_bounds` - (optional) trait bounds for the associated type `State` (e.g. `: Send`).
#[macro_export]
macro_rules! generate_view_trait {
($viewtrait:ident, $bound:ident, $cx:ty, $changeflags:ty; $($ss:tt)*) => {
($viewtrait:ident, $viewmarker:ident, $bound:ident, $cx:ty, $changeflags:ty; ($($super_bounds:tt)*), ($($state_bounds:tt)*)) => {
/// A view object representing a node in the UI.
///
/// This is a central trait for representing UI. An app will generate a tree of
Expand All @@ -36,9 +38,9 @@ macro_rules! generate_view_trait {
/// and also a type for actions which are passed up the tree in message
/// propagation. During message handling, mutable access to the app state is
/// given to view nodes, which in turn can expose it to callbacks.
pub trait $viewtrait<T, A = ()> $( $ss )* {
pub trait $viewtrait<T, A = ()>: $viewmarker $( $super_bounds )* {
/// Associated state for the view.
type State $( $ss )*;
type State $( $state_bounds )*;

/// The associated element for the view.
type Element: $bound;
Expand Down
4 changes: 2 additions & 2 deletions crates/xilem_web/src/interfaces.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use crate::{Pointer, PointerMsg, View, ViewMarker};
use crate::{Pointer, PointerMsg, View};
use std::borrow::Cow;

use gloo::events::EventListenerOptions;
Expand Down Expand Up @@ -29,7 +29,7 @@ macro_rules! event_handler_mixin {
};
}

pub trait Element<T, A = ()>: View<T, A> + ViewMarker + sealed::Sealed
pub trait Element<T, A = ()>: View<T, A> + sealed::Sealed
where
Self: Sized,
{
Expand Down
2 changes: 1 addition & 1 deletion crates/xilem_web/src/view.rs
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ impl Pod {
}
}

xilem_core::generate_view_trait! {View, DomNode, Cx, ChangeFlags;}
xilem_core::generate_view_trait! {View, ViewMarker, DomNode, Cx, ChangeFlags;(),()}
xilem_core::generate_viewsequence_trait! {ViewSequence, View, ViewMarker, DomNode, Cx, ChangeFlags, Pod;}
xilem_core::generate_anyview_trait! {AnyView, View, ViewMarker, Cx, ChangeFlags, AnyNode, BoxedView;}
xilem_core::generate_memoize_view! {Memoize, MemoizeState, View, ViewMarker, Cx, ChangeFlags, static_view, memoize;}
Expand Down
2 changes: 1 addition & 1 deletion src/view/view.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ use xilem_core::{Id, IdPath};

use crate::widget::{AnyWidget, ChangeFlags, Pod, Widget};

xilem_core::generate_view_trait! {View, Widget, Cx, ChangeFlags; : Send}
xilem_core::generate_view_trait! {View, ViewMarker, Widget, Cx, ChangeFlags; (+ Send), (: Send)}
xilem_core::generate_viewsequence_trait! {ViewSequence, View, ViewMarker, Widget, Cx, ChangeFlags, Pod; : Send}
xilem_core::generate_anyview_trait! {AnyView, View, ViewMarker, Cx, ChangeFlags, AnyWidget, BoxedView; + Send}
xilem_core::generate_memoize_view! {Memoize, MemoizeState, View, ViewMarker, Cx, ChangeFlags, s, memoize; + Send}
Expand Down

0 comments on commit fe8f9b8

Please sign in to comment.