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

Owned references to contents in an earlier stack frame (&own, &move, etc) #998

Open
nikomatsakis opened this issue Mar 21, 2015 · 11 comments
Labels
T-lang Relevant to the language team, which will review and decide on the RFC.

Comments

@nikomatsakis
Copy link
Contributor

nikomatsakis commented Mar 21, 2015

A common request is to have a way to pass a reference that actually owns its referent. The idea originated long ago in an attempt to find a suitable type for Drop, but it's not a perfect fit there (you really want to not own the struct being dropped, just its fields). It has since resurfaced as a means to pass ownership of unsized types (but see #990 as well) and various other use cases.

Postponed RFCs

@ticki
Copy link
Contributor

ticki commented Dec 6, 2015

👍 Doing this in a safe way w/o heap allocation would be neat.

@ticki
Copy link
Contributor

ticki commented Dec 8, 2015

Are there any unresolved questions?

@burdges
Copy link

burdges commented Jan 18, 2016

It sounds like a comonad actually, so state machines, etc.

There is an RFC proposing impl delegation here : #1406

I'd imagine this could be done by delegating several impls to a reference pointer, while offering a destroy routine that returns the referent pointer, otherwise kept hidden and unsafe. In many situations, destroy would return an index too. I donno if this pattern could be abstracted to encapsulate the unsafe somehow.

There isn't afaik any reason to touch the usual comonad definition here, but comonads do run close to object oriented programming http://www.haskellforall.com/2013/02/you-could-have-invented-comonads.html It's not too odd that an RFC for adding a form of inheritance would help add the most well understood application of comonads too.

@cramertj
Copy link
Member

Alternatively, is there a clean way to make references more extensible in general? It seems to me that an alternative approach that allowed substitution of references for anything implementing Deref would be really useful. For example, in public library structs with internal references, it seems like references are too limiting: really, the user should be able to provide a reference, Rc, Arc, Box, or whatever they please. The obvious answer is to make every such struct generic on Deref, but that adds a lot of unnecessary boilerplate (SomeStruct<Deref<Target = RefType1>, Deref<Target = RefType2>, ...>) in comparison with simple references.

@pnkfelix
Copy link
Member

@cramertj I think what you are asking for are higher-kinded types (HKT)?

so that one could have a library parameterized over a type constructor from type to type (and I guess also in this case the type resulting from the construction would be expected to implement Deref in an appropriate manner); then you would instantiate such a library with the desired reference type constructor: Rc, Arc, Cow, .,..

If that is indeed what you are describing, then yes, HKT is something the community has been discussing for a long while. (However, I believe it to be separate from the construct described on this ticket, at least in the sense that whether or not we add HKT is largely orthogonal to whether we add a &own that the borrow checker knows how to reason about )

@cramertj
Copy link
Member

Yes, I'm essentially proposing a specific use case of HKTs. I wasn't sure whether or not this RFC was designed with HKTs in mind-- perhaps I don't properly understand the concept of own. Given the application of HKTs I suggested, why must &own be a special type of reference separate from a generic Own<T> in the standard library? It seems like Own could just be a simple wrapper struct with a single field of type T, which could be factored out at compile time.

@Centril Centril added the T-lang Relevant to the language team, which will review and decide on the RFC. label Feb 23, 2018
@clarfonthey
Copy link
Contributor

This honestly might be worth revisiting for types that can't be pinned. Having a way of transferring ownership without moving would be very handy.

@clarfonthey
Copy link
Contributor

One other interesting thing that I thought of is: what if there were an &own and an &own mut? That way the only distinction is that the "owning" simply indicates that the object will be dropped after the lifetime, with potential sugar to allow treating moves as offering owned references instead.

With &own the object cannot implement Drop, and you simply get the ability to look at the object without changing it before it's deleted. With &own mut, you can also drop the item at the end of its lifetime.

Honestly, I don't know what the use of immutable owned references would be, unless we were to add an immutable version of the Drop trait which simply did something at the end of scope without modifying anything. And even then, I'm not really sure what that'd accomplish.

But maybe it'd be a cool concept to consider, because it'd help explicitly annotate whether mutation has to happen during the lifetime during the drop. Like, ownership is merely a property of the reference, rather than it being a level of reference above usual mutability.

@RustyYato
Copy link

I don't see the point of having the immutable version because it's not Drop that you need to guard against, it's all drop glue. So pretty much all useful types.

@clarfonthey
Copy link
Contributor

I mean, that's fair, although I would argue against "all useful types" because not all types contain heap allocations or other resources to tear down.

Another interpretation is that taking an immutable reference is similar to calling mem::forget and forgoing the destructor, which could also be useful. But I'm also saying this kind of theoretically and can't think of any use cases, which is why I'm bringing this up in the discussion here instead of just assuming that I'm making the right call. :P

@RustyYato
Copy link

I mean, that's fair, although I would argue against "all useful types" because not all types contain heap allocations or other resources to tear down.

True, I should have said most useful types.

Another interpretation is that taking an immutable reference is similar to calling mem::forget

Or you could just mem::forget the owned pointer. I don't see a reason to make leaks so easy to create.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
T-lang Relevant to the language team, which will review and decide on the RFC.
Projects
None yet
Development

No branches or pull requests

8 participants