This page is no longer maintained — Please continue to the home page at www.scala-lang.org

Nonnullability

2 replies
Naftoli Gugenheim
Joined: 2008-12-17,
User offline. Last seen 42 years 45 weeks ago.
I am trying to understand the position of defining nonnullability as a property of a type rather that of a val/var/def.
For instance, I am writing a (so far very simple) app in Lift. There are tons of warnings everywhere an external method is called that returns a type that doesn't extend NotNull. I have an entity, called Nature. I made it extend NotNull. Now everywhere that had a valid possibility of a null Nature has to be changed to store an Option. Not the end of the world, although whether to use None or null to indicate emptiness should be the decision of the storage site, not the class -- why should such a decision be all or nothing? If the language would not have a concept of null it would be one thing. Okay. Now I want my helper lookup to return Seq[Nature] with NotNull. Now if nullability were a property of the site, you could check if the API lookup returns null and return Nil etc. instead. But being that Seq (or any type in a parallel situation) wasn't defined by me and the return value isn't instantiated by me, (and even if it was it wouldn't help for a final type) I can't ensure to return a subtype of NotNull. You can't just cast to NotNull. So for Seq you can use a SeqProxy as a hacky workaround.
Another use case is nonnullable Strings (that have to be java.lang.Strings for one reason or another, e.g. AppEngine JPA entities). (Anyway, for e.g. RichString to extend NotNull again imposes an arbitrary restriction across the board.)
But what's the logic? If there was a general mechanism to Not any type (specify that a value must not extend it) and that mechanism allowed one to Not(Null), I would understand. But the primary purpose is to provide null safety, which means a "recursive" guarantee of non-null-ness at a given point in code. So that seems to logically be a property of the code site. In other words, given a type T that extends AnyRef, since Null _is_ a subtype of every AnyRef, and a dangerous one, we want to know where we can guarantee that it doesn't actually get returned. So for example, there should be a way (i.e. an annotation or proof) for e.g. a method to tell the compiler that it guarantees not to return null, and every time a property of the method's return value is referenced the compiler no longer has to consider the possibility of null. Perhaps optional proof of null-less-ness would generate an annotation that could be written by hand instead. This would allow for gradual development of this feature (which can exist side-by-side with NotNull)--at first do not warn if a value is of a type that extends NotNull OR if it is annotated with @nonnull etc. Then, over time the compiler could generate the @nonull etc. annotation automatically based on various proofs. In fact, NotNull could be one kind of proof.
I wonder what will be different in 2.8 about NotNull, but I can't see the logic of specifying across the board what to do with a type, as long as the language doesn't prohibit null.
P.S. In any case, it would be nice if the concept of NotNull -- a filter in a complex type definition -- would be generalized to allow e.g. Seq with Not(mutable.Seq) or Person with Not(Employee). I know that this idea was brought up before, as well as ORing types.

Thanks, and waiting to hear what others have to say,
NG
Ricky Clarkson
Joined: 2008-12-19,
User offline. Last seen 3 years 2 weeks ago.
Re: Nonnullability

The reason is that we only want to do it once per type, not on every
single declaration. If it bothers you, write a Nullable[T] that
behaves like Option[T], but defines n=null to be like n=None, and
gives toString appropriately. Don't try to get equals/hashCode
semantics right transparently, you won't.

2009/6/3 Naftoli Gugenheim :
> I am trying to understand the position of defining nonnullability as a
> property of a type rather that of a val/var/def.
> For instance, I am writing a (so far very simple) app in Lift. There are
> tons of warnings everywhere an external method is called that returns a type
> that doesn't extend NotNull. I have an entity, called Nature. I made it
> extend NotNull. Now everywhere that had a valid possibility of a null Nature
> has to be changed to store an Option. Not the end of the world, although
> whether to use None or null to indicate emptiness should be the decision of
> the storage site, not the class -- why should such a decision be all or
> nothing? If the language would not have a concept of null it would be one
> thing. Okay. Now I want my helper lookup to return Seq[Nature] with NotNull.
> Now if nullability were a property of the site, you could check if the API
> lookup returns null and return Nil etc. instead. But being that Seq (or any
> type in a parallel situation) wasn't defined by me and the return value
> isn't instantiated by me, (and even if it was it wouldn't help for a final
> type) I can't ensure to return a subtype of NotNull. You can't just cast to
> NotNull. So for Seq you can use a SeqProxy as a hacky workaround.
> Another use case is nonnullable Strings (that have to be java.lang.Strings
> for one reason or another, e.g. AppEngine JPA entities). (Anyway, for e.g.
> RichString to extend NotNull again imposes an arbitrary restriction across
> the board.)
> But what's the logic? If there was a general mechanism to Not any type
> (specify that a value must not extend it) and that mechanism allowed one to
> Not(Null), I would understand. But the primary purpose is to provide null
> safety, which means a "recursive" guarantee of non-null-ness at a given
> point in code. So that seems to logically be a property of the code site. In
> other words, given a type T that extends AnyRef, since Null _is_ a subtype
> of every AnyRef, and a dangerous one, we want to know where we can guarantee
> that it doesn't actually get returned. So for example, there should be a way
> (i.e. an annotation or proof) for e.g. a method to tell the compiler that it
> guarantees not to return null, and every time a property of the method's
> return value is referenced the compiler no longer has to consider the
> possibility of null. Perhaps optional proof of null-less-ness would generate
> an annotation that could be written by hand instead. This would allow for
> gradual development of this feature (which can exist side-by-side with
> NotNull)--at first do not warn if a value is of a type that extends NotNull
> OR if it is annotated with @nonnull etc. Then, over time the compiler could
> generate the @nonull etc. annotation automatically based on various proofs.
> In fact, NotNull could be one kind of proof.
> I wonder what will be different in 2.8 about NotNull, but I can't see the
> logic of specifying across the board what to do with a type, as long as the
> language doesn't prohibit null.
> P.S. In any case, it would be nice if the concept of NotNull -- a filter in
> a complex type definition -- would be generalized to allow e.g. Seq with
> Not(mutable.Seq) or Person with Not(Employee). I know that this idea was
> brought up before, as well as ORing types.
>
> Thanks, and waiting to hear what others have to say,
> NG
>

