[rust-dev] Implementation of traits in Rust: could it be dynamic?

Lionel Parreaux lionel.parreaux at gmail.com
Tue Jul 22 12:39:53 PDT 2014


Right, I had forgotten Rust had this convenient trait object feature.

However, my question remains: does a function accepting an object always
have the same behavior as a function that uses a generic parameter? If this
was the case, as I proposed in my previous message, we could not only
generate specialized monomorphic versions of generic functions, but also
specialized *polymorphic* versions of them (using objects), transparently.
This would allow writing generic functions only once, that can be used
efficiently when possible/appropriate (by monomorphization), but are also
usable dynamically.

This property is not necessarily trivial, because of overloading for
instance.
I'm not sure how it works in Rust, but in C++, calling "foo<Person*>(p)"
and "foo<Student*>(p)" with the same object p of type Student* may have
different behaviors because of overloading resolution after template
instantiation (and also because of template specialization).




2014-07-22 19:23 GMT+02:00 Corey Richardson <corey at octayn.net>:

> You can avoid monomorphization by using "trait objects", which erase
> the precise implementing type through a vtable + pointer.
>
> http://doc.rust-lang.org/tutorial.html#trait-objects-and-dynamic-method-dispatch
> has some documentation.
>
> On Tue, Jul 22, 2014 at 10:16 AM, Lionel Parreaux
> <lionel.parreaux at gmail.com> wrote:
> > 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 at mozilla.org
> > https://mail.mozilla.org/listinfo/rust-dev
> >
>
>
>
> --
> http://octayn.net/
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.mozilla.org/pipermail/rust-dev/attachments/20140722/cf62ab0c/attachment.html>


More information about the Rust-dev mailing list