Wrapper for two possible input parameter types

Moin folks,

I'm relatively new to Rust, I'm trying to write a function which can accpet both

  1. an iterator of (f32, f32)
  2. an iterator of (chrono::NaiveDate, f32)

and I want them visualized with plotters crate. I already tried creating two separate functions, one for each scenario, and this works. Now I want to combine the two with generics.
Here an example: Rust Playground (won't run not only because of the error, but also because of the missing crates - did I had to post the source directly here?)

It complains that
79 | .draw_series(

  • | ^^^^^^^^^^^ the trait for<'b> PointCollection<'b, (chrono::NaiveDate, _)> is not implemented for &'b plotters::element::Circle<(T, U), {integer}>*
  • |*
  • = help: the trait PointCollection<'_, (T, U)> is implemented for &plotters::element::Circle<(T, U), {integer}>*
  • = help: for that trait implementation, expected T, found chrono::NaiveDate*
    note: required by a bound in ChartContext::<'a, DB, CT>::draw_series
  • --> /home/user/.cargo/registry/src/index.crates.io-6f17d22bba15001f/plotters-0.3.6/src/chart/context.rs:126:24*
  • |*
    120 | pub fn draw_series<B, E, R, S>(
  • | ----------- required by a bound in this associated function*
    ...
    126 | for<'b> &'b E: PointCollection<'b, CT::From, B>,
  • | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in ChartContext::<'a, DB, CT>::draw_series*

(There is another TODO here, related with the initialization of the chart_context - it has to be initialized according to the scenario - I will address this one next.)

I feel I miss some general knowledge (I recently started using generics in my code), can you help me with some guidance? From what I understand, it has a problem with the newly introduced lifetime 'b, but the same error for<'b> PointCollection<'b ... is there even if I remove b from my code at all.

Many thanks in advance!

Why not just use two functions? It seems cleaner to me.

I'm not familiar with this crate so this is a bit out of my depth, but from the looks of it, the compiler is complaining that your generic isn't bound to a required trait. When I'm in a pinch like this I usually look at what the function I'm trying to use expects so I can figure out what the trait bounds of my generic should be, take a look at the function on the documentation:

It expects that your generic implements: PointCollection<'b, CT::From, B>, I think anyway, the trait bounds seem a little confusing to me without context.

That won't be DRY, there are about 20 - 30 lines of code.. But I will use this as a workaround.

Thanks Jonnyso, that's basically what I try to do, but it seems I don't know how to do it :smiley:
It seems the answer is somewhere around "

However, Generic Associated Types is far away from stabilize. So currently we have the following workaround:
Instead of implement the PointCollection trait on the element type itself, it implements on the reference to the element. By doing so, we now have a well-defined lifetime for the iterator.

, but I still don't know what to do.
Tried to add the bound + for <'b> PointCollection<'b, MyXDataType<f32>> for both my generic params T and U, doesn't work.

In the plotters API docs

pub trait PointCollection<'a, Coord, CM = BackendCoordOnly> {

I see CM generic parameter has a default value and I assume it's useful, so I only need to

  1. specify 'Coord' generic parameter and
  2. a lifetime, in the docs reffered to as 'a - which in my code is 'b and I maybe have to point a relation to 'a (like 'a, 'b: 'a)?

I will try to make use of Limit a generic type to be either A or B - #8 by jhpratt

Still no luck. Forgot to note, that in order to run the playground project, you have to

cargo add chrono plotters num_traits anyhow

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.