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

Nawfel BGH b.gh.n.93 at gmail.com
Tue Jul 22 11:09:37 PDT 2014


this remindes me of the issue i got when trying to implement finger
trees in Rust so long ago

https://github.com/rust-lang/rust/issues/8613

I suggested to let add a way to specify (in the code) how match
functions do we want to generate and failing at runtime when the limit
is reached. This made sense in my situation.

2014-07-22 18:23 UTC+01: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/
> _______________________________________________
> Rust-dev mailing list
> Rust-dev at mozilla.org
> https://mail.mozilla.org/listinfo/rust-dev
>


More information about the Rust-dev mailing list