Packages rooted or not

This is not new news, but nested package syntax interacts with “packages from the class path”.

Concretely, this example compiles, but not if the package clause is scala.p (or if scala is deleted).

package scala
package p

import jdk.OptionConverters._
import java.util.Optional

class Q {
  def f = Optional.ofNullable("hello, world").toScala

That is because jdk is now a top-level package in the JDK.

The expectation is that jdk means scala.jdk always, because scala is a “root import”.

I proposed a fix a few years ago; I remember I justified my expectation, but it went unmerged.

There was a topic on the users forum about package clauses, and I just saw again Paul’s old commit.

To quote the paulpism:

Confusing, now-it-happens now-it-doesn't mysteries lurk in the darkness.

Now I’m wondering if another hyphen is required, or maybe a comma.

His example:

Then paths relative to scala can easily be broken via the unlucky
presence of an empty (or nonempty) directory. Example:

  // a.scala
  class Bar { new util.Random }

  % scalac ./a.scala
  % mkdir util
  % scalac ./a.scala
  ./a.scala:4: error: type Random is not a member of package util
    new util.Random
  one error found

I remember my unmerged fix corrected lookup in “root” imports.

Because I like -Yimports at least in theory, it seems to me more likely that user expectations about “lookups in root imports” will be disappointed.

A reference q.Q to foo.q.Q with -Yimports:java.lang,scala,scala.Predef,foo is unresolved if there is a directory q on the class path (e.g., locally ./q).

Possibly, the justification was that root imports are logically like package clauses in the current compilation unit, and anything on the class path is not from the current compilation unit.