Fwd: Null-Restricted and Nullable Types concern
Caleb Cushing
caleb.cushing at gmail.com
Mon Nov 18 17:54:18 UTC 2024
>
> Back to your example: for findFoos, I believe javac will generate some
> sort of unchecked cast warning upon both instances of toString calls; there
> is no way the compiler knows that the result of a filter(Objects:nonNull)
> changes the type of the resulting stream.
>
I would think that the jdk would be the only thing that would be able to
make this inference. even if this was only planned as future work, it feels
like a thing that needs to be planned as future work.
... So to me it sounds like the only benefit over existing implementations
is syntactic sugar? I'm all for syntactic sugar in this case. Although then
I don't see the need for the changes to the constructor; that's not
something I'm worried about though.
even if it was released in the next jdk it won't super effective for
another decade at least (this doesn't mean don't try). I'm basing this on
the amount of time it will take libraries and Enterprise to adopt. Spring
has only recently adopted Java 17. Most things are still on Java 11 or even
8 as far as compatibility support. Without any support to enforce a policy
at the package or module level I don't really see people adopting this
anymore than they have adopted jpms which is to mean pulling teeth to get
them to even add an automatic module. The libraries that have null support
now seem to have only done so because of their ability to provide sensible
defaults.
I really do believe this is a feature that Java needs, and I'm glad it's
being worked on, I just think it needs to go a little farther before it
would be adopted.
Anyways, I just felt like I needed to give feedback as best I could based
on the JEP that I read. As this is a feature that I truly care about. I can
take off now, I have said what I needed to say.
I hope that answers your questions and relieves your concerns.
>
> Regards,
> Chen Liang
> ------------------------------
> *From:* valhalla-dev <valhalla-dev-retn at openjdk.org> on behalf of Caleb
> Cushing <caleb.cushing at gmail.com>
> *Sent:* Friday, November 15, 2024 11:13 AM
> *To:* Brian Goetz <brian.goetz at oracle.com>
> *Cc:* valhalla-dev at openjdk.org <valhalla-dev at openjdk.org>
> *Subject:* Re: Fwd: Null-Restricted and Nullable Types concern
>
> > This is a valid opinion, but let's be clear what you're saying: it means
> you think that having a solid, committed flippening story is so important
> that you're willing to say that "no one can have the benefits of valhalla
> for another 5-10 years, or maybe ever." That's a pretty big deal. (And,
> yes, sometimes we are willing to make such tradeoffs, but it's still a
> pretty big deal.)
>
> I just want to say that I get that, but also things that go into the
> JDK tend to get stuck that way. I would like this feature 10 years
> ago, but I don't want to get stuck in a bad situation that we can't
> back out of because it might break someone's code. There are weird
> (unrelated) situations where I do not understand why the behavior has
> been preserved when it doesn't make sense, only because someone,
> somewhere, might be relying on the implicit (NPE) failure which was
> likely a mistake in coding. So even some semblance of an idea for a
> plan, even if it's not committed to, like this is a "preliminary idea
> which could change"; would be good. I'm just concerned about
> delivering a "stable" feature that can't change because it might break
> someone's code. Please also be aware that I wouldn't be commenting at
> all if I didn't care, or wasn't excited about this impossible work.
>
> In any sense, the JEP didn't seem to discuss the exact examples
> mentioned, so hopefully we can move on to those ;) although perhaps
> they are "future work"
>
> On Fri, Nov 15, 2024 at 11:55 AM Brian Goetz <brian.goetz at oracle.com>
> wrote:
> >
> > Before anything makes it into the JDK I'd like to see the plan for
> > this
> >
> >
> > This is a valid opinion, but let's be clear what you're saying: it means
> you think that having a solid, committed flippening story is so important
> that you're willing to say that "no one can have the benefits of valhalla
> for another 5-10 years, or maybe ever." That's a pretty big deal. (And,
> yes, sometimes we are willing to make such tradeoffs, but it's still a
> pretty big deal.)
> >
> > But, maybe that's not what you meant. Maybe what you meant is "I want
> to impress on you how important I think it is to get to where the nullity
> default is flipped." If that's what you mean, yes, we understand how
> strongly some people feel about this. Our antipathy to attacking this
> problem *right now* is not because we don't think it is a real pain point,
> but one of practicality: it's not possible to solve all the problems
> simultaneously and still deliver something in a mortal lifetime.
> >
> > Or maybe what you meant is "there seem to be simple solutions to this
> problem, why wouldn't we jump on them?" Unfortunately just because a
> solution is obvious (like "let's just put a bang on the module directive"),
> doesn't mean they are simple. (To be clear, you are asking for what would
> be, by far, the biggest change to Java ever -- reinterpreting existing code
> to mean something else based on a directive _in another file_.) Rest
> assured that we've seen these "solutions" proposed before, and our lack of
> enthusiasm for them is that they may well create more problems than they
> solve.
> >
> > So, we get that adding null restriction to Java will significantly
> worsen the fact that "nullable" is yet another bad default; this is pretty
> clear. But if we really thought that we can't do Valhalla until we
> reinterpret all the world's Java code with a new default, the rational
> response might well be to cancel the project. Sometimes things have to be
> separated out into smaller, dependent chunks; sometimes we even have to
> accept that we might not even get to all the later chunks.
> >
> > I get that you would be more comfortable if we had a committed,
> bulletproof plan for this. But I think I can say with confidence that we
> won't; we need to focus our attention on the many nearly-impossible
> problems we already have in front of us before adding more to our plate.
> >
> >
> >
> >
> > On 11/15/2024 11:16 AM, Caleb Cushing wrote:
> >
> > It is not a goal to automatically re-interpret existing code—use of
> these features should be optional and explicitly opted in to (future work
> will explore mechanisms to request a bulk opt-in without needing to change
> individual types)
> >
> > Before anything makes it into the JDK I'd like to see the plan for
> > this, especially since I do not believe such a feature should be
> > released unless it has been applied to the entirety of the JDK.
> > Without this the adoption will be almost as slow as JPMS (an aside on
> > that I'd like progressive enforcement there so it could be possible to
> > get there).
> >
> > Not to speak for anyone other than myself, the community seems to be
> > leaning towards the conversion where non null is the default, and
> > using marker annotations on packages,classes,modules. This or
> > something like this to speed conversion would be appreciated. maybe
> > the following (Evil tangent: let this only exist on module, I'd like
> > to get modules actually moving, in a different email it'd be nice if
> > jars without at least an automatic module would start failing to load)
> >
> > module org.example! {} // or ?
> > package org.example.something!; // or ?
> >
> > could be used for speedy defaults on otherwise unmarked code. Some
> > have taken to separating API and Fields though.
> >
> > How do these behave? given the following interface, static
> > implementations (meaning they aren't doing real loads from an external
> > database), that Stream::map arguments are marked "?" as nullable and
> > use
> >
> > interface MyRepository {
> > Stream<Foo?>! findFoos();
> > }
> >
> > class Foo {}
> >
> > given
> >
> > class MyRepositoryValueNeedsNullCheck implements MyRepository {
> > Stream<Foo?>! findFoos() {
> > return Stream.of(new Foo(), null);
> > }
> > }
> >
> > class MyRepositoryValueDoesNotNeedNullCheck implements MyRepository {
> > Stream<Foo?>! findFoos() {
> > return Stream.of(new Foo());
> > }
> > }
> >
> > when MyRepositoryValueNeedsNullCheck
> > findFoos().filter(Objects::nonNull).map( foo -> foo.toString())
> >
> > when MyRepositoryValueDoesNotNeedNullCheck
> > findFoos().map( foo -> foo.toString())
> >
> > will the above be considered "ok" since neither of them would actually
> > create a runtime error? they should be considered ok in my opinion.
> >
> > class MyRepositoryValueNeedsNullCheck implements MyRepository {
> > Stream<Foo?>! findFoos() {
> > return /// do something with a database or something that
> > cannot be known until runtime
> > }
> > }
> > when MyRepositoryValueNeedsNullCheck
> > findFoos().filter(Objects::nonNull).map( foo -> foo.toString())
> > findFoos().map( foo -> foo.toString())
> >
> > does the return on findFoos() do an implicit runtime check for the
> > Stream throwing some good NPE error? will the map without the filter
> > result in a compile time NPE?
> >
> > class MyRepositoryValueNeedsNullCheck implements MyRepository {
> > Stream<Foo!>? findFoos() {
> > return null;
> > }
> > }
> >
> > is this valid? I have a valid use case for what's more or less the
> > inverse (where the interface is nullable, but the implementation is
> > not)
> >
> > Will we be getting a way to assert variables with inferred types?
> >
> > `var! foo = null` (tangent: can we reopen mutability on var here?
> > meaning val! foo or const! foo, that thing I foolishly voted
> > against... and was wrong, it should exist (I hadn't used a language
> > that had it yet, maybe I wasn't the only one), I don't like const
> > because I see that as a static final)
> >
> > given
> >
> > Foo! foo;
> > foo = new Foo();
> >
> > valid so long as it's assigned before use?
> >
> > is partial markup really valid at compile time?
> >
> > interface MyRepository {
> > Stream<Foo?> findFoos();
> > }
> >
> > I find the examples using this, but then Stream is nullable? it feels
> > like if you define any nullability on a given type then the whole type
> > should be fully marked up.
> >
> > In all of these stream examples, the concept in checker framework is
> > @PolyNull, will there be a way of writing functional interfaces that
> > defines that the implementers can use them in a PolyNull fashion?
> > meaning the null check necessity can't be known until usage is
> > defined?
> >
> > Will the compiler strip if null checks out of the bytecode if it
> > determines they are no longer necessary? probably not necessary to
> > define in the jep.
> >
> >
>
>
> --
> Caleb Cushing
>
> Appointments https://calendly.com/caleb-cushing
> https://xenoterracide.com
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://mail.openjdk.org/pipermail/valhalla-dev/attachments/20241118/47503939/attachment-0001.htm>
More information about the valhalla-dev
mailing list