fir-lang / fir

MIT License
26 stars 3 forks source link

Specialization in trait implementations #20

Open osa1 opened 3 months ago

osa1 commented 3 months ago
trait T[A]:
    fn f(self)

impl T[I32]: ...

impl[A: T] T[Vec[A]]: ...

# Overlaps with the more general definition above.
impl T[Vec[I32]]: ...

I think this is actually safe when all of the following holds:

  1. We do monomorphisation, instead of runtime polymorphism.

    This allows compiling call sites:

    fn g[A: T](a: A) = [a].f()

    Here each call site of g will create a monomorphic g based on the type argument, so I know which f to call in [a].f(), without having to do runtime type tests.

  2. To make sure (1) covers all invocations of the f, the trait is not allowed in trait objects. E.g. you can't have an existential with this trait as the type.

  3. Specialization is only allowed within the compilation/type checking unit of the trait. Users cannot add implementations that specialize an existing implementation.

    This makes sure when two packages/libararies build and run fine on their own, they will build and run the same way when they are linked together in a third package/library.

I actually don't know if this pattern is useful. I'm thinking maybe in the standard library we can provide faster Hash on Vec[I32] (and other Vec types with 4-byte unboxed elements) using this.