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

Conventions for the use of Deref and DerefMut #25

Closed
wants to merge 1 commit into from

Conversation

sfackler
Copy link
Member

This was discussed previously in rust-lang/rust#13126.

calls the `bar` function on the smart pointer type and `foo->bar()` calls the
`bar` function on the wrapped type. Rust could change to emulate this setup.
This would be a truly enormous change. `->` could be limited to use with
`Deref` and `DerefMut`, but that ghettoizes smart pointers and would also
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We could go the C route and only apply auto-deref via -> on all pointer types (i.e. (~int).foo() would be trying to call foo on ~int, but (~int)->foo() would attempt to auto-deref.)

@emberian
Copy link
Member

I'm starting to feel that a -> operator is going to be necessary, for understandability. When the behavior of autoderef on . was straightforward and non-overloadable, there wasn't really any understandability hazards.

Perhaps . could stay smart, and -> would be dumb indexing? I'd also really really like -> on pointers (like C), writing certain unsafe code becomes unmanagable without it. (*(*(*foo).bar).baz).qux can be an actual thing (I encountered it when playing with making &T -> &mut T transmutes forbidden)

@nikomatsakis
Copy link
Contributor

I think UFCS basically addresses the problems we'll find in practice.

There is no good reason we can't support autoderef for unsafe pointers, by the way. We just don't.

@sfackler
Copy link
Member Author

My understanding of UFCS may be incomplete, but I don't see how it will significantly affect this at all. We will still be unable to extend the API of smart pointers, users will still find it confusing when the make_unique method on one of their starts returning a different value than it used to, and they'll still have to fix it with some relatively obscure syntax. The only difference is that they'll be able to choose between (*foo).make_unique() and MyType::make_unique(&*foo) as the obscure syntax they'll want to use. It also doesn't handle public fields.

@nikomatsakis
Copy link
Contributor

To be honest, UFCS isn't really needed at all. I think people implementing smart pointers should just not put methods on them but rather define functions. I don't consider function call syntax to be "obscure". It seems clear enough to say "if you want to operate on the pointer rather than its referent you use a function". I guess it depends on how common such methods are. My experience in C++ has been that they are really quite rare, but YMMV.

I do think guidelines for when to implement Deref (and thus be considered a "smart pointer") are needed. It seems to boil down to a rule like "You should implement deref if your type is a largely transparent wrapper around some other type --- like a pointer. If you implement deref, you should not define methods of your own, but rather prefer functions."

Actually, one of the things we talked about at the work week as part of UFCS actually makes the problem worse. We had talked about not requiring that a function "opt-in" to being used like a method but just accepting any function with a compatible first argument. But this seems to screw smart pointers that might want to offer operations (and define traits) that do not interefere with autoderef. So I think we'll want to revise this (cc @pcwalton)

Ultimately I think that the idea of autoderef is completely incompatible with an overloadable *. We either have the current system or we go with making every deref explicit, like C++. Adding -> that corresponds to more than one deref doesn't seem to really solve the problem because of multiple indirection scenarios like Rc<Rc<T>>

@nikomatsakis
Copy link
Contributor

@sfackler it could be that I am underestimating the problem, though -- I guess this will become slightly clearer in time. In particular, I could imagine that smart pointers types might want to implement traits that define methods, and this is a potential problem.

@pcwalton
Copy link
Contributor

I am beginning to wonder whether -> is inevitable. Autoderef is starting to get more and more complex.

@pcwalton
Copy link
Contributor

pcwalton commented Apr 1, 2014

Niko has convinced me that -> is a non-starter (consider &Rc<Foo>—C++ gets away with this because of & references but we can't do that in Rust). Ignore comment above.

@emberian
Copy link
Member

emberian commented Apr 5, 2014

Also this isn't really RFC-worthy I don't think. It's not proposing a change to the language etc.

@nikomatsakis
Copy link
Contributor

I think it's too early to adopt best practices. We may change our autoderef rules etc etc. (I have some ideas I want to toy with.)

@ben0x539
Copy link

Instead of -> for deref+member access, can we make regular deref postfix so that you can do p~~.some_foo_method() (with p: &Rc<Foo>), à la rust-lang/rust#10011? Or is the problem more generally that having to explicitly deref through references is unacceptable?

(This is my secondary preference after the variable-length p-->some_foo_method() deref+member access operator, for which I don't have high hopes.)

@vadimcn
Copy link
Contributor

vadimcn commented May 25, 2014

How about allowing (or perhaps requiring) fields and functions of smart pointer types to be type-qualified? For example: rc.Rc::downgrade()

@alexcrichton
Copy link
Member

As we discussed earlier about this, we think it's a little premature to have ultimatums about this. For now, we're going to close this, but I'm going to tag this as postponed because we're going to want to revisit this once we've got some more traction with using these traits.

withoutboats pushed a commit to withoutboats/rfcs that referenced this pull request Jan 15, 2017
@Centril Centril added the A-convention Proposals relating to documentation conventions. label Nov 26, 2018
wycats pushed a commit to wycats/rust-rfcs that referenced this pull request Mar 5, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-convention Proposals relating to documentation conventions. postponed RFCs that have been postponed and may be revisited at a later time.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

10 participants