From 826dbd9a709de2f883992bdcefa8f2d566d74ecb Mon Sep 17 00:00:00 2001 From: Mingwei Samuel Date: Mon, 20 May 2024 10:10:21 -0700 Subject: [PATCH] refactor: simplify `demux_enum()`, somewhat improves error messages #1201 (#1204) --- hydroflow/src/util/demux_enum.rs | 49 +++-------- .../surface_demuxenum_notenum.stderr | 69 ++------------- .../surface_demuxenum_port_extra.stderr | 27 ++++-- .../surface_demuxenum_port_missing.stderr | 23 +++-- .../surface_demuxenum_wrongenum.rs | 3 +- .../surface_demuxenum_wrongenum.stderr | 87 +++++++++++++++++-- .../surface_demuxenum_wrongfields_1.rs | 23 +++++ .../surface_demuxenum_wrongfields_1.stderr | 29 +++++++ .../surface_demuxenum_wrongfields_2.rs | 23 +++++ .../surface_demuxenum_wrongfields_2.stderr | 29 +++++++ .../surface_demuxenum_wrongitems.stderr | 11 --- ...tems.rs => surface_demuxenum_wrongtype.rs} | 1 - .../surface_demuxenum_wrongtype.stderr | 14 +++ hydroflow/tests/surface_demux_enum.rs | 18 ++-- hydroflow_lang/src/graph/ops/demux_enum.rs | 30 +++---- hydroflow_macro/src/lib.rs | 26 +++--- pusherator/src/demux.rs | 7 -- pusherator/src/lib.rs | 1 - 18 files changed, 289 insertions(+), 181 deletions(-) create mode 100644 hydroflow/tests/compile-fail/surface_demuxenum_wrongfields_1.rs create mode 100644 hydroflow/tests/compile-fail/surface_demuxenum_wrongfields_1.stderr create mode 100644 hydroflow/tests/compile-fail/surface_demuxenum_wrongfields_2.rs create mode 100644 hydroflow/tests/compile-fail/surface_demuxenum_wrongfields_2.stderr delete mode 100644 hydroflow/tests/compile-fail/surface_demuxenum_wrongitems.stderr rename hydroflow/tests/compile-fail/{surface_demuxenum_wrongitems.rs => surface_demuxenum_wrongtype.rs} (90%) create mode 100644 hydroflow/tests/compile-fail/surface_demuxenum_wrongtype.stderr diff --git a/hydroflow/src/util/demux_enum.rs b/hydroflow/src/util/demux_enum.rs index 256e03d2907e..a08577d821ea 100644 --- a/hydroflow/src/util/demux_enum.rs +++ b/hydroflow/src/util/demux_enum.rs @@ -1,43 +1,22 @@ -//! 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: DemuxEnumItems -where - Nexts: PusheratorListForItems, -{ - /// 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(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; +/// 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 = "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: DemuxEnumBase { + /// Pushes self into the corresponding output pusherator in `outputs`. + fn demux_enum(self, outputs: &mut Outputs); } -/// Helper trait to bound a [`PusheratorList`] variadic to some coresponding item list variadic. -/// -/// A pusherator list `var_type!(PushA, PushB, PushC)` implements `PusheratorListForItems`, -/// where `PushA: Pusherator`, etc. -pub trait PusheratorListForItems: PusheratorList -where - Items: Variadic, -{ -} -impl PusheratorListForItems<(Head, Rest)> for (HeadPush, RestPush) -where - HeadPush: Pusherator, - RestPush: PusheratorListForItems, - Rest: Variadic, -{ -} -impl PusheratorListForItems<()> for () {} +/// Base implementation to constrain that `DemuxEnum` is implemented. +#[diagnostic::on_unimplemented(note = "Use `#[derive(hydroflow::DemuxEnum)]`")] +pub trait DemuxEnumBase {} diff --git a/hydroflow/tests/compile-fail/surface_demuxenum_notenum.stderr b/hydroflow/tests/compile-fail/surface_demuxenum_notenum.stderr index 330a78540e5b..57d301082118 100644 --- a/hydroflow/tests/compile-fail/surface_demuxenum_notenum.stderr +++ b/hydroflow/tests/compile-fail/surface_demuxenum_notenum.stderr @@ -1,9 +1,10 @@ -error[E0277]: the trait bound `Shape: DemuxEnumItems` is not satisfied +error[E0277]: the trait bound `Shape: DemuxEnumBase` is not satisfied --> tests/compile-fail/surface_demuxenum_notenum.rs:12:28 | 12 | ]) -> demux_enum::(); - | ^^^^^ the trait `DemuxEnumItems` is not implemented for `Shape` + | ^^^^^ the trait `DemuxEnumBase` is not implemented for `Shape` | + = note: Use `#[derive(hydroflow::DemuxEnum)]` note: required by a bound in `check_impl_demux_enum` --> tests/compile-fail/surface_demuxenum_notenum.rs:8:18 | @@ -62,72 +63,20 @@ help: if there were a trait named `Example` with associated type `Square` implem 15 | my_demux[::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::(); - | ^^^^^^^^^^^^^^^^^^^^^ 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::(); - | ^^^^^ 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, (impl Pusherator, (impl Pusherator, (impl Pusherator, ()))))>` is not satisfied --> tests/compile-fail/surface_demuxenum_notenum.rs:12:15 | -12 | ]) -> demux_enum::(); - | ^^^^^^^^^^^^^^^^^^^^^ the trait `DemuxEnum<(impl Pusherator, (impl Pusherator, (impl Pusherator, (impl Pusherator, ()))))>` 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, (impl Pusherator, (impl Pusherator, (impl Pusherator, ()))))>` 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::(); - | |___________________________________^ the trait `DemuxEnum<(impl Pusherator, (impl Pusherator, (impl Pusherator, (impl Pusherator, ()))))>` 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: 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, ...)`. diff --git a/hydroflow/tests/compile-fail/surface_demuxenum_port_extra.stderr b/hydroflow/tests/compile-fail/surface_demuxenum_port_extra.stderr index 5732d5cf44ea..e998c9f500da 100644 --- a/hydroflow/tests/compile-fail/surface_demuxenum_port_extra.stderr +++ b/hydroflow/tests/compile-fail/surface_demuxenum_port_extra.stderr @@ -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::(); + | | ^^^^^^^^^^^^^^^^^^^^^ 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, ())` + | |_____- arguments to this function are incorrect | - = note: expected unit type `()` - found tuple `(impl Pusherator, ())` - = 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, impl Pusherator, impl Pusherator, impl Pusherator)` +note: method defined here + --> src/util/demux_enum.rs + | + | fn demux_enum(self, outputs: &mut Outputs); + | ^^^^^^^^^^ diff --git a/hydroflow/tests/compile-fail/surface_demuxenum_port_missing.stderr b/hydroflow/tests/compile-fail/surface_demuxenum_port_missing.stderr index 70e3f9585ec2..e51294ec63fc 100644 --- a/hydroflow/tests/compile-fail/surface_demuxenum_port_missing.stderr +++ b/hydroflow/tests/compile-fail/surface_demuxenum_port_missing.stderr @@ -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::(); + | | ^^^^^^^^^^^^^^^^^^^^^ 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, impl Pusherator)` +note: method defined here + --> src/util/demux_enum.rs + | + | fn demux_enum(self, outputs: &mut Outputs); + | ^^^^^^^^^^ diff --git a/hydroflow/tests/compile-fail/surface_demuxenum_wrongenum.rs b/hydroflow/tests/compile-fail/surface_demuxenum_wrongenum.rs index b5e6acffc827..71ef0b72edc5 100644 --- a/hydroflow/tests/compile-fail/surface_demuxenum_wrongenum.rs +++ b/hydroflow/tests/compile-fail/surface_demuxenum_wrongenum.rs @@ -14,11 +14,10 @@ fn main() { Shape::Rectangle { w: 10.0, h: 8.0 }, Shape::Square(9.0), Shape::Circle { r: 5.0 }, - ]) -> demux_enum::