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

2014-07-27 Thread Lionel Parreaux
I see. Thanks for the links, Greg Morrisett's notes are a great survey of
possible approaches to this problem.
It is funny because I had also come to the conclusion that JIT was the
neater solution, as long as JIT is available with the runtime... and you
don't have to implement it -- I guess it's even more complex than doing
runtime dictionary passing.
Has there been experiments using LLVM's JIT to implement polymorphism in
Rust? I'm not sure about the cost of JIT, though. Maybe it would not make
sense in Rust. Well, at least there should still be the static
monomorphization option.



2014-07-26 5:31 GMT+02:00 Patrick Walton :

> On 7/25/14 8:26 PM, Patrick Walton wrote:
>
>> Uniform value representations work well too (as
>> OCaml shows), but of course you'll pay a performance cost for that.
>>
>
> Oh, note that Greg's notes are a little bit out of date when discussing
> the performance tradeoffs of uniform value representation. On 64 bit (and
> even on 32 bit) you can do NaN-boxed "fatvals" [1] (scroll down to
> "Mozilla's New JavaScript Value Representation") which avoid having to box
> every floating point value.
>
> Patrick
>
> [1] http://evilpie.github.io/sayrer-fatval-backup/cache.aspx.htm
>
>
> ___
> Rust-dev mailing list
> Rust-dev@mozilla.org
> https://mail.mozilla.org/listinfo/rust-dev
>
___
Rust-dev mailing list
Rust-dev@mozilla.org
https://mail.mozilla.org/listinfo/rust-dev


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

2014-07-25 Thread Patrick Walton

On 7/25/14 8:26 PM, Patrick Walton wrote:

Uniform value representations work well too (as
OCaml shows), but of course you'll pay a performance cost for that.


Oh, note that Greg's notes are a little bit out of date when discussing 
the performance tradeoffs of uniform value representation. On 64 bit 
(and even on 32 bit) you can do NaN-boxed "fatvals" [1] (scroll down to 
"Mozilla's New JavaScript Value Representation") which avoid having to 
box every floating point value.


Patrick

[1] http://evilpie.github.io/sayrer-fatval-backup/cache.aspx.htm

___
Rust-dev mailing list
Rust-dev@mozilla.org
https://mail.mozilla.org/listinfo/rust-dev


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

2014-07-25 Thread Patrick Walton

On 7/25/14 8:10 PM, Lionel Parreaux wrote:

Oh I'm sorry I completely missed your message, because I was not
subscribed to the list.

Thanks for the explanation. I do realize that this is the tough part,
compared to a system like Haskell where everything is boxed.

It's interesting to hear that this is how it was (meant to be) done in a
previous version of Rust. Could you expand on the sources of the
difficulties met trying to implement it? (Or just give me a pointer to
some material about it.)


Basically it got really complicated when you had things like:

fn f(x: T) {
if ... {
   f((x,x,x));
}
}

Not only did we have to have the notion of a "type descriptor" which was 
passed at runtime, because of generics-constructed-out-of-other-generics 
we had to have the notion of a "derived type descriptor" which was a 
type descriptor constructed at runtime on the stack, which formed a 
singly linked list of type descriptors (so that you could find 
destructors for the original types).


Additionally, the requirement that we have to follow C alignment rules 
meant that accessing field N of a struct was actually an O(n) operation, 
since there's no closed-form way to calculate alignment of a struct at 
length N.


These two were the biggest problems.


I'm interested, because I'm working on a research language without GC
and without boxed allocation semantics, so this kind of things come up.


Have you seen these notes from Greg Morrisett? 
http://www.eecs.harvard.edu/~greg/cs256sp2005/lec15.txt


They were very helpful for us. I have a few minor quibbles (for example 
I don't think the hazards of infinite template instantiation via 
polymorphic recursion are that big of a deal in practice, whereas those 
notes seem to consider it a deal-breaker). What I do agree with is that 
the best way to do generics if you have non-uniform value 
representations is to JIT each template instantiation as you come to it 
(like .NET does). This is basically the best of all worlds. However, it 
requires a JIT; if you don't have a JIT, I think the best thing is what 
Rust currently does. Uniform value representations work well too (as 
OCaml shows), but of course you'll pay a performance cost for that.


Patrick

___
Rust-dev mailing list
Rust-dev@mozilla.org
https://mail.mozilla.org/listinfo/rust-dev


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

