Explicitly null check the stdlib#23566
Conversation
|
@noti0na1 As agreed to, please push the changes to explicitly null check the stdlib here. |
2fe2627 to
2d178a7
Compare
cc174ce to
99df51b
Compare
|
@hamzaremmal Do you know how the stdlib is compiled at the first step? When I do |
When we compute `afterPatternContext`, the wrong `ctx` is passed to the
function.
```scala
def f(s: AnyRef | Null) = s match
case null => 0
case s: String => s.length
case _ =>
val a: AnyRef = s
a.toString.length
```
Will be useful for #23566
| * @return A Scala `Iterator` view of the argument. | ||
| */ | ||
| def asScala[A](i: ju.Iterator[A]): Iterator[A] = i match { | ||
| def asScala[A](i: ju.Iterator[A] | Null): Iterator[A] | Null = i match { |
There was a problem hiding this comment.
I wonder if we could do some kind of trick like mapNull, with match types, to give asScala a null-polymorphic signature, so that it returns a non-null when you pass it a non-null. That would reduce the need for many .nns not only within the library itself, but probably also in code that uses the library.
There was a problem hiding this comment.
I would like to add a match type as shown in @sjrd 's comment. But this means the new type would show up at the type signature, and adding a new public definition to stdlib is impossible at this point...
There was a problem hiding this comment.
Maybe I should just forbid null like the wrappers wrapRefArray
There was a problem hiding this comment.
Forbidding nulls would break the current contract. That's a big no-no.
I also agree that we shouldn't introduce the match type I suggested at this time. We can reconsider in a future release, as we get closer to general adoption of explicit nulls.
There was a problem hiding this comment.
I would argue for non-explicit-nulls users, forbidding nulls will not change any contract. It is just a more strict type for explicit-nulls.
There was a problem hiding this comment.
It would make the body inconsistent with its typing. Constant-folding in the compiler could for example mis-"optimize" x == null as false because the type of x is not nullable. So even non-explicit-nulls users could get affected, indirectly.
In general I don't think the types under explicit-nulls should be any more restrictive than the existing (sometimes tacit 🤷♂️) contract. Typing should better describe the contract; not make the contract stricter.
There was a problem hiding this comment.
I think we have to make a decision here. Of course we will ensure the behaviour of the body will not change, no matter passing null or not. Take asScala as an example:
- Keep the original type:
def asScala[A](i: ju.Iterator[A]): Iterator[A]. No effect for non-explicit-nulls in terms of typing. Not able to passnullin explicit nulls, more convenient to have a chain of collection operations. - Change the type to:
def asScala[A](i: ju.Iterator[A] | Null): Iterator[A] | Null. Still no effect for non-explicit-nulls. More precise to the original behaviour and document. Have to add.nnat more places in explicit-nulls.
There was a problem hiding this comment.
After experimenting with the wrapper, I personally think 1 is batter choice for the library.
There was a problem hiding this comment.
Since we disagree, I added this question as an agenda item for tomorrow's core meeting.
216877c to
2a854a1
Compare
5b251c0 to
747eb65
Compare
|
Why does the MiMa check a java class? |
|
Why should it not? Java classes are also part of the ABI of our artifacts. Even tasty-mima checks Java classes! |
Oh, I thought we only check scala code. |
|
I added So I guess at least the stdlib itself is good? |
a22fa25 to
582c5c5
Compare
|
Strange tailrac errors only during [info] compiling 650 Scala sources and 55 Java sources to /Users/Work/dotty/library-js/target/scala-library/classes ...
[error] -- Error: /Users/Work/dotty/library/src/scala/collection/concurrent/TrieMap.scala:60:26
[error] 60 | else GCAS_Complete(/*READ*/mainnode, ct)
[error] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
[error] | Cannot rewrite recursive call: it is not in tail position
[error] -- Error: /Users/Work/dotty/library/src/scala/collection/concurrent/TrieMap.scala:73:28
[error] 73 | else GCAS_Complete(m, ct)
[error] | ^^^^^^^^^^^^^^^^^^^^
[error] | Cannot rewrite recursive call: it is not in tail position
[error] -- Error: /Users/Work/dotty/library/src/scala/collection/concurrent/TrieMap.scala:77:23
[error] 77 | GCAS_Complete(/*READ*/mainnode, ct)
[error] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
[error] | Cannot rewrite recursive call: it is not in tail position
[error] -- Error: /Users/Work/dotty/library/src/scala/collection/concurrent/TrieMap.scala:179:53
[error] 179 | if (startgen eq in.gen) in.rec_insertif(k, v, hc, cond, fullEquals, lev + 5, this, startgen, ct)
[error] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
[error] | Cannot rewrite recursive call: it is not in tail position
[error] -- Error: /Users/Work/dotty/library/src/scala/collection/concurrent/TrieMap.scala:181:72
[error] 181 | if (GCAS(cn, cn.renewed(startgen, ct), ct)) rec_insertif(k, v, hc, cond, fullEquals, lev, parent, startgen, ct)
[error] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
[error] | Cannot rewrite recursive call: it is not in tail position
[error] -- Error: /Users/Work/dotty/library/src/scala/runtime/MethodCache.scala:73:33
[error] 73 | case x: PolyMethodCache => x findInternal forReceiver
[error] | ^^^^^^^^^^^^^^^^^^^^^^^^^^
[error] | Cannot rewrite recursive call: it is not in tail positionThe same files was fine when only compiling the stdlib. |
It seems there are extra |
aef13b9 to
553881d
Compare
|
As the explicit-null checks for the Scala 3 standard library progress, I’d like to invite everyone to help and perform a deep review of the changes. Please look beyond the diff: review surrounding code and any interactions that could be impacted. Guidelines I followed during the migration:
How you can help:
Thanks in advance for your thorough review! |
This reverts commit e478f65.
84a4184 to
e6bd8f4
Compare
|
Hi @sjrd , do you want to "approve" this PR? |
natsukagami
left a comment
There was a problem hiding this comment.
I don't have any more complains, and seems like others are fine with it too :)
|
@noti0na1 should this have been squash-merged instead of merged directly? Right now the @sjrd @hamzaremmal since this seems to keep happening (last happened in #24127), perhaps you guys could turn on |
|
Having squash as default would for sure be very useful when backporting things 🤔 |
The PR enables explicit nulls for stdlib. The detailed review guide is at: #23566 (comment)