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

?. operator should extend to remaining selectors #26240

Closed
MikeMitterer opened this issue Apr 11, 2016 · 9 comments
Closed

?. operator should extend to remaining selectors #26240

MikeMitterer opened this issue Apr 11, 2016 · 9 comments
Labels
area-language Dart language related items (some items might be better tracked at github.com/dart-lang/language). core-l type-enhancement A request for a change that isn't a bug

Comments

@MikeMitterer
Copy link

MikeMitterer commented Apr 11, 2016

The ?. operator should extend to the remaining selectors.
That is, o?.x.y should be legal, and not bomb on the .y access.

This issue was edited by @floitschG. Original content below:

final dom.HtmlElement elementToActivate = query("[for=${propertyName}]");
elementToActivate?.classes.add(_cssClasses.ACTIVE);

Shows `INFO: The expression uses '?.', so can be 'null'``
It wants a ?. between "classes" and "add"
This is wrong - elementToActivate can be null but not "classes"

html_dartium:

CssClassSet get classes => new _ElementCssClassSet(this);
@bwilkerson
Copy link
Member

If elementToActivate is null, then elementToActivate?.classes will also be null.

@MikeMitterer
Copy link
Author

Clear - but it makes no sense to double check

elementToActivate?.classes?.add(...) would be the same as:

if(elementToActivate != null) {
    if(elementToActivate.classes != null {
       ...
    }   
}

@bwilkerson
Copy link
Member

But without the extra check, the code is equivalent to

var classes = elementToActivate == null ? null : elementToActivate.classes;
classes.add(...);

which can result in a null pointer dereference.

You could argue that the ?. operator ought to short circuit everything to the right (in which case this is a language issue), but that's not the current definition.

@MikeMitterer
Copy link
Author

Uhhh - really?? To me it is logic that the first ?. operator makes all checks to the right unnecessary. I think someone should update the current definition. And - yes, I think this is a language issue!

BTW: In C# for example operators are also short-circuiting

@bwilkerson bwilkerson added the area-language Dart language related items (some items might be better tracked at github.com/dart-lang/language). label Apr 12, 2016
@eernstg
Copy link
Member

eernstg commented Apr 12, 2016

It's certainly a modified semantics to say that x?.y.z should evaluate to
null if x is null, rather than throwing a NPE because we attempt to look
up z in the null object.

Given that member access associates to the left (with x.y.z, we evaluate
x, then .y of that object, then .z of that object again), and given
that we do have members like toString and runtimeType on null, it would
be a rather twisted exception to say that exactly that .z should be
skipped in x?.y.z, because we evaluated x to null.

Do you think there is a simple and consistent way to explain what is going
on if we were to take such a shortcut? To me it looks like a tiny
convenience, bundled with a significant source of confusion. Just consider
(x?.y).z, should the shortcut semantics bleed through the parentheses? ..
and how about (w = x?.y).z? .. or ((x) => x?.y)(x).z?

On Tue, Apr 12, 2016 at 4:37 PM, Mike Mitterer [email protected]
wrote:

Uhhh - really?? To me it is logic that the first ?. operator makes all
checks to the right unnecessary. I think someone should update the current
definition. And - yes, I think this is a language issue!

BTW: In C# for example operators are also short-circuiting


You are receiving this because you are subscribed to this thread.
Reply to this email directly or view it on GitHub
#26240 (comment)

Erik Ernst - Google Danmark ApS
Skt Petri Passage 5, 2 sal, 1165 København K, Denmark
CVR no. 28866984

@lrhn
Copy link
Member

lrhn commented Apr 12, 2016

If you look at the following accesses as a chain of selectors, it makes a kind of sense to short-circuit the entire rest of the chain.
We have the construct already in cascades: x..y.z.w()..p.q.r() - in this the cascade extends only through the following chain of selectors (.z.w() for x..y). If we can adopt the same syntactic approach for ?. as for .. then it is possible to either handle the entire selector chain or none of it.

It does have some consequences, just as for cascades - parentheses become meaningful and necessary in some cases. It won't have the same precedence as cascade - it's still like the normal dot operator - and it might not be obvious where a selector chain ends, but I think it's worth trying it out to see if it can work.

@MikeMitterer
Copy link
Author

@eernstg You say it looks like a tiny convenience - I think it's more. In my opinion it's just more logical to assume that the ?. is short-circuiting. A language feels good if it does what you think it should do. That's one reason why I like Dart. You know all the specs but the average programmer doesn't read all the specs...
(w = x?.y).z 😅 😅 My interpretation: It assigns either x or y to w depending if x is null or not. It calls z on the result. So if there should be a null-check for z I would write (w = x?.y)?.z (BTW I hope such constructs won't be used in average code - nobody knows what it should do without extra lines of comments)

@floitschG floitschG mentioned this issue May 24, 2017
16 tasks
@floitschG floitschG changed the title Wrong warning on ?. operator ?. operator should extend to remaining selectors May 24, 2017
@floitschG
Copy link
Contributor

I updated this issue to reflect the requirement to change the language spec.

@lrhn
Copy link
Member

lrhn commented Oct 6, 2021

This feature is included in Dart 2.12 (the null safety release, because with null safety we really did want to be able to distinguish whether a?.foo is nullable because a is nullable or because a.foo is, and warn you if you write a?.foo?.bar when a.foo isn't nullable.).

@lrhn lrhn closed this as completed Oct 6, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area-language Dart language related items (some items might be better tracked at github.com/dart-lang/language). core-l type-enhancement A request for a change that isn't a bug
Projects
None yet
Development

No branches or pull requests

5 participants