Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Has someone considered an owned trait object? #2489

Closed
lqf96 opened this issue Jun 26, 2018 · 6 comments
Closed

Has someone considered an owned trait object? #2489

lqf96 opened this issue Jun 26, 2018 · 6 comments

Comments

@lqf96
Copy link

lqf96 commented Jun 26, 2018

Apart from &dyn Trait and &mut dyn Trait, both of which are borrowed trait objects, why don't we have an owned trait object type dyn Trait? Such type will likely be a DST with pointers to vtables (including Drop), size and align of the original value, followed by the value itself. Object safety rules will be relaxed on the owned trait object type to allow self to be consumed.

Together with DerefMove this can be used to replace FnBox for Box<dyn FnOnce(...) -> ...> syntax.

@SimonSapin
Copy link
Contributor

The own trait object is Box<dyn Trait> a.k.a. Box<Trait>.

DerefMove still requires the value being moved to be Sized, in order to figure out how much stack space to allocate. This is why Box<dyn FnOnce> doesn’t work today.

@lqf96
Copy link
Author

lqf96 commented Jun 26, 2018

I'm actually thinking of implementing it in the opposite way. dyn Trait is owned and can be placed anywhere, either on the stack or on the heap. And then Box will only allocate memory and move the dyn Trait object from the stack to the heap.

@Ixrec
Copy link
Contributor

Ixrec commented Jun 26, 2018

@lqf96 That's basically "unsized rvalues", for which the tracking issue is: rust-lang/rust#48055

@lqf96
Copy link
Author

lqf96 commented Jun 27, 2018

@Ixrec Yes, such type will have to rely on unsized rvalues. What I want to propose is that object safety rules on dyn Trait can be relaxed so that self can be consumed. An example would be like this:

struct A(u32);

trait Test {
    fn test(self) -> u32;
}

impl Test for A {
    fn test(self) -> u32 { self.0 }
}

And then you can cast variable with type A to type dyn Test and call method test without knowing the type of underlying value:

// Create an `A` instance and cast it to an owned trait object
let a = A(10) as dyn Test;
// Consume the owned trait object
println!("{}", a.test());
// `a` is consumed and can no longer be used

With dyn Trait type we no longer need to do anything special to support dynamic dispatch on arbitrary self types, as every arbitrary self type can Deref, DerefMut or DerefMove to &dyn Trait, &mut dyn Trait or Dyn Trait, and the latter trait object types will all support dynamic dispatch right out of the box.

@qnighy
Copy link

qnighy commented Jun 28, 2018

object safety rules on dyn Trait can be relaxed so that self can be consumed

That is the part of the unsized rvalues RFC. In fact, it's one of the two achievements which the RFC aims at. The other one is the fast allocation of small arrays.

With dyn Trait type we no longer need to do anything special to support dynamic dispatch on arbitrary self types,

I'm not sure which problem you're referring, but at least the problem listed here doesn't seem to be relevant to unsized self: Self.

@Centril
Copy link
Contributor

Centril commented Oct 9, 2018

This seems to be completed as per the unsized rvalues RFC per notes above, thus, I'll close this issue.

@Centril Centril closed this as completed Oct 9, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants