Bug 233384 - Ref<T> should support indirection operator *
Summary: Ref<T> should support indirection operator *
Status: RESOLVED WONTFIX
Alias: None
Product: WebKit
Classification: Unclassified
Component: Web Template Framework (show other bugs)
Version: Other
Hardware: Unspecified Unspecified
: P2 Normal
Assignee: Nobody
URL:
Keywords: InRadar
Depends on:
Blocks:
 
Reported: 2021-11-19 14:36 PST by Jean-Yves Avenard [:jya]
Modified: 2022-02-17 01:50 PST (History)
10 users (show)

See Also:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Jean-Yves Avenard [:jya] 2021-11-19 14:36:11 PST
While Ref<T> was supposed to be a replacement for T& with lifetime guarantees, C++ limitations made it act more like a pointer than a reference.
Ref<T> is more like a RefPtr<T> that guarantees it's never null.

A Ref can be converted into a RefPtr directly.
You already have to dereference the content of a Ref<T> using operator->().

So it makes sense that it also implements the indirection operator *.

I propose that Ref<T> be made to at the very least support the indirection operator and maybe even be officially be made into just a RefPtr that guarantees to never be null (so get() would return T* rather than T&
Comment 1 Alex Christensen 2021-11-19 15:36:58 PST
To me, the indirection operator is used when you have something that might be null/nullopt/error, so you check if (thing) { useThing(*thing); } but that isn't the case with Ref.  It never needs checking whether it's null because if you haven't used it after you moved from it, it's never null.  Adding the indirection operator would make it so when we write code that just calls useThing(*thing), we now have to think about whether it is a Ref or not.  Also, when someone down the line changes thing from a Ref to a RefPtr, we would then have code that may not be nearby that needs a null check, but you didn't notice it because it compiled fine.  This really needs operator dot, but C++ doesn't allow that.  It currently follows the convention of unique_ptr<T>::get which returns a T*, but it returns a T&.

Maybe we could implement Ref<T>::operator& instead of Ref<T>::ptr to get a T*, though.  That would be nicer syntactically.
Comment 2 Geoffrey Garen 2021-11-19 15:46:06 PST
Jean-Yves mentioned on Slack that supporting operator*() would make converting from RefPtr<T> to Ref<T> easier.

Alex seems to be pointing out that supporting operator*() would make converting from Ref<T> to RefPtr<T> harder / more error-prone.

It seems like the logic here is the same: There's an impedance mismatch because Ref<T>  offers more than RefPtr<T>.
Comment 3 Ryosuke Niwa 2021-11-19 20:42:25 PST
I'm pretty this is an intentional design choice because we wanted it to act like a reference. This is why Ref has operator T& whereas RefPtr doesn't, and Ref::get returns T& instead of T* as in RefPtr::get. To get a pointer, you call Ref::ptr instead.

I actually don't understand why we want operator *. Why would operator T& not be sufficient?
Comment 4 Jean-Yves Avenard [:jya] 2021-11-19 21:53:13 PST
(In reply to Ryosuke Niwa from comment #3)
> I'm pretty this is an intentional design choice because we wanted it to act
> like a reference. 

Indeed that was the intent, but the lack of operator.() in C++ makes it that you have to use -> to dereference it; as such, in practice it works like a pointer.

> I actually don't understand why we want operator *. Why would operator T&
> not be sufficient?

Yes, Alex made a good point there.

As Geoffrey mentioned, currently there's a mismatch between intent and actual usage.
Comment 5 Antti Koivisto 2021-11-19 23:16:08 PST
Originally Ref had just get() (since operator.() doesn't exist in C++). It was considered too verbose so operator->() was added as a somewhat inconsistent workaround. This doesn't mean it should have pointer-like semantics in general.
Comment 6 Ryosuke Niwa 2021-11-20 00:04:52 PST
(In reply to Jean-Yves Avenard [:jya] from comment #4)
> (In reply to Ryosuke Niwa from comment #3)
> > I'm pretty this is an intentional design choice because we wanted it to act
> > like a reference. 
> 
> Indeed that was the intent, but the lack of operator.() in C++ makes it that
> you have to use -> to dereference it; as such, in practice it works like a
> pointer.

Just because the presence of operator-> doesn't make it a pointer like. Ref::operator! works like T::operator! so it's not pointer-like in that regard for example. In fact, almost everything else doesn't behave like a pointer.
Comment 7 Ryosuke Niwa 2021-11-20 00:05:07 PST
FWIW, I'm opposed to the proposed change.
Comment 8 Radar WebKit Bug Importer 2021-11-26 14:37:25 PST
<rdar://problem/85773648>