2014-07-25 Thread Lionel Parreaux
Oh I'm sorry I completely missed your message, because I was not subscribed
to the list.

Thanks for the explanation. I do realize that this is the tough part,
compared to a system like Haskell where everything is boxed.

It's interesting to hear that this is how it was (meant to be) done in a
previous version of Rust. Could you expand on the sources of the
difficulties met trying to implement it? (Or just give me a pointer to some
material about it.)

I'm interested, because I'm working on a research language without GC and
without boxed allocation semantics, so this kind of things come up.

Cheers,
LP.

PS: I agree that the current system seems reasonable for what Rust targets.


Patrick Walton 
Tue Jul 22 11:47:18 PDT 2014

> On 7/22/14 10:16 AM, Lionel Parreaux wrote:
> > 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.
>
> The hard part about doing that is not the dictionary passing. The hard
> part is that generic types may have unknown size or alignment. In
> Haskell this is not a problem because the language is garbage-collected
> and lazy so values have a uniform representation. But in Rust this is
> not true.
>
> Old Rust used to try to use runtime dictionary passing, where the
> dictionary contained size and alignment information, and all
> size/alignment info was computed at runtime for generics. I cannot
> overstate how *fiendishly* complex this was. We never got all the bugs
> out. In many cases, the amount of runtime code generated to compute size
> and alignment outweighed the cost of just monomorphizing.
>
> I strongly feel that the current system, where you can use generic type
> parameters to get monomorphization or trait objects to get dictionary
> passing, is the sweet spot.
>
> Patrick
>
___
Rust-dev mailing list
Rust-dev@mozilla.org
https://mail.mozilla.org/listinfo/rust-dev


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

2014-07-24 Thread Daniel Micay
On 24/07/14 11:59 AM, Lionel Parreaux wrote:
>
> I can't pronounce myself about the suitability of features in the Rust
> language, but it may be worth noting that some convenient high-level
> features are already present in the language, like garbage collection.

There isn't an implementation of garbage collection.



signature.asc
Description: OpenPGP digital signature
___
Rust-dev mailing list
Rust-dev@mozilla.org
https://mail.mozilla.org/listinfo/rust-dev


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

2014-07-24 Thread Lionel Parreaux
Hi,

Could you provide a link to Patrick's description of size/alignment-passing
implementation? I'm interested in these things.

Well, there could be a warning if the compiler switches to such an
implementation. It's arguably still better than not compiling at all.
However, I don't have enough experience with type classes to know whether
such situations actually happen in the real world. But didn't Nawfel BGH
give an example of that?

I'm not an expert in embedded systems, but I know that in some embedded
systems, especially when memory is scarce or when the instruction cache is
small, code size does matter more than the number of instructions executed
per function call. It would probably be useful to be able to use generic
libraries but still tweak the amount of monomoprhization in order to
control the size of the generated executable.
I don't know if this is the case for Rust, but executable size is an
endemic problem in C++ because of wild template instantiation.

I can't pronounce myself about the suitability of features in the Rust
language, but it may be worth noting that some convenient high-level
features are already present in the language, like garbage collection.
Also, even C compilers output code with dramatically varying efficiency
depending on the chosen levels of optimization -- and sometimes small
details can disable optimization opportunities.

Cheers,
LP.



2014-07-23 4:13 GMT+02:00 Cameron Zwarich :

