Skip to content

Commit

Permalink
refactor(hydroflow_lang, hydroflow): somewhat improve demux_enum()
Browse files Browse the repository at this point in the history
…error messages, fix hydro-project#1201 (hydro-project#1204)
  • Loading branch information
MingweiSamuel committed May 18, 2024
1 parent f1c7f90 commit 7e36ab1
Show file tree
Hide file tree
Showing 12 changed files with 123 additions and 409 deletions.
48 changes: 12 additions & 36 deletions hydroflow/src/util/demux_enum.rs
Original file line number Diff line number Diff line change
@@ -1,43 +1,19 @@
//! Traits for the `demux_enum` derive and operator.
//! Trait for the `demux_enum` derive and operator.

pub use hydroflow_macro::DemuxEnum;
use pusherator::demux::PusheratorList;
use pusherator::Pusherator;
use variadics::Variadic;

/// Trait for use with the `demux_enum` operator.
///
/// This trait is meant to be derived: `#[derive(DemuEnum)]`.
pub trait DemuxEnum<Nexts>: DemuxEnumItems
where
Nexts: PusheratorListForItems<Self::Items>,
{
/// Pushes self into the corresponding output pusherator.
fn demux_enum(self, outputs: &mut Nexts);
}

/// Fixed output item list for [`DemuxEnum`].
///
/// This trait is meant to be derived: `#[derive(DemuEnum)]`.
pub trait DemuxEnumItems {
/// A `var_type!(...)` list of items corresponding to each variant's output type.
type Items: Variadic;
}

/// Helper trait to bound a [`PusheratorList`] variadic to some coresponding item list variadic.
/// This trait is meant to be derived: `#[derive(DemuxEnum)]`.
///
/// A pusherator list `var_type!(PushA, PushB, PushC)` implements `PusheratorListForItems<var_type!(ItemA, ItemB, ItemC)>`,
/// where `PushA: Pusherator<Item = ItemA>`, etc.
pub trait PusheratorListForItems<Items>: PusheratorList
where
Items: Variadic,
{
}
impl<HeadPush, RestPush, Head, Rest> PusheratorListForItems<(Head, Rest)> for (HeadPush, RestPush)
where
HeadPush: Pusherator<Item = Head>,
RestPush: PusheratorListForItems<Rest>,
Rest: Variadic,
{
/// The derive will implement this such that `Outputs` can be any tuple where each item is a
/// `Pusherator` that corresponds to each of the variants of the tuple, in alphabetic order.
#[diagnostic::on_unimplemented(
note = "Use `#[derive(hydroflow::DemuxEnum)]`",
note = "Ensure there is exactly one output for each enum variant.",
note = "Ensure that the type for each output is a tuple of the field for the variant: `()`, `(a,)`, or `(a, b, ...)`."
)]
pub trait DemuxEnum<Outputs> {
/// Pushes self into the corresponding output pusherator in `outputs`.
fn demux_enum(self, outputs: &mut Outputs);
}
impl PusheratorListForItems<()> for () {}
85 changes: 7 additions & 78 deletions hydroflow/tests/compile-fail/surface_demuxenum_notenum.stderr
Original file line number Diff line number Diff line change
@@ -1,23 +1,3 @@
error[E0277]: the trait bound `Shape: DemuxEnumItems` is not satisfied
--> tests/compile-fail/surface_demuxenum_notenum.rs:12:28
|
12 | ]) -> demux_enum::<Shape>();
| ^^^^^ the trait `DemuxEnumItems` is not implemented for `Shape`
|
note: required by a bound in `check_impl_demux_enum`
--> tests/compile-fail/surface_demuxenum_notenum.rs:8:18
|
8 | let mut df = hydroflow_syntax! {
| __________________^
9 | | my_demux = source_iter([
10 | | Shape { area: 10.0 },
11 | | Shape { area: 9.0 },
... |
16 | | my_demux[Ellipse] -> for_each(std::mem::drop);
17 | | };
| |_____^ required by this bound in `check_impl_demux_enum`
= note: this error originates in the macro `hydroflow_syntax` (in Nightly builds, run with -Z macro-backtrace for more info)

error[E0223]: ambiguous associated type
--> tests/compile-fail/surface_demuxenum_notenum.rs:14:18
|
Expand Down Expand Up @@ -62,72 +42,21 @@ help: if there were a trait named `Example` with associated type `Square` implem
15 | my_demux[<Shape as Example>::Square] -> for_each(std::mem::drop);
| ~~~~~~~~~~~~~~~~~~~~~~~~~~

error[E0277]: the trait bound `Shape: DemuxEnumItems` is not satisfied
--> tests/compile-fail/surface_demuxenum_notenum.rs:12:15
|
12 | ]) -> demux_enum::<Shape>();
| ^^^^^^^^^^^^^^^^^^^^^ the trait `DemuxEnumItems` is not implemented for `Shape`

error[E0277]: the trait bound `Shape: DemuxEnum<_>` is not satisfied
--> tests/compile-fail/surface_demuxenum_notenum.rs:12:28
|
12 | ]) -> demux_enum::<Shape>();
| ^^^^^ the trait `DemuxEnum<_>` is not implemented for `Shape`
|
note: required by a bound in `__typeguard_demux_enum_fn`
--> tests/compile-fail/surface_demuxenum_notenum.rs:8:18
|
8 | let mut df = hydroflow_syntax! {
| __________________^
9 | | my_demux = source_iter([
10 | | Shape { area: 10.0 },
11 | | Shape { area: 9.0 },
... |
16 | | my_demux[Ellipse] -> for_each(std::mem::drop);
17 | | };
| |_____^ required by this bound in `__typeguard_demux_enum_fn`
= note: this error originates in the macro `hydroflow_syntax` (in Nightly builds, run with -Z macro-backtrace for more info)

error[E0277]: the trait bound `Shape: DemuxEnum<(impl Pusherator<Item = _>, (impl Pusherator<Item = _>, (impl Pusherator<Item = _>, (impl Pusherator<Item = _>, ()))))>` is not satisfied
--> tests/compile-fail/surface_demuxenum_notenum.rs:12:15
|
12 | ]) -> demux_enum::<Shape>();
| ^^^^^^^^^^^^^^^^^^^^^ the trait `DemuxEnum<(impl Pusherator<Item = _>, (impl Pusherator<Item = _>, (impl Pusherator<Item = _>, (impl Pusherator<Item = _>, ()))))>` is not implemented for `Shape`
|
note: required by a bound in `__typeguard_demux_enum_fn`
--> tests/compile-fail/surface_demuxenum_notenum.rs:8:18
|
8 | let mut df = hydroflow_syntax! {
| __________________^
| __________________-
9 | | my_demux = source_iter([
10 | | Shape { area: 10.0 },
11 | | Shape { area: 9.0 },
... |
16 | | my_demux[Ellipse] -> for_each(std::mem::drop);
17 | | };
| |_____^ required by this bound in `__typeguard_demux_enum_fn`
= note: this error originates in the macro `hydroflow_syntax` (in Nightly builds, run with -Z macro-backtrace for more info)

error[E0277]: the trait bound `Shape: DemuxEnum<(impl Pusherator<Item = _>, (impl Pusherator<Item = _>, (impl Pusherator<Item = _>, (impl Pusherator<Item = _>, ()))))>` is not satisfied
--> tests/compile-fail/surface_demuxenum_notenum.rs:9:20
|
9 | my_demux = source_iter([
| ____________________^
10 | | Shape { area: 10.0 },
11 | | Shape { area: 9.0 },
12 | | ]) -> demux_enum::<Shape>();
| |___________________________________^ the trait `DemuxEnum<(impl Pusherator<Item = _>, (impl Pusherator<Item = _>, (impl Pusherator<Item = _>, (impl Pusherator<Item = _>, ()))))>` is not implemented for `Shape`
|
note: required by a bound in `__typeguard_demux_enum_fn`
--> tests/compile-fail/surface_demuxenum_notenum.rs:8:18
|
8 | let mut df = hydroflow_syntax! {
| __________________^
9 | | my_demux = source_iter([
10 | | Shape { area: 10.0 },
11 | | Shape { area: 9.0 },
| | ^^^^^^^^^^^^^^^^^^^^^ the trait `DemuxEnum<_>` is not implemented for `Shape`
... |
16 | | my_demux[Ellipse] -> for_each(std::mem::drop);
17 | | };
| |_____^ required by this bound in `__typeguard_demux_enum_fn`
= note: this error originates in the macro `hydroflow_syntax` (in Nightly builds, run with -Z macro-backtrace for more info)
| |_____- required by a bound introduced by this call
|
= note: Use `#[derive(hydroflow::DemuxEnum)]`
= note: Ensure there is exactly one output for each enum variant.
= note: Ensure that the type for each output is a tuple of the field for the variant: `()`, `(a,)`, or `(a, b, ...)`.
27 changes: 19 additions & 8 deletions hydroflow/tests/compile-fail/surface_demuxenum_port_extra.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -8,20 +8,31 @@ error[E0599]: no variant named `Ellipse` found for enum `Shape`
| ^^^^^^^ variant not found in `Shape`

error[E0308]: mismatched types
--> tests/compile-fail/surface_demuxenum_port_extra.rs:12:18
--> tests/compile-fail/surface_demuxenum_port_extra.rs:17:15
|
12 | let mut df = hydroflow_syntax! {
| __________________^
| __________________-
13 | | my_demux = source_iter([
14 | | Shape::Rectangle { w: 10.0, h: 8.0 },
15 | | Shape::Square(9.0),
... |
16 | | Shape::Circle { r: 5.0 },
17 | | ]) -> demux_enum::<Shape>();
| | ^^^^^^^^^^^^^^^^^^^^^ expected a tuple with 3 elements, found one with 4 elements
18 | | my_demux[Rectangle] -> for_each(std::mem::drop);
| | ------------------------ one of the found opaque types
19 | | my_demux[Circle] -> for_each(std::mem::drop);
| | ------------------------ one of the found opaque types
20 | | my_demux[Square] -> for_each(std::mem::drop);
| | ------------------------ the found opaque type
| | ------------------------ one of the found opaque types
21 | | my_demux[Ellipse] -> for_each(std::mem::drop);
| | ------------------------ one of the found opaque types
22 | | };
| |_____^ expected `()`, found `(impl Pusherator<Item = _>, ())`
| |_____- arguments to this function are incorrect
|
= note: expected unit type `()`
found tuple `(impl Pusherator<Item = _>, ())`
= note: this error originates in the macro `$crate::var_expr` which comes from the expansion of the macro `hydroflow_syntax` (in Nightly builds, run with -Z macro-backtrace for more info)
= note: expected mutable reference `&mut (_, _, _)`
found mutable reference `&mut (impl Pusherator<Item = _>, impl Pusherator<Item = _>, impl Pusherator<Item = _>, impl Pusherator<Item = _>)`
note: method defined here
--> src/util/demux_enum.rs
|
| fn demux_enum(self, outputs: &mut Outputs);
| ^^^^^^^^^^
23 changes: 16 additions & 7 deletions hydroflow/tests/compile-fail/surface_demuxenum_port_missing.stderr
Original file line number Diff line number Diff line change
@@ -1,16 +1,25 @@
error[E0308]: mismatched types
--> tests/compile-fail/surface_demuxenum_port_missing.rs:12:18
--> tests/compile-fail/surface_demuxenum_port_missing.rs:17:15
|
12 | let mut df = hydroflow_syntax! {
| __________________^
| __________________-
13 | | my_demux = source_iter([
14 | | Shape::Rectangle { w: 10.0, h: 8.0 },
15 | | Shape::Square(9.0),
... |
16 | | Shape::Circle { r: 5.0 },
17 | | ]) -> demux_enum::<Shape>();
| | ^^^^^^^^^^^^^^^^^^^^^ expected a tuple with 3 elements, found one with 2 elements
18 | | my_demux[Rectangle] -> for_each(std::mem::drop);
| | ------------------------ one of the found opaque types
19 | | my_demux[Circle] -> for_each(std::mem::drop);
| | ------------------------ one of the found opaque types
20 | | };
| |_____^ expected `(_, ())`, found `()`
| |_____- arguments to this function are incorrect
|
= note: expected tuple `(_, ())`
found unit type `()`
= note: this error originates in the macro `$crate::var_expr` which comes from the expansion of the macro `hydroflow_syntax` (in Nightly builds, run with -Z macro-backtrace for more info)
= note: expected mutable reference `&mut (_, _, _)`
found mutable reference `&mut (impl Pusherator<Item = _>, impl Pusherator<Item = _>)`
note: method defined here
--> src/util/demux_enum.rs
|
| fn demux_enum(self, outputs: &mut Outputs);
| ^^^^^^^^^^
96 changes: 10 additions & 86 deletions hydroflow/tests/compile-fail/surface_demuxenum_wrongenum.stderr
Original file line number Diff line number Diff line change
@@ -1,24 +1,3 @@
error[E0277]: the trait bound `std::option::Option<()>: DemuxEnumItems` is not satisfied
--> tests/compile-fail/surface_demuxenum_wrongenum.rs:17:28
|
17 | ]) -> demux_enum::<Option<()>>();
| ^^^^^^^^^^ the trait `DemuxEnumItems` is not implemented for `std::option::Option<()>`
|
= help: the trait `DemuxEnumItems` is implemented for `Shape`
note: required by a bound in `check_impl_demux_enum`
--> tests/compile-fail/surface_demuxenum_wrongenum.rs:12:18
|
12 | let mut df = hydroflow_syntax! {
| __________________^
13 | | my_demux = source_iter([
14 | | Shape::Rectangle { w: 10.0, h: 8.0 },
15 | | Shape::Square(9.0),
... |
20 | | my_demux[Square] -> for_each(std::mem::drop);
21 | | };
| |_____^ required by this bound in `check_impl_demux_enum`
= note: this error originates in the macro `hydroflow_syntax` (in Nightly builds, run with -Z macro-backtrace for more info)

error[E0599]: no variant named `Circle` found for enum `std::option::Option<()>`
--> tests/compile-fail/surface_demuxenum_wrongenum.rs:19:18
|
Expand All @@ -37,55 +16,26 @@ error[E0599]: no variant named `Square` found for enum `std::option::Option<()>`
20 | my_demux[Square] -> for_each(std::mem::drop);
| ^^^^^^ variant not found in `std::option::Option<()>`

error[E0277]: the trait bound `std::option::Option<()>: DemuxEnumItems` is not satisfied
--> tests/compile-fail/surface_demuxenum_wrongenum.rs:17:15
|
17 | ]) -> demux_enum::<Option<()>>();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `DemuxEnumItems` is not implemented for `std::option::Option<()>`
|
= help: the trait `DemuxEnumItems` is implemented for `Shape`

error[E0277]: the trait bound `std::option::Option<()>: DemuxEnum<_>` is not satisfied
--> tests/compile-fail/surface_demuxenum_wrongenum.rs:17:28
|
17 | ]) -> demux_enum::<Option<()>>();
| ^^^^^^^^^^ the trait `DemuxEnum<_>` is not implemented for `std::option::Option<()>`
|
= help: the trait `DemuxEnum<(__PusheratorCircle, (__PusheratorRectangle, (__PusheratorSquare, ())))>` is implemented for `Shape`
note: required by a bound in `__typeguard_demux_enum_fn`
--> tests/compile-fail/surface_demuxenum_wrongenum.rs:12:18
|
12 | let mut df = hydroflow_syntax! {
| __________________^
13 | | my_demux = source_iter([
14 | | Shape::Rectangle { w: 10.0, h: 8.0 },
15 | | Shape::Square(9.0),
... |
20 | | my_demux[Square] -> for_each(std::mem::drop);
21 | | };
| |_____^ required by this bound in `__typeguard_demux_enum_fn`
= note: this error originates in the macro `hydroflow_syntax` (in Nightly builds, run with -Z macro-backtrace for more info)

error[E0277]: the trait bound `std::option::Option<()>: DemuxEnum<(impl Pusherator<Item = _>, (impl Pusherator<Item = _>, (impl Pusherator<Item = _>, ())))>` is not satisfied
--> tests/compile-fail/surface_demuxenum_wrongenum.rs:17:15
|
17 | ]) -> demux_enum::<Option<()>>();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `DemuxEnum<(impl Pusherator<Item = _>, (impl Pusherator<Item = _>, (impl Pusherator<Item = _>, ())))>` is not implemented for `std::option::Option<()>`
|
= help: the trait `DemuxEnum<(__PusheratorCircle, (__PusheratorRectangle, (__PusheratorSquare, ())))>` is implemented for `Shape`
note: required by a bound in `__typeguard_demux_enum_fn`
--> tests/compile-fail/surface_demuxenum_wrongenum.rs:12:18
|
12 | let mut df = hydroflow_syntax! {
| __________________^
| __________________-
13 | | my_demux = source_iter([
14 | | Shape::Rectangle { w: 10.0, h: 8.0 },
15 | | Shape::Square(9.0),
16 | | Shape::Circle { r: 5.0 },
17 | | ]) -> demux_enum::<Option<()>>();
| | ^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `DemuxEnum<_>` is not implemented for `std::option::Option<()>`
... |
20 | | my_demux[Square] -> for_each(std::mem::drop);
21 | | };
| |_____^ required by this bound in `__typeguard_demux_enum_fn`
= note: this error originates in the macro `hydroflow_syntax` (in Nightly builds, run with -Z macro-backtrace for more info)
| |_____- required by a bound introduced by this call
|
= note: Use `#[derive(hydroflow::DemuxEnum)]`
= note: Ensure there is exactly one output for each enum variant.
= note: Ensure that the type for each output is a tuple of the field for the variant: `()`, `(a,)`, or `(a, b, ...)`.
= help: the trait `DemuxEnum<(__PusheratorCircle, __PusheratorRectangle, __PusheratorSquare)>` is implemented for `Shape`

