The call isn't statically dispatched when I invoke a method via a trait pointer. So it seems when I invoke any trait function, I pay double the cost of a virtual function call instead of one... I suppose it isn't _too_ bad, but it still hurts.
On Wed, Nov 13, 2013 at 12:21 PM, Eric Reed <ecr...@cs.washington.edu>wrote: > I'm not clear on why LLVM wouldn't be able to inline super() calls. It's > static dispatch, so it knows exactly what function is being called. > > > On Wed, Nov 13, 2013 at 1:25 AM, Oren Ben-Kiki <o...@ben-kiki.org> wrote: > >> This is probably as good as we can get in the current system (I do >> something similar in my code today). >> >> I also think you probably need both "super" and "mut_super", so it would >> be two methods to implement instead of one (still pretty good). I wonder >> whether it is possible to write a macro that automates writing these >> boilerplate methods? >> >> The key weakness is that (I think) the compiler can't inline the accesses >> to "super" so that you end up with a chain of virtual function calls every >> time it is accessed, so performance would be pretty bad. >> >> >> On Wed, Nov 13, 2013 at 10:27 AM, Eric Reed <ecr...@cs.washington.edu>wrote: >> >>> Here's how I would do it using just existing Rust (assuming this hasn't >>> all changed under me in the past couple months). >>> NB: I haven't actually tried compiling this, but I'm pretty sure it (or >>> something like it) would work. >>> >>> Nice properties over this solution: >>> - Doesn't require language extensions (although syntax sugar wouldn't be >>> unwelcome) >>> - Doesn't require trait objects (i.e. static dispatch is possible) >>> - Only need to implement one method for each derived type (super) in >>> addition to overridden methods >>> - Supports multiple inheritance in two ways (and avoids the diamond >>> problem I think -- not a C++ expert so I may have misunderstood that) >>> + no default parent and programmer must select which parent to use >>> before calling >>> + implementer-chosen default parent and programmer can chose to >>> use a different parent if desired >>> >>> Neutral?: >>> - Doesn't enforce or care about the prefix property. Not sure if that >>> still matters so much w/o dynamic dispatch. >>> >>> Downsides: >>> - Performance of delegation depends on LLVM's ability to inline (I >>> think). >>> - Does require repeating all the methods once (for delegating default >>> implementations) >>> >>> // The base type >>> struct Base { >>> data : int; >>> } >>> >>> // Characterize it's extensible behavior in a trait >>> trait Trait { >>> fn method(&self); >>> } >>> >>> // Implement the base behavior >>> impl Trait for Base { >>> fn method(&self) { ... } >>> } >>> >>> // Extension of trait that supports upcasting to existing implementations >>> trait DerivingTrait<P : Trait> : Trait { >>> // one extra method for accessing a parent's implementation. ideally >>> this would be inlined by the compiler >>> fn super(&self) -> P; >>> // default implementations for all the methods in Trait let us avoid >>> writing delegation everywhere manually >>> fn method(&self) { >>> self.super().method() // just delegate to parent >>> } >>> } >>> >>> // Single inheritance >>> struct Single { >>> parent: Base, >>> moreData: int, >>> } >>> >>> impl DerivingTrait<Base> for Single { >>> fn super(&self) -> Base { self.parent } >>> } >>> >>> // Overriding behavior >>> struct Override { >>> parent: Base, >>> otherData: u8, >>> } >>> >>> impl DerivingTrait<Base> for Override { >>> fn super(&self) -> Base { self.parent } >>> fn method(&self) { ... } >>> } >>> >>> // Multiple inheritance >>> struct Multiple { >>> single: Single, >>> override: Override, >>> evenMoreData: ~str, >>> } >>> >>> // must specify which parent's implementation we want (could hide >>> wrapping inside of as_* methods impl'd on Multiple if you like) >>> // if we want one of them as the default, then we can impl DerivingTrait >>> on Multiple directly >>> struct MultipleAsSingle(Multiple); >>> struct MultipleAsOverride(Multiple); >>> >>> impl DerivingTrait<Single> for MultipleAsSingle { >>> fn super(&self) -> Single { self.single } >>> } >>> >>> impl DerivingTrait<Override> for MultipleAsOverride { >>> fn super(&self) -> Override { self.override } >>> } >>> >>> fn main() { >>> let base = Base { ... }; >>> let single = Single { ... }; >>> let override = Override { ... }; >>> let multiple = Multiple { ... }; >>> >>> base.method(); >>> base.super(); // compile time error >>> >>> single.method(); // =inline delegation=> single.super().method() >>> =inline upcast=> single.base.method() >>> override.method(); // done! no delegating >>> MultipleAsSingle(multiple).method(); // =delegate=> >>> MAS(multiple).super().method() =upcast=> multiple.single.method() >>> =delegate=> multiple.single.super().method() =upcast=> >>> multiple.single.base.method() >>> MutlipleAsOverride(multiple).method(); // =delegate=> >>> MAO(multiple).super().method() =upcast=> multiple.override.method() >>> } >>> >>> Thoughts? >>> >>> Eric >>> >>> >>> On Tue, Nov 12, 2013 at 10:30 PM, Kevin Ballard <ke...@sb.org> wrote: >>> >>>> On Nov 12, 2013, at 10:26 PM, Kevin Ballard <ke...@sb.org> wrote: >>>> >>>> > And even that restriction could be lifted if ~Trait objects could be >>>> represented using an array of pointers (one to each inherited struct), e.g. >>>> ([*A,*B,*C],*vtable) instead of just (*A,*vtable), though I suspect this is >>>> not worth doing. >>>> >>>> Upon further reflection, this would need to be done anyway because of >>>> the ability to combine traits. If I have >>>> >>>> trait TraitA : A {} >>>> trait TraitB : B {} >>>> >>>> and I want to use ~TraitA+TraitB then I would need a "fat" trait. >>>> Although in this case the number of value pointers is equal to the number >>>> of combined traits, so it's a bit more sensible to allow for "fat" trait >>>> pointers here. >>>> >>>> -Kevin >>>> _______________________________________________ >>>> 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 >>> >>> >> >
_______________________________________________ Rust-dev mailing list Rust-dev@mozilla.org https://mail.mozilla.org/listinfo/rust-dev