scala / scala3

The Scala 3 compiler, also known as Dotty.
https://dotty.epfl.ch
Apache License 2.0
5.81k stars 1.05k forks source link

Spurious errors depending on package name #16012

Open jchyb opened 2 years ago

jchyb commented 2 years ago

Compiler version

3.1.3, 3.2.2-RC1-bin-20220908-c11f5cb-NIGHTLY

Minimized code

Main.scala

//> using scala "3.nightly"
import s.util.tag // letters t and higher work

sealed trait ScalaInput

object InputUnmarshaller {
  def emptyMapVars = tag[ScalaInput](Map.empty[String, Any])
}

@main def main() =
  println(InputUnmarshaller.emptyMapVars)

tag.scala

package s.util // letters t and higher work

object tag {
  def apply[U] = new Tagger[U]

  sealed trait Tagged[U]
  type @@[+T, U] = T with Tagged[U]

  class Tagger[U] {
    def apply[T](t: T): T @@ U = t.asInstanceOf[T @@ U]
  }
}

Output

Exception in thread "main" java.lang.ClassCastException: class scala.collection.immutable.Map$EmptyMap$ cannot be cast to class s.util.tag$Tagged (scala.collection.immutable.Map$EmptyMap$ and s.util.tag$Tagged are in unnamed module of loader 'app')
        at InputUnmarshaller$.emptyMapVars(9283eaf8c80429e61efd1fb62418255a-main/Main.scala:7)
        at Main$package$.main(9283eaf8c80429e61efd1fb62418255a-main/Main.scala:11)
        at main.main(9283eaf8c80429e61efd1fb62418255a-main/Main.scala:10)

Expectation

Program should print Map(). In general I've noticed that package names starting with t and higher work, other don't, although I haven't tested enough to be 100% sure exactly which package names will work.

mbovel commented 2 years ago

Idea from @dwijnand: maybe the order of packages depend on the hash of the package name?

KacperFKorban commented 2 years ago

That is my current theory too. It looks like it crashed whenever the name of the package is lexicographically smaller than scala.

dwijnand commented 2 years ago

@mbovel https://github.com/lampepfl/dotty/issues/14011 is the issue I created. And Names.nameTable is the global variable that can impact the iteration of memberNames.

KacperFKorban commented 1 year ago

This behaviour looks to be intended (by adding antisymmetry to the compareErasedGlb relation): https://github.com/lampepfl/dotty/blob/ad8d3bb24f831fe978269251d87c0c5aaf8b4216/compiler/src/dotty/tools/dotc/core/TypeErasure.scala#L451-L453

I checked which tests would fail if I changed it to always erase to the left value and it ended up being just 3 tests: pos/i5139, neg/i5139, run/manifest-summoning. (Where all of them are expected)

@smarter Do you know if the "A <= B && B <= A iff A =:= B" property on compareErasedGlb is needed anywhere?