Generics syntax differences and monomorphization

These two declarations are almost equivalent I saw.
I think the first one gives more flexibility for the caller.
Apart from that: is monomorphization by the compiler done in exactly the same way?
The second one is shorter and easier to read, that is why I would prefer it.

fn copy<DstMap>(&self, dst: &mut DstMap, dst_point: Point)
where
    DstMap: MapTrait<T> {}
fn copy(&self, dst: &mut impl MapTrait<T>, dst_point: Point) {}

Another burning question: I have used const generics in a way that is "trusting the compiler to eliminate dead code and generating specialized function copies".
So without implementing specialized traits handling the situations.
Is that a viable way? Like "OK to do"?

fn do_something<const param: usize>()
{
    match param
    {
        0 => { /* do things */}
        1 => { /* do things */}
        2 => { /* do things */}
        _ => {}
    }
}

a more complicated one:

fn do_something<const param: usize>()
{
    // do some default things
    if param < 2
    {
        // do things
    }
    if param == 3
    {
        // do things
    }
    // etc.
}

Note: I really appreciate the very good answers I often get. Learning a lot.

There's no difference to the monomorphization.

The main non-syntactic difference is that the first version gives the generic type a name. This matters if you need or want to refer to the name

  • In the function body (e.g. let _: DstMap::Assoc = ...)
  • In a turbofish (e.g. foo.copy::<MapTraitImplementor>(...))
  • In an opaque return type (e.g. -> impl OtherTrait<DstMap>)

As you noted, even if you don't need it locally, giving the type a name can be nicer for consumers (the turbofish case), depending on the traits involved or generally how things get used.


Yes. I would expect those branches to optimize away.

4 Likes

impl Trait is only syntactically different from generics (eg. ability to turbofish); there's no difference in the meaning, and there should be no difference in the generated code.

I would prefer the generic version because impl Trait means a vastly different thing (a statically-dispatched, opaque existential) in a return type, where it is useful, needed, and often used.

However, using the same impl Trait syntax for both what is effectively a generic and existentials at the same time is confusing. So I'd reserve impl Trait for return types, and use real generics in argument position.

1 Like

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.