> Even if we could do a size/alignment-passing implementation like Patrick
> describes, would be it even be appropriate? It wouldn’t make sense for a
> systems language to transparently switch to a dramatically less efficient
> implementation mechanism without the programmer’s involvement.
>
> Is there any place where an unbounded number of dictionaries at runtime is
> actually appropriate for solving a real problem in Rust?
>
> Cameron
>
> On Jul 22, 2014, at 10:16 AM, Lionel Parreaux 
> 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 {
> f: T
> }
>
> trait Show {
> fn show(&self) -> int;
> }
>
> impl Show for int {
> fn show(&self) -> int { 666 }
> }
> impl Show for W {
> fn show(&self) -> int { self.f.show()+1 }
> }
> impl Clone for W {
> fn clone(&self) -> W { W{f:self.f.clone()} }
> }
>
> fn foo(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
>
>
>
___
Rust-dev mailing list
Rust-dev@mozilla.org
https://mail.mozilla.org/listinfo/rust-dev


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

2014-07-23 Thread Lionel Parreaux
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(p)"
and "foo(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 :

> 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
>  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 {
> > f: T
> > }
> >
> > trait Show {
> > fn show(&self) -> int;
> > }
> >
> > impl Show for int {
> > fn show(&self) -> int { 666 }
> > }
> > impl Show for W {
> > fn show(&self) -> int { self.f.show()+1 }
> > }
> > impl Clone for W {
> > fn clone(&self) -> W { W{f:self.f.clone()} }
> > }
> >
> > fn foo(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
> >
>
>
>
> --
> http://octayn.net/
>
___
Rust-dev mailing list
Rust-dev@mozilla.org
https://mail.mozilla.org/listinfo/rust-dev


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

2014-07-22 Thread Cameron Zwarich
Even if we could do a size/alignment-passing implementation like Patrick 
describes, would be it even be appropriate? It wouldn’t make sense for a 
systems language to transparently switch to a dramatically less efficient 
implementation mechanism without the programmer’s involvement.

Is there any place where an unbounded number of dictionaries at runtime is 
actually appropriate for solving a real problem in Rust?

Cameron

On Jul 22, 2014, at 10:16 AM, Lionel Parreaux  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 {
> f: T
> }
> 
> trait Show {
> fn show(&self) -> int;
> }
> 
> impl Show for int {
> fn show(&self) -> int { 666 }
> }
> impl Show for W {
> fn show(&self) -> int { self.f.show()+1 }
> }
> impl Clone for W {
> fn clone(&self) -> W { W{f:self.f.clone()} }
> }
> 
> fn foo(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

___
Rust-dev mailing list
Rust-dev@mozilla.org
https://mail.mozilla.org/listinfo/rust-dev


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

2014-07-22 Thread Patrick Walton

On 7/22/14 10:16 AM, Lionel Parreaux wrote:

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.


The hard part about doing that is not the dictionary passing. The hard 
part is that generic types may have unknown size or alignment. In 
Haskell this is not a problem because the language is garbage-collected 
and lazy so values have a uniform representation. But in Rust this is 
not true.


Old Rust used to try to use runtime dictionary passing, where the 
dictionary contained size and alignment information, and all 
size/alignment info was computed at runtime for generics. I cannot 
overstate how *fiendishly* complex this was. We never got all the bugs 
out. In many cases, the amount of runtime code generated to compute size 
and alignment outweighed the cost of just monomorphizing.


I strongly feel that the current system, where you can use generic type 
parameters to get monomorphization or trait objects to get dictionary 
passing, is the sweet spot.


Patrick

___
Rust-dev mailing list
Rust-dev@mozilla.org
https://mail.mozilla.org/listinfo/rust-dev


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

2014-07-22 Thread Nawfel BGH
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 :
> 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
>  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 {
>> f: T
>> }
>>
>> trait Show {
>> fn show(&self) -> int;
>> }
>>
>> impl Show for int {
>> fn show(&self) -> int { 666 }
>> }
>> impl Show for W {
>> fn show(&self) -> int { self.f.show()+1 }
>> }
>> impl Clone for W {
>> fn clone(&self) -> W { W{f:self.f.clone()} }
>> }
>>
>> fn foo(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
>>
>
>
>
> --
> http://octayn.net/
> ___
> Rust-dev mailing list
> Rust-dev@mozilla.org
> https://mail.mozilla.org/listinfo/rust-dev
>
___
Rust-dev mailing list
Rust-dev@mozilla.org
https://mail.mozilla.org/listinfo/rust-dev


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

2014-07-22 Thread Corey Richardson
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
 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 {
> f: T
> }
>
> trait Show {
> fn show(&self) -> int;
> }
>
> impl Show for int {
> fn show(&self) -> int { 666 }
> }
> impl Show for W {
> fn show(&self) -> int { self.f.show()+1 }
> }
> impl Clone for W {
> fn clone(&self) -> W { W{f:self.f.clone()} }
> }
>
> fn foo(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
>



-- 
http://octayn.net/
___
Rust-dev mailing list
Rust-dev@mozilla.org
https://mail.mozilla.org/listinfo/rust-dev


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

2014-07-22 Thread Lionel Parreaux
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 {
f: T
}

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

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

fn foo(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