And just in case there is a confusion (as I have noticed others to
have), it might help to see a specific example comparing static
dispatch with dynamic.
// This is a single function for all types implementing the LCD Trait.
fn foo(x : &LCD) { // x's type is &LCD rather than the actual type of
the object being passed in
x.line(....); // dynamic dispatch
}
// Like C++ templates, this generates a function for each type T that
implements LCD.
fn foo<T : LCD>(x : &T) { // x's type is &T rather than &LCD
x.line(....); // static dispatch based on type T known at compile-time
}
On Wed, Apr 2, 2014 at 8:32 AM, Daniel Micay <[email protected]> wrote:
> On 02/04/14 06:25 AM, Vladimir Pouzanov wrote:
>> If I get it right, calls to traits are resolved in runtime (so, traits
>> are kind of similar to C++ virtual methods).
>
> All method calls on regular types are resolved via static dispatch,
> whether or not they come from a trait. For example, consider a generic
> function like the following:
>
> fn min<T: TotalOrd>(a: T, b: T) -> T {
> if a < b { a } else { b }
> }
>
> This function performs a *static* call of the `lt` method defined on the
> `Ord` trait that `TotalOrd` inherits from. Generics are fully expanded
> at compile-time just as C++ templates are.
>
> Rust also allows using traits as boxed objects, but this is an entirely
> transparent choice. They're almost always used for static dispatch via
> trait bounds on generics, or simply outside of generics.
>
>> What I'm proposing here is a compile-time approach.
>>
>> Let's say we have the following trait:
>>
>> pub trait LCD {
>> fn line(&mut self, x0_b: i32, y0_b: i32, x1: i32, y1: i32, color: u8);
>> fn rect(&mut self, x0: i32, y0: i32, x1: i32, y1: i32, color: u8);
>> fn fillrect(&mut self, x0_b: i32, y0_b: i32, x1_b: i32, y1_b: i32,
>> color: u8);
>> fn putc(&mut self, value: char);
>> fn puts(&mut self, s: &str);
>>
>> fn flush(&self);
>> fn clear(&mut self);
>> }
>>
>> which defined a LED screen. There are two structs implementing it:
>> C12832 and ILI9341 (two different lcd controllers).
>>
>> So I want my app to print hello world on lcd, I write the following code:
>>
>> let mut lcd = lcd_c12832::C12832::new(spi);
>> let mut l: &mut lcd::LCD = lcd as &mut lcd::LCD;
>> l.puts("hello, world");
>>
>> Which results in a runtime dispatch, a slower and bigger code than the
>> one I'd have without a trait.
>
> You can call methods defined on a trait without boxing the object as a
> trait object. The ability to perform dynamic dispatch via a trait object
> is totally optional. The methods can also be called directly, including
> inside a generic function by specifying the trait as a type parameter
> bound. You can simply call the `puts` method directly on the `lcd`
> object without a cast.
>
>> A second problem is there is no easy way to write unified code that
>> supports both the lcds based on passed in --cfg, as I can't
>> apply #[cfg(lcd_c12832)] to a chunk of code in fn, and it's kind of
>> problematic to return a &LCD out from it given that there is no heap and
>> no analog of placement new from C++.
>
> Rust supports generic functions, and you can write code supporting both
> types by making it generic. The choice between static dispatch and
> dynamic dispatch is entirely up to you in the current system.
>
>> Proposed binding concept solves those two problems:
>>
>> #[cfg(lcd_c12832)]
>> let Binding: binding {
>> let lcd: &lcd_c12832::C12832;
>> let main: &Main;
>>
>> bind main.lcd = lcd;
>> }
>>
>> at this point of time compiler can be sure about what struct is
>> implementing LCD trait for main.lcd and can bind the function bodies as
>> compile time, inlining them if applicable.
>>
>> This also might be something that is already implemented, please advice.
>> The goal here is to minimise runtime code being executed and its size.
>
>
>
> _______________________________________________
> Rust-dev mailing list
> [email protected]
> https://mail.mozilla.org/listinfo/rust-dev
>
_______________________________________________
Rust-dev mailing list
[email protected]
https://mail.mozilla.org/listinfo/rust-dev