`&'static SPI` is going to be a trait object (with dynamic dispatch).
The error it's giving is that `&SPI` (the trait object) doesn't
implement `SPI` (the trait). You would have to explicitly implement
`SPI` for `&SPI`. I'm not really sure  how to solve this without using
trait objects; you seem to want an inherently dynamically-dispatched
system.

On Tue, Apr 8, 2014 at 2:08 PM, Vladimir Pouzanov <[email protected]> wrote:
> That actually worked much better than I expected inlining everything and
> getting rid of vtables (I don't have support for .data section at the moment
> :-) ).
>
> I can't say the syntax is very clear to me, but I can get used to it. Still,
> one more question remains. I have a "debug output" concept, which means that
> debug::d("str") gets delivered to either LCD or UART, whatever is configured
> at runtime. I do it via static mut:
>
> pub trait Debugger {
>   fn debugs(&mut self, s: &str);
> }
>
> pub static mut debug_output: *mut c12332::C12332<'static, &'static spi::SPI>
> = unsafe { init() };
>
> pub fn d(s: &str) {
>   let debugger = unsafe { &mut (*debug_output) as &mut Debugger }; // failed
> to find an implementation of trait hal::spi::SPI for &'static
> hal::spi::SPI:'static
>   debugger.debugs(s);
> }
>
> pub fn set_debugger(lcd: *mut c12332::C12332<&spi::SPI>) {
>   unsafe { debug_output = lcd; };
> }
>
> I don't really support UART now, but I'd still like to access my LCD via a
> globally known static getter. How can I re-write that with typed struct?
>
>
> On Tue, Apr 8, 2014 at 6:26 PM, Corey Richardson <[email protected]> wrote:
>>
>> You don't use bounds in the struct, you put them in the impl. So you
>> would instead say
>>
>>
>> struct LCD<S> {
>>   spi: S,
>>   ...
>> }
>>
>>
>> and then:
>>
>> impl<S: SPI> LCD<S> {
>>     ...
>> }
>>
>> On Tue, Apr 8, 2014 at 1:23 PM, Vladimir Pouzanov <[email protected]>
>> wrote:
>> > I might have found an unsupported case.
>> >
>> > Consider the following:
>> >
>> > trait SPI { ... }
>> >
>> > struct McuSPI;
>> > impl SPI for McuSPI { ... }
>> >
>> > struct LCD {
>> >   spi: &SPI,
>> >   ...
>> > }
>> >
>> > This code results in a dynamic dispatch to SPI, as "trait bounds are not
>> > allowed in structure definitions". Is it in any way possible to use
>> > static
>> > dispatch from LCD to SPI given the exact implementations are known at
>> > compile time?
>> >
>> >
>> > On Thu, Apr 3, 2014 at 2:46 AM, Ashish Myles <[email protected]> wrote:
>> >>
>> >> 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
>> >> >
>> >
>> >
>> >
>> >
>> > --
>> > Sincerely,
>> > Vladimir "Farcaller" Pouzanov
>> > http://farcaller.net/
>> >
>> > _______________________________________________
>> > Rust-dev mailing list
>> > [email protected]
>> > https://mail.mozilla.org/listinfo/rust-dev
>> >
>>
>>
>>
>> --
>> http://octayn.net/
>
>
>
>
> --
> Sincerely,
> Vladimir "Farcaller" Pouzanov
> http://farcaller.net/



-- 
http://octayn.net/
_______________________________________________
Rust-dev mailing list
[email protected]
https://mail.mozilla.org/listinfo/rust-dev

Reply via email to