error[E0271]: type mismatch resolving `<impl Pusherator<Item = Option<()>> as Pusherator>::Item == Shape`
--> tests/compile-fail/surface_demuxenum_wrongenum.rs:17:15
Expand Down Expand Up @@ -113,29 +63,3 @@ note: required by a bound in `pivot_run_sg_1v1`
16 | | Shape::Circle { r: 5.0 },
17 | | ]) -> demux_enum::<Option<()>>();
| |________________________________________^ required by this bound in `pivot_run_sg_1v1`

error[E0277]: the trait bound `std::option::Option<()>: DemuxEnum<(impl Pusherator<Item = _>, (impl Pusherator<Item = _>, (impl Pusherator<Item = _>, ())))>` is not satisfied
--> tests/compile-fail/surface_demuxenum_wrongenum.rs:13:20
|
13 | my_demux = source_iter([
| ____________________^
14 | | Shape::Rectangle { w: 10.0, h: 8.0 },
15 | | Shape::Square(9.0),
16 | | Shape::Circle { r: 5.0 },
17 | | ]) -> demux_enum::<Option<()>>();
| |________________________________________^ the trait `DemuxEnum<(impl Pusherator<Item = _>, (impl Pusherator<Item = _>, (impl Pusherator<Item = _>, ())))>` is not implemented for `std::option::Option<()>`
|
= help: the trait `DemuxEnum<(__PusheratorCircle, (__PusheratorRectangle, (__PusheratorSquare, ())))>` is implemented for `Shape`
note: required by a bound in `__typeguard_demux_enum_fn`
--> tests/compile-fail/surface_demuxenum_wrongenum.rs:12:18
|
12 | let mut df = hydroflow_syntax! {
| __________________^
13 | | my_demux = source_iter([
14 | | Shape::Rectangle { w: 10.0, h: 8.0 },
15 | | Shape::Square(9.0),
... |
20 | | my_demux[Square] -> for_each(std::mem::drop);
21 | | };
| |_____^ required by this bound in `__typeguard_demux_enum_fn`
= note: this error originates in the macro `hydroflow_syntax` (in Nightly builds, run with -Z macro-backtrace for more info)
Loading

0 comments on commit 7e36ab1

Please sign in to comment.