Deref
's documentation certainly has added to this discussion, and I think the documentation should be fixed in either case.
However, the term "smart pointer" doesn't only appear in the context of Deref
. I would even say that it's one of Rust's major peculiarities to utilize "smart pointers" such as
but also other types that might fall into this category such as
- guards (e.g.
MutexGuard
)
- wrapper types for dynamic borrows (e.g.
Ref
and RefMut
)
- "pointer types" influencing storage / movement in memory such as
- the special case of
Cow
- the special case of
Weak
(rc::Weak
and sync::Weak
)
- cells and mutexes (e.g.
RefCell
and Mutex
)
- buffers such as
- wrappers (including zero-cost wrappers) such as
- and possibly some other that I didn't even think of yet
Not wanting to imply all of these should be considered smart pointers, but some for sure. No wonder, the term "smart pointer" (or the generalized term "pointer type") also appears in the reference and repeatedly pops up in discussions (which was actually the trigger that made me rise the question).
Being interested in Rust and modern computer programming languages in general, i'm interested in the used terminology, and I don't think this discussion is "moot" after Deref
's doc has been fixed. (Besides, the reference uses the terminology as well.)
However, I also understand that this sort of discussion doesn't interest everyone, and that's totally fine.
Having said the above, I think it makes sense to differentiate between the two questions:
- When and when not to implement
Deref
- What are "smart pointers"
The question when to implement Deref
is an important one (and one that may be of more practical value for most people here rather than debating about "academic" terminology). In that context, the ticket created by @2e71828 contains a reference to another discussion (Understanding the perils of Deref
) which I haven't read yet. It may also deserve further discussion / documentation / etc., but I meanwhile think that it's best to leave that question out when trying to define what a smart pointer is.
That said, I'm still interested in debating the issue of the terminology "smart pointer" further (for the reasons explained above), but I'm not sure if it's possible to make any progress here. I'll give it a try, however, and throw in some new (updated) hypotheses:
- Smart pointers are entirely generic in regard to their target, which means
String
is not a smart pointer.
- Smart pointers do not always provide a fail-safe (or non-blocking) dereferencing mechanism, which particularly means that
Mutex
and RefCell
but also Weak
or Option
could be considered smart pointers, and also means that in not all smart pointers can implement Deref
in Rust (as Deref::deref
should never fail, at least in Rust).
Note: I'm very unsure on this, and maybe in the context of Rust it makes sense to demand never-failing dereferencing, as it's also the case with ordinary references. Perhaps it makes sense to think about a term like "smart references", which demand fail-safe deref?
- Smart pointers do not always point to values on the heap.
- Wrappers which are intended to change the behavior of the wrapped type (newtype pattern) go beyond of what a smart pointer usually does and thus are not considered smart pointers.
I'm not sure if "storage" is the right term. When I think of storage, I think of "wrappers". A Cow::Borrow
doesn't store anything. It points to something. Also the Cow::Owned
points to something (but adds some "smartness" to dispose of the value when the Cow
goes out of scope).
But I do like what you wrote with "the T
being pointed at is far more important to the user than the fact that it's wrapped by something else." It's a bit vague though, and it might rule out Mutex
and MutexGuard
as it's a very important property of these that they actually perform locking.
Interesting fact. Also note that Pin<P>
doesn't impose any bounds on P
(only in methods / implementations).
Right now this might be an implication of Deref
's documentation. But I think that should be changed (for the reasons that came up in this thread). In particular, such a definition would rule out Weak
being considered a smart pointer, and it would imply that non-generic types such as String
are a smart pointer (which I don't think anymore they are).