Skip to content

Regression in type inference leading to illegal signatures and runtime failures #19324

Closed
@WojciechMazur

Description

@WojciechMazur

Regression found when testing Scala Native runtime with 3.4.0-RC1

Compiler version

3.4.0-RC1
3.3.2-RC1
First bad release: 3.3.2-RC1-bin-20230715-4851278-NIGHTLY
Bisect points to 89735d0

Minimized code

// trait Consumer[T]:
//   def accept(v: T): Unit
// trait Collection[T]:
//   def forEach(action: Consumer[T]): Unit
import java.util.{Collection, Collections}

class Foo[E] {
  def copyElements(c: Collection[_ <: E]): Unit = {
    c.forEach(addLast(_))
  }
  def addLast(e: E): Unit = println(e)
}

// for runtime test only
@main def Test = {
  val x = new Foo[String]()
  x.copyElements(Collections.singletonList("foo"))
}

Output (runtime)

Exception in thread "main" java.lang.ClassCastException: class java.lang.String cannot be cast to class scala.runtime.Nothing$ (java.lang.String is in module java.base of loader 'bootstrap'; scala.runtime.Nothing$ is in unnamed module of loader 'app')
        at java.base/java.util.Collections$SingletonList.forEach(Collections.java:4966)
        at Foo.copyElements(Test.scala:12)
        at Test$package$.Test(Test.scala:19)
        at Test.main(Test.scala:17)

Output (javap)

public class Foo<E> {
  public Foo();
  public void copyElements(java.util.Collection<? extends E>);
  public void addLast(E);
  private final void copyElements$$anonfun$1(scala.runtime.Nothing$); // << illegal
}

Output (-Xprint:typer)

[syntax trees at end of                     typer]] // /Users/wmazur/projects/scala-native/sandbox/src/main/scala/Test.scala
package <empty> {
  import java.util.Collection
  import java.util.Collections
  class Foo[E >: Nothing <: Any]() extends Object() {
    E
    def copyElements(c: java.util.Collection[? >: Nothing <: Foo.this.E]): Unit
       =
      {
        c.forEach(
          {
            def $anonfun(_$1: Nothing): Unit = this.addLast(_$1) // << illegal
            closure($anonfun:java.util.function.Consumer[c.T])
          }
        )
      }
    def addLast(e: Foo.this.E): Unit = println(e)
  }
  ...

Expectation

Should infer to correct type, that is AnyRef/java.lang.Object

public class Foo<E> {
  public Foo();
  public void copyElements(java.util.Collection<? extends E>);
  public void addLast(E);
  private final void copyElements$$anonfun$1(java.lang.Object);
}

Metadata

Metadata

Assignees

Labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions