Note that Reference& (and not const Reference&) obscures in the call sites that the object can actually be changed. This is more obvious with pointers which require the address to be &taken or the variable type to be a pointer.
On Mon, Sep 9, 2013 at 6:32 PM, Peter Kasting <pkas...@google.com> wrote:
On Mon, Sep 9, 2013 at 6:10 PM, Paweł Hajdan, Jr. <phajd...@chromium.org> wrote:
Note that Reference& (and not const Reference&) obscures in the call sites that the object can actually be changed. This is more obvious with pointers which require the address to be &taken or the variable type to be a pointer.For this reason the Google (and hence Chromium) Style Guide bans non-const reference arguments to functions, which is a practice I suggest the Blink community adopt if it hasn't already done so.(In general, I normally go further and suggest in my code reviews that people avoid non-const refs entirely, using either const refs or pointers as appropriate.)If document() returns a Document& then you'd need to convert it back into a pointer to pass it to anything (or we switch it back to Document*). I think the Document* might be better, but it does mean we end up with null checks when developers don't understand the lifetime of objects.
I've seen a lot of changes going by over the last several weeks
changing, e.g., Node::document() now returns a Document& instead of
Document*. My understanding was that these are being ported over from
similar work in WebKit, but I was surprised that there wasn't a
discussion about this change on blink-dev, especially given that I've
seen comments on code reviews from some Blink OWNERS (at least esprehn
and eseidel, CCed) that they're not sure the current approach is
ideal.
So, consider this a place to have that discussion. I'd hope that
besides broadening knowledge and consensus about the right way of
making this change in the codebase, this thread would also end up
giving us a few sentences to put in the style guide governing when to
use pointers vs references.
On Mon, Sep 9, 2013 at 6:10 PM, Paweł Hajdan, Jr. <phajd...@chromium.org> wrote:
Note that Reference& (and not const Reference&) obscures in the call sites that the object can actually be changed. This is more obvious with pointers which require the address to be &taken or the variable type to be a pointer.For this reason the Google (and hence Chromium) Style Guide bans non-const reference arguments to functions, which is a practice I suggest the Blink community adopt if it hasn't already done so.
How does the OilPan work impact this? That work is happening on a branch, but in a nut-shell it is about changing reference counted DOM nodes into heap managed objects that can be GC'd. It involves using Handle<T> in place of raw pointers. Will all of the work to change pointers to references just be wasted effort if we have to again change them to Handle<T>?
This seems to support the idea of having a NotNull<T> type, presumably
with oilpan we might want a NotNullHandle<T>?
To unsubscribe from this group and stop receiving emails from it, send an email to blink-dev+...@chromium.org.
Hi,Thanks tkent@!I personally like it:- Useless null checks will (still) not compile- Less refactoring work as it can still be used as a pointer (unlike references), we only need to update the APIs, not the code.- Makes pointer comparison nice again. With references we had to do (&a == &b)- Could potentially have NonNullRefPtr / NonNullPassRefPtr alternatives?One drawback I can see is that it makes it less obvious (compared to references) to reviewers when null checks are missing. The code still looks unsafe as the type still has pointer semantics:a.b().c() looks safe, but a->b()->c() does not. As a reviewer, you would have to look at the declarations of a() and b() to make sure this is correct (i.e. they return NonNullPtr<T> types).
I'm sorry that I started some work without any notification.I converted some arguments and return values in Page and the editing area. I found no downsides in these areas because- Ownership is very clear. e.g. Page owns a FocusController.- No need to compare objects.I removed a lot of unnecessary NULL checks, and it must have reduced binary size and source code size, and we don't need to worry about NULL deferences of these objects any longer.I think it's worth to proceed the reference-conversion for objects handled by OwnPtr or similar relationship.The difference between the above case and DOM nodes:- DOM node values are never null in some cases. e.g. Node::document() and Document argument of Node factories- DOM node values can be null in some cases. e.g. Document::focusedElement() can be null.- We need to compare DOM nodes frequently.I don't have a strong opinion about DOM nodes. AFAIK, almost all of RefCounted classes are unable to copy, and we may want to have operator== implementations with pointer comparison.
I guess the following rules will satisfy many developers.* Use NonNullPtr<T>, not C++ referencesIt's compatible with Chromium coding style.(We should have shorter better name. NotNull<T>?)
* Don't add Ref<T>, which is non-nullable RefPtr<T>. Don't support Non-nullable types in IDL.They have additional complexity, and need too much code change. We should revisit them when we have the decision about Oilpan.WDYT?
To unsubscribe from this group and stop receiving emails from it, send an email to blink-dev+...@chromium.org.
I discussed this in person with some folks yesterday who shared my concerns and so decided to chime in on the thread.I don't think we should re-invent non-nullity (not least because NotNull<Document> everywhere looks very verbose to me). If we want to have non-null references, we should use our language's native version: C++ references.I'll address each complaint I've heard about that approach.Problem: Comparisons between, e.g., Document& now need "&" to compare pointersSolution: Add operator== for Nodes (or maybe just TreeShared) that compares pointers.
Problem: Chromium style says not to use non-null references, and to use pointers insteadSolution: Blink style has long used references for out-params, and elsewhere (e.g., for some DEFINE_STATIC_LOCALs). Blink style needn't be identical to Chromium style, especially when we're already following existing Blink style practices.Problem: WebKit's Ref class is weirdSolution: Don't use it. If we want to reduce the use of the & operator, we could add a RefPtr(T&) constructor.
If folks are interested in discussing further, I propose we have a 15-minute huddle sometime today as part of BlinkOn.- AdamOn Tue, Sep 24, 2013 at 4:05 AM, Christophe Dumez <dch...@gmail.com> wrote:
Sounds good to me as well, Thanks.On Mon, Sep 23, 2013 at 6:38 PM, TAMURA, Kent <tk...@chromium.org> wrote:
I guess the following rules will satisfy many developers.* Use NonNullPtr<T>, not C++ referencesIt's compatible with Chromium coding style.(We should have shorter better name. NotNull<T>?)* Don't add Ref<T>, which is non-nullable RefPtr<T>. Don't support Non-nullable types in IDL.They have additional complexity, and need too much code change. We should revisit them when we have the decision about Oilpan.WDYT?--
TAMURA Kent
Software Engineer, Google
To unsubscribe from this group and stop receiving emails from it, send an email to blink-dev+...@chromium.org.
--
Christophe DUMEZ
Problem: With non-const refs, you can't tell at the callsite whether a function will modify an input parameter.Also, a bit of a nit, but C++ references are not "non-null".
The advantage of NonNull<T> is that you could actually put a DCHECK in there that enforces the invariant.
This leaves out the main argument against non-const refs, the underlying rationale for Chrome's styleguide:Problem: With non-const refs, you can't tell at the callsite whether a function will modify an input parameter.Also, a bit of a nit, but C++ references are not "non-null". They are perfectly happy to be null:Foo *f = NULL;Foo& f2 = *f;
This leaves out the main argument against non-const refs, the underlying rationale for Chrome's styleguide:Problem: With non-const refs, you can't tell at the callsite whether a function will modify an input parameter.Also, a bit of a nit, but C++ references are not "non-null". They are perfectly happy to be null:
Foo *f = NULL;
Foo& f2 = *f;
printf("%d", f2.bonk);
On Thu, Sep 26, 2013 at 1:19 PM, Aaron Boodman <a...@chromium.org> wrote:
This leaves out the main argument against non-const refs, the underlying rationale for Chrome's styleguide:Problem: With non-const refs, you can't tell at the callsite whether a function will modify an input parameter.Also, a bit of a nit, but C++ references are not "non-null". They are perfectly happy to be null:Foo *f = NULL;Foo& f2 = *f;This is undefined behavior (8.3.2p4)
and can be found by asan or valgrind just as well as the DCHECK as far as I know ( http://valgrind.org/docs/origin-tracking2007.pdf ).
On Thu, Sep 26, 2013 at 1:28 PM, Nico Weber <tha...@chromium.org> wrote:
On Thu, Sep 26, 2013 at 1:19 PM, Aaron Boodman <a...@chromium.org> wrote:
This leaves out the main argument against non-const refs, the underlying rationale for Chrome's styleguide:Problem: With non-const refs, you can't tell at the callsite whether a function will modify an input parameter.Also, a bit of a nit, but C++ references are not "non-null". They are perfectly happy to be null:Foo *f = NULL;Foo& f2 = *f;This is undefined behavior (8.3.2p4)
It doesn't seem like the undefinedness helps us in practice -- it's still a very easy bug to type accidentally.
and can be found by asan or valgrind just as well as the DCHECK as far as I know ( http://valgrind.org/docs/origin-tracking2007.pdf ).
Perhaps. I guess my take is that the same way a bug found by the compiler is preferable to a bug found by a unit test
, a bug found by a DCHECK is better than a bug found by valgrind.
- a
This leaves out the main argument against non-const refs, the underlying rationale for Chrome's styleguide:Problem: With non-const refs, you can't tell at the callsite whether a function will modify an input parameter.
Also, a bit of a nit, but C++ references are not "non-null". They are perfectly happy to be null:Foo *f = NULL;Foo& f2 = *f;printf("%d", f2.bonk);You can imagine this will happen all the time accidentally when converting to reference params or return values.
So, I'd like to conclude we should use references to represent non-null objects.
It doesn't mean we use references forever. If we decided to follow Chromium coding style entirely or found critical problems with references, we would switch back to pointers or NotNull<T>. Even if the switching back happens, using references for now is beneficial because it clarifies what are not nullable.
On Thu, Oct 3, 2013 at 7:39 AM, TAMURA, Kent <tk...@chromium.org> wrote:
So, I'd like to conclude we should use references to represent non-null objects.
It doesn't mean we use references forever. If we decided to follow Chromium coding style entirely or found critical problems with references, we would switch back to pointers or NotNull<T>. Even if the switching back happens, using references for now is beneficial because it clarifies what are not nullable.This is not the kind of switch we should be making multiple times. If we switch, it should be because we intend to change forever.
There have been stated (if vague) goals in the past to align more with Google and Chromium style over the long term. This would be a pretty strong move in the opposite direction.
Rather than just taking a poll about what people would like in the abstract, I'd like to explicitly hear the other owners' comments on that particular issue, as well as the underlying reason for the Google style rule -- which Aaron originally raised, but got lost in discussion about whether references can actually be NULL.
No one addressed the much more critical issue of why the Google (and thus Chromium) style guides ban non-const ref arguments in the first place, which is clarity at the callsites.
Given that Node::document() already returns a reference, using these as our axioms would mean that the future's already set, and so we could stop this thread altogether.
Rather than just taking a poll about what people would like in the abstract, I'd like to explicitly hear the other owners' comments on that particular issue, as well as the underlying reason for the Google style rule -- which Aaron originally raised, but got lost in discussion about whether references can actually be NULL.Concretely, the reason I (as a Blink owner) would prefer references over pointers are that they make it clear that the value cannot be null (I think I already stated this up thread). This is not a side-point, it's in fact the whole point of this thread (and the changes it refers to).
You two seem to be talking past each other a bit. There are two separate issues:
1) Should we use non-const references to represent non-NULL pointers to non-copyable object (e.g., Document).2) Should we use non-const references as out parameters for copyable types (e.g., Vector).It might be worth discussing these topics in separate threads as they are largely unrelated to each other. For example, whether a function receives a Document* or a Document& had no effect on what changes that function can make to the Document or the caller's local variables whereas if we pass a Vector<Foo>& to a function, then the function is able to modify local variables in the caller's scope.
PK
Its the difference between being able to do this:void foo(Document* doc) {*doc = Document();}and not being able to:void foo(Document& foo) {foo = Document() // this just changes the local ref.}
void foo(...) {
Document* doc = ...bar(doc);baz(*doc);}void bar(Document*) { ... }void baz(Document&) { ... }I believe the effects that bar and baz can have on foo and doc are the same. That's issue (1). Issue (2) is about the following pattern:void foo(...) {int x = 0;bar(x);}void bar(int& result) { ... }In this case, it's not clear from the text of |foo| what effects calling bar will have on x. The bar function might alter the value of x unexpectedly.
On Thu, Oct 3, 2013 at 11:13 AM, Adam Klein <ad...@chromium.org> wrote:
Given that Node::document() already returns a reference, using these as our axioms would mean that the future's already set, and so we could stop this thread altogether.I'm confused. I thought the entire point of this thread was that the current codebase uses pointers extensively, and the question was whether to shift to references in all places where the pointer cannot be NULL. Your original message in the thread seems to imply that such a shift has just started to take effect, and that we should discuss it before it actually becomes widespread.Now you seem to be saying that the codebase uses references extensively, and a decision to "use references" means leaving things as they are. Indeed, you even tell me explicitly that an argument for _not_ using references in some cases is out of scope for this thread, which I find quite surprising.
Rather than just taking a poll about what people would like in the abstract, I'd like to explicitly hear the other owners' comments on that particular issue, as well as the underlying reason for the Google style rule -- which Aaron originally raised, but got lost in discussion about whether references can actually be NULL.Concretely, the reason I (as a Blink owner) would prefer references over pointers are that they make it clear that the value cannot be null (I think I already stated this up thread). This is not a side-point, it's in fact the whole point of this thread (and the changes it refers to).Perhaps I was unclear. I understand already that the benefit of references is as a way to indicate "cannot be NULL". I wasn't talking about whether indicating such a thing was a good idea. I was asking explicitly for comments on the issue of callsite unclarity due to non-const refs, as that is a restriction on code outside Blink, and lots of important folks have expressed desires in the past to migrate Blink and Chromium styles closer together over time.
The reason this is relevant is because if we intend to change the Blink style guide to require references in all cases where arguments cannot be NULL, that implicitly requires non-const refs any time those arguments aren't passed by value; and so we should either knowingly decide that we want that, and we disagree with (or don't care about) the Google style guide, or make some sort of exception/alternative plan.
I guess many Blink developers don't agree with the concern.
Many objects such as DOM nodes are really unstable, and developers always need to consider possibility that a function call modifies a passed object regardless of callee(doc) or callee(&doc).
Also, using pointers doesn't show such signals in many cases.
On Thu, Oct 3, 2013 at 2:06 PM, TAMURA, Kent <tk...@chromium.org> wrote:Many objects such as DOM nodes are really unstable, and developers always need to consider possibility that a function call modifies a passed object regardless of callee(doc) or callee(&doc).void foo(const Document& doc);
I addressed this some in my latest reply to Adam (Barth). I would also suggest that "there are cases where you don't get good signals" is not the same as saying "there are no cases where you _do_ get good signals". The point of a style guide is to suggest global uses of certain patterns precisely so not everything comes down to a local determination.