`&'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