odersky
Joined: 2008-07-29,
User offline. Last seen 45 weeks 6 days ago.
Re: Nonnullability

On Thu, Jun 4, 2009 at 12:55 AM, Naftoli Gugenheim wrote:
> I am trying to understand the position of defining nonnullability as a
> property of a type rather that of a val/var/def.
> For instance, I am writing a (so far very simple) app in Lift. There are
> tons of warnings everywhere an external method is called that returns a type
> that doesn't extend NotNull. I have an entity, called Nature. I made it
> extend NotNull. Now everywhere that had a valid possibility of a null Nature
> has to be changed to store an Option. Not the end of the world, although
> whether to use None or null to indicate emptiness should be the decision of
> the storage site, not the class -- why should such a decision be all or
> nothing? If the language would not have a concept of null it would be one
> thing. Okay. Now I want my helper lookup to return Seq[Nature] with NotNull.
> Now if nullability were a property of the site, you could check if the API
> lookup returns null and return Nil etc. instead. But being that Seq (or any
> type in a parallel situation) wasn't defined by me and the return value
> isn't instantiated by me, (and even if it was it wouldn't help for a final
> type) I can't ensure to return a subtype of NotNull. You can't just cast to
> NotNull. So for Seq you can use a SeqProxy as a hacky workaround.
> Another use case is nonnullable Strings (that have to be java.lang.Strings
> for one reason or another, e.g. AppEngine JPA entities). (Anyway, for e.g.
> RichString to extend NotNull again imposes an arbitrary restriction across
> the board.)
> But what's the logic? If there was a general mechanism to Not any type
> (specify that a value must not extend it) and that mechanism allowed one to
> Not(Null), I would understand. But the primary purpose is to provide null
> safety, which means a "recursive" guarantee of non-null-ness at a given
> point in code. So that seems to logically be a property of the code site. In
> other words, given a type T that extends AnyRef, since Null _is_ a subtype
> of every AnyRef, and a dangerous one, we want to know where we can guarantee
> that it doesn't actually get returned. So for example, there should be a way
> (i.e. an annotation or proof) for e.g. a method to tell the compiler that it
> guarantees not to return null, and every time a property of the method's
> return value is referenced the compiler no longer has to consider the
> possibility of null. Perhaps optional proof of null-less-ness would generate
> an annotation that could be written by hand instead. This would allow for
> gradual development of this feature (which can exist side-by-side with
> NotNull)--at first do not warn if a value is of a type that extends NotNull
> OR if it is annotated with @nonnull etc. Then, over time the compiler could
> generate the @nonull etc. annotation automatically based on various proofs.
> In fact, NotNull could be one kind of proof.
> I wonder what will be different in 2.8 about NotNull, but I can't see the
> logic of specifying across the board what to do with a type, as long as the
> language doesn't prohibit null.
> P.S. In any case, it would be nice if the concept of NotNull -- a filter in
> a complex type definition -- would be generalized to allow e.g. Seq with
> Not(mutable.Seq) or Person with Not(Employee). I know that this idea was
> brought up before, as well as ORing types.
>
NotNull is really work in progress, or I should rather say work in
suspension. As you noted, it needs much more refined analyses to avoid
having errors in lots of cases which are clearly
safe. So I cannot recommend to use NotNull right now. The planis to
come back to that eventually, but there are some other things on my
plate before that will happen.

Cheers

Copyright © 2012 École Polytechnique Fédérale de Lausanne (EPFL), Lausanne, Switzerland