Hi,

So traits seem to be quite similar to Haskell's classes, being also used
for parametric polymorphism. Now, Haskell classes are usually implemented
using runtime dictionary passing. In general, code cannot be specialized
for every function call, since there may be an unbounded number of
instances generated for it, as is explained in this reddit answer:
http://www.reddit.com/r/haskell/comments/1ar642/what_type_of_binding_does_haskell_use/c94o2ju

Knowing that Rust implements traits using monomorphization of code (much
like C++ templates), I was curious about how it handled such cases, and
tried this:

    struct W<T> {
        f: T
    }

    trait Show {
        fn show(&self) -> int;
    }

    impl Show for int {
        fn show(&self) -> int { 666 }
    }
    impl<T:Show> Show for W<T> {
        fn show(&self) -> int { self.f.show()+1 }
    }
    impl<T:Clone> Clone for W<T> {
        fn clone(&self) -> W<T> { W{f:self.f.clone()} }
    }

    fn foo<S:Show+Clone>(s: &S, n: int) {
        let w = W{f:s.clone()};
        if n > 0 { foo(&w, n-1); }
    }

    fn main() {
      foo(&W{f:42i},42);
    }


It gave me an "error: reached the recursion limit during monomorphization",
which... well, that's a possible solution :)

I'm not sure whether this is a big problem in practice, but I was wondering
if it would be possible to switch to some runtime mechanism in cases like
this. Maybe we could make a special version of every generic functions,
that takes a dictionary at runtime and that would be able to handle types
unknown at compile-time. We would switch to this version when
monomorphization does not work. It could also allow dynamic linking of
libraries with generic functions, or it could be a way to compile some
programs (or some parts of programs) much faster.
I was thinking about, for example, an IDE where generic function calls to
types defined inside the files currently being edited use their dynamic
version, so that recompile times can be virtually inexistent (like Java).
On the other hand, the release build would of course monomorphize as much
as possible to make the perf optimal.

Now the question is: would this conform to the current semantic of
monomorphization? Do special things happen during monomorphization that
cannot be reproduced at runtime?
This is the case in C++ (and one of the reasons why C++ templates are so
"bad"). Is it the case in Rust, which should already have all the required
info (type bounds) before monomorphization?

I apologize if this has already been discussed. I could not find many
satisfying answers by googling.

Cheers,
LP.
_______________________________________________
Rust-dev mailing list
Rust-dev@mozilla.org
https://mail.mozilla.org/listinfo/rust-dev

Reply via email to