Generics in crate boundaries

Let's say that we have a crate graph like this:

A exposes

pub fn entry_to_system<A: Trait>(ty: A) {} // This creates lots of generic stuff.

as MIR.

  1. If B and C use entry_to_system with the same type, will the compiler need to build the same thing twice?
  2. What if they use dyn?

In these kinds of cases, would it be better to expose something like

fn entry_to_system<A: Trait>(ty: A) {}

pub struct MyType;
impl Trait for MyType {}
pub fn concrete_entry_to_system(ty: MyType) {
  entry_to_system(ty)
}
// or
pub fn dyn_entry_to_system(ty: Box<dyn A>) {
  entry_to_system(ty)
}

To avoid these issues?

Yes, generics may end up being built redundantly multiple times.

Crates are built in parallel, and then each crate may be further split into codegen units. If multiple codegen units end up needing to instantiate the same generic code with the same type, they will end up compiling the same thing redundantly.

Using dyn avoids this. There will be one concrete implementation built once for all types.

But only if the dyn version is exposed in crate A, right? if B and C use dyn while using entry_to_system directly, won't that need two concrete versions of it?

That's a good point. Code using dyn can be compiled eagerly once for all types, but where concrete implementations of a trait for specific types are built is less clear.

Due to orphan rules, you can't have multiple crates implementing the same trait for the same type. So if there's a specific impl Trait for u32 it would have to be in the crate defining the Trait. However I'm not sure if the dyn impl is built eagerly at that point if you don't use u32 with dyn in the same crate.

If there's a generic blanket impl like impl<T> Trait for T where… then it will behave like generics, and may be built redundantly.

There is an unstable option called -Zshare-generics which means that, if A contains a use of entry_to_system::<MyType>(), then B and C can reuse those monomorphizations.

2 Likes

That option seems to be the default in stable for inline(never) fns :smiley:

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.