Skip to content

Tuple.toList.toArray raise java.lang.ClassCastException #14964

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
esse-byte opened this issue Apr 18, 2022 · 4 comments · Fixed by #14971
Closed

Tuple.toList.toArray raise java.lang.ClassCastException #14964

esse-byte opened this issue Apr 18, 2022 · 4 comments · Fixed by #14971
Assignees
Milestone

Comments

@esse-byte
Copy link

esse-byte commented Apr 18, 2022

Compiler version

Scala 3.1.0, Scala 3.1.1, Scala 3.1.2 RC1, Scala 3.1.2

Minimized code

val xs = (1, 2).toList
val a1 = xs.toArray              // fine
println((1, 2).toList.toArray)  // this works without exception, but the result is wrong: get a [Ljava.lang.Object rather than [I@
val a2 = (1, 2).toList.toArray // java.lang.ClassCastException

Output

java.lang.ClassCastException: class [Ljava.lang.Object; cannot be cast to class [I ([Ljava.lang.Object; and [I are in module java.base of loader 'bootstrap')
  ... 65 elided
java.lang.NoClassDefFoundError: Could not initialize class rs$line$1$
  at rs$line$1.a1(rs$line$1)
  at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
  at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
  at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
  at java.base/java.lang.reflect.Method.invoke(Method.java:566)
  at dotty.tools.repl.Rendering.$anonfun$4(Rendering.scala:110)
  at scala.Option.map(Option.scala:242)
  at dotty.tools.repl.Rendering.valueOf(Rendering.scala:110)
  at dotty.tools.repl.Rendering.renderVal(Rendering.scala:139)
  at dotty.tools.repl.ReplDriver.$anonfun$10(ReplDriver.scala:335)
  at scala.collection.immutable.List.flatMap(List.scala:293)
  at scala.collection.immutable.List.flatMap(List.scala:79)
  at dotty.tools.repl.ReplDriver.extractAndFormatMembers$1(ReplDriver.scala:335)
  at dotty.tools.repl.ReplDriver.renderDefinitions$$anonfun$2(ReplDriver.scala:358)
  at scala.Option.map(Option.scala:242)
  at dotty.tools.repl.ReplDriver.renderDefinitions(ReplDriver.scala:361)
  at dotty.tools.repl.ReplDriver.compile$$anonfun$2(ReplDriver.scala:280)
  at scala.util.Either.fold(Either.scala:189)
  at dotty.tools.repl.ReplDriver.compile(ReplDriver.scala:296)
  at dotty.tools.repl.ReplDriver.interpret(ReplDriver.scala:230)
  at dotty.tools.repl.ReplDriver.loop$1(ReplDriver.scala:162)
  at dotty.tools.repl.ReplDriver.runUntilQuit$$anonfun$1(ReplDriver.scala:165)
  at dotty.tools.repl.ReplDriver.withRedirectedOutput(ReplDriver.scala:186)
  at dotty.tools.repl.ReplDriver.runBody$$anonfun$1(ReplDriver.scala:174)
  at dotty.tools.runner.ScalaClassLoader$.asContext(ScalaClassLoader.scala:80)
  at dotty.tools.repl.ReplDriver.runBody(ReplDriver.scala:174)
  at dotty.tools.repl.ReplDriver.runUntilQuit(ReplDriver.scala:165)
  at xsbt.ConsoleInterface.run(ConsoleInterface.java:52)
  at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
  at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
  at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
  at java.base/java.lang.reflect.Method.invoke(Method.java:566)
  at sbt.internal.inc.AnalyzingCompiler.invoke(AnalyzingCompiler.scala:329)
  at sbt.internal.inc.AnalyzingCompiler.console(AnalyzingCompiler.scala:233)
  at sbt.Console.console0$1(Console.scala:64)
  at sbt.Console.$anonfun$apply$5(Console.scala:74)
  at sbt.Run$.executeSuccess(Run.scala:186)
  at sbt.Console.$anonfun$apply$4(Console.scala:74)
  at sbt.internal.util.Terminal.withRawInput(Terminal.scala:145)
  at sbt.internal.util.Terminal.withRawInput$(Terminal.scala:143)
  at sbt.internal.util.Terminal$ProxyTerminal$.withRawInput(Terminal.scala:384)
  at sbt.Console.$anonfun$apply$3(Console.scala:74)
  at sbt.internal.util.Terminal$TerminalImpl.withRawOutput(Terminal.scala:975)
  at sbt.internal.util.Terminal$ProxyTerminal$.withRawOutput(Terminal.scala:423)
  at sbt.Console.apply(Console.scala:71)
  at sbt.Console.apply(Console.scala:49)
  at sbt.Console.apply(Console.scala:41)
  at sbt.Defaults$.$anonfun$consoleTask$1(Defaults.scala:2232)
  at sbt.Defaults$.$anonfun$consoleTask$1$adapted(Defaults.scala:2218)
  at scala.Function1.$anonfun$compose$1(Function1.scala:49)
  at sbt.internal.util.$tilde$greater.$anonfun$$u2219$1(TypeFunctions.scala:62)
  at sbt.std.Transform$$anon$4.work(Transform.scala:68)
  at sbt.Execute.$anonfun$submit$2(Execute.scala:282)
  at sbt.internal.util.ErrorHandling$.wideConvert(ErrorHandling.scala:23)
  at sbt.Execute.work(Execute.scala:291)
  at sbt.Execute.$anonfun$submit$1(Execute.scala:282)
  at sbt.ConcurrentRestrictions$$anon$4.$anonfun$submitValid$1(ConcurrentRestrictions.scala:265)
  at sbt.CompletionService$$anon$2.call(CompletionService.scala:64)
  at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264)
  at java.base/java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:515)
  at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264)
  at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128)
  at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628)
  at java.base/java.lang.Thread.run(Thread.java:829)
java.lang.NoClassDefFoundError: Could not initialize class rs$line$1$
  at rs$line$1.a2(rs$line$1)
  at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
  at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
  at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
  at java.base/java.lang.reflect.Method.invoke(Method.java:566)
  at dotty.tools.repl.Rendering.$anonfun$4(Rendering.scala:110)
  at scala.Option.map(Option.scala:242)
  at dotty.tools.repl.Rendering.valueOf(Rendering.scala:110)
  at dotty.tools.repl.Rendering.renderVal(Rendering.scala:139)
  at dotty.tools.repl.ReplDriver.$anonfun$10(ReplDriver.scala:335)
  at scala.collection.immutable.List.flatMap(List.scala:293)
  at scala.collection.immutable.List.flatMap(List.scala:79)
  at dotty.tools.repl.ReplDriver.extractAndFormatMembers$1(ReplDriver.scala:335)
  at dotty.tools.repl.ReplDriver.renderDefinitions$$anonfun$2(ReplDriver.scala:358)
  at scala.Option.map(Option.scala:242)
  at dotty.tools.repl.ReplDriver.renderDefinitions(ReplDriver.scala:361)
  at dotty.tools.repl.ReplDriver.compile$$anonfun$2(ReplDriver.scala:280)
  at scala.util.Either.fold(Either.scala:189)
  at dotty.tools.repl.ReplDriver.compile(ReplDriver.scala:296)
  at dotty.tools.repl.ReplDriver.interpret(ReplDriver.scala:230)
  at dotty.tools.repl.ReplDriver.loop$1(ReplDriver.scala:162)
  at dotty.tools.repl.ReplDriver.runUntilQuit$$anonfun$1(ReplDriver.scala:165)
  at dotty.tools.repl.ReplDriver.withRedirectedOutput(ReplDriver.scala:186)
  at dotty.tools.repl.ReplDriver.runBody$$anonfun$1(ReplDriver.scala:174)
  at dotty.tools.runner.ScalaClassLoader$.asContext(ScalaClassLoader.scala:80)
  at dotty.tools.repl.ReplDriver.runBody(ReplDriver.scala:174)
  at dotty.tools.repl.ReplDriver.runUntilQuit(ReplDriver.scala:165)
  at xsbt.ConsoleInterface.run(ConsoleInterface.java:52)
  at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
  at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
  at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
  at java.base/java.lang.reflect.Method.invoke(Method.java:566)
  at sbt.internal.inc.AnalyzingCompiler.invoke(AnalyzingCompiler.scala:329)
  at sbt.internal.inc.AnalyzingCompiler.console(AnalyzingCompiler.scala:233)
  at sbt.Console.console0$1(Console.scala:64)
  at sbt.Console.$anonfun$apply$5(Console.scala:74)
  at sbt.Run$.executeSuccess(Run.scala:186)
  at sbt.Console.$anonfun$apply$4(Console.scala:74)
  at sbt.internal.util.Terminal.withRawInput(Terminal.scala:145)
  at sbt.internal.util.Terminal.withRawInput$(Terminal.scala:143)
  at sbt.internal.util.Terminal$ProxyTerminal$.withRawInput(Terminal.scala:384)
  at sbt.Console.$anonfun$apply$3(Console.scala:74)
  at sbt.internal.util.Terminal$TerminalImpl.withRawOutput(Terminal.scala:975)
  at sbt.internal.util.Terminal$ProxyTerminal$.withRawOutput(Terminal.scala:423)
  at sbt.Console.apply(Console.scala:71)
  at sbt.Console.apply(Console.scala:49)
  at sbt.Console.apply(Console.scala:41)
  at sbt.Defaults$.$anonfun$consoleTask$1(Defaults.scala:2232)
  at sbt.Defaults$.$anonfun$consoleTask$1$adapted(Defaults.scala:2218)
  at scala.Function1.$anonfun$compose$1(Function1.scala:49)
  at sbt.internal.util.$tilde$greater.$anonfun$$u2219$1(TypeFunctions.scala:62)
  at sbt.std.Transform$$anon$4.work(Transform.scala:68)
  at sbt.Execute.$anonfun$submit$2(Execute.scala:282)
  at sbt.internal.util.ErrorHandling$.wideConvert(ErrorHandling.scala:23)
  at sbt.Execute.work(Execute.scala:291)
  at sbt.Execute.$anonfun$submit$1(Execute.scala:282)
  at sbt.ConcurrentRestrictions$$anon$4.$anonfun$submitValid$1(ConcurrentRestrictions.scala:265)
  at sbt.CompletionService$$anon$2.call(CompletionService.scala:64)
  at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264)
  at java.base/java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:515)
  at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264)
  at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128)
  at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628)
  at java.base/java.lang.Thread.run(Thread.java:829)

Expectation

Both works

@esse-byte esse-byte added itype:bug stat:needs triage Every issue needs to have an "area" and "itype" label labels Apr 18, 2022
@romanowski romanowski added area:backend and removed stat:needs triage Every issue needs to have an "area" and "itype" label labels Apr 19, 2022
@nicolasstucki
Copy link
Contributor

The source of the problem seems to be in typer while inferring the ClassTag argument.

Tuple2.apply[Int, Int](1, 2).toList.toArray[(Int | (Int | Nothing))](
            scala.reflect.ClassTag.apply[(Int | (Int | Nothing))](
              classOf[Object]
            )
          )

@nicolasstucki
Copy link
Contributor

We get Int | (Int | Nothing) from Tuple.Union[(Int, Int)]

@nicolasstucki
Copy link
Contributor

It seems we are not summoning the correct ClassTag when we have an | type with a Nothing

  println(summon[reflect.ClassTag[Int]]) // classOf[Int]
  println(summon[reflect.ClassTag[Int | Int]]) // classOf[Int]
  println(summon[reflect.ClassTag[Int | 1]]) // classOf[Int]
  println(summon[reflect.ClassTag[Int | Nothing]]) // classOf[Object]

@nicolasstucki
Copy link
Contributor

nicolasstucki commented Apr 19, 2022

At line https://github.com/lampepfl/dotty/blob/main/compiler/src/dotty/tools/dotc/typer/Synthesizer.scala#L42,
erasure returns the type Object for Int | Nothing.

Should the erasure of Int | Nothing be Int? If so this would fix our issue. See #14970

@nicolasstucki nicolasstucki self-assigned this Apr 19, 2022
nicolasstucki added a commit to dotty-staging/dotty that referenced this issue Apr 19, 2022
Aligns `| Nothing` with `& Any` and `Nothing |` with `Any &` for value types.

This also fixes `summon[ClassTag[Int | Nothing]]` as it is now equivalent to `summon[ClassTag[Int]]`.

Fixes scala#14970
Fixes scala#14964

> ⚠️ This is a binary breaking change.
> Previous version generated the `def f: Int` and `def f: Object` variants of the method.
> In the new one, we only generate the the `def f: Int` version.
> Unfortunatelly, the previous version called the boxed version of the interface which does not exist anymore.
>
> Is this something that we enounter in practice?
nicolasstucki added a commit to dotty-staging/dotty that referenced this issue Apr 19, 2022
…e types.

This also fixes `summon[ClassTag[Int | Nothing]]` as it is now equivalent to `summon[ClassTag[Int]]`.

Fixes scala#14970
Fixes scala#14964

> ⚠️ This is a binary breaking change.

> the Previous version generated the `def f: Int` and `def f: Object` variants of the method.
> In the new one, we only generate the `def f: Int` version.
> Unfortunately, the previous version called the boxed version of the interface that does not exist anymore.
>
> Is this something that we encounter in practice?
nicolasstucki added a commit to dotty-staging/dotty that referenced this issue Apr 19, 2022
…e types.

This also fixes `summon[ClassTag[Int | Nothing]]` as it is now equivalent to `summon[ClassTag[Int]]`.

Fixes scala#14970
Fixes scala#14964

> ⚠️ This is a binary breaking change.

> the Previous version generated the `def f: Int` and `def f: Object` variants of the method.
> In the new one, we only generate the `def f: Int` version.
> Unfortunately, the previous version called the boxed version of the interface that does not exist anymore.
>
> Is this something that we encounter in practice?
nicolasstucki added a commit to dotty-staging/dotty that referenced this issue Apr 19, 2022
…e types.

This also fixes `summon[ClassTag[Int | Nothing]]` as it is now equivalent to `summon[ClassTag[Int]]`.

Fixes scala#14970
Fixes scala#14964

> ⚠️ This is a binary breaking change.

> the Previous version generated the `def f: Int` and `def f: Object` variants of the method.
> In the new one, we only generate the `def f: Int` version.
> Unfortunately, the previous version called the boxed version of the interface that does not exist anymore.
>
> Is this something that we encounter in practice?
nicolasstucki added a commit to dotty-staging/dotty that referenced this issue Apr 21, 2022
…e types.

This also fixes `summon[ClassTag[Int | Nothing]]` as it is now equivalent to `summon[ClassTag[Int]]`.

Fixes scala#14970
Fixes scala#14964

> ⚠️ This is a binary breaking change.

> the Previous version generated the `def f: Int` and `def f: Object` variants of the method.
> In the new one, we only generate the `def f: Int` version.
> Unfortunately, the previous version called the boxed version of the interface that does not exist anymore.
>
> Is this something that we encounter in practice?
nicolasstucki added a commit to dotty-staging/dotty that referenced this issue Apr 22, 2022
This make the erasure different for value types as they now correctly
erase to the primitive types instead of `Object`.

Aligns | Nothing with & Any and Nothing | with Any & for value types.

This also fixes `summon[ClassTag[Int | Nothing]]` as it is now equivalent to `summon[ClassTag[Int]]`.

Fixes scala#14970
Fixes scala#14964

> ⚠️ This is a binary breaking change.

> the Previous version generated the `def f: Int` and `def f: Object` variants of the method.
> In the new one, we only generate the `def f: Int` version.
> Unfortunately, the previous version called the boxed version of the interface that does not exist anymore.
>
> Is this something that we encounter in practice?
nicolasstucki added a commit to dotty-staging/dotty that referenced this issue Apr 22, 2022
This make the erasure different for value types as they now correctly
erase to the primitive types instead of `Object`.

Aligns | Nothing with & Any and Nothing | with Any & for value types.

This also fixes `summon[ClassTag[Int | Nothing]]` as it is now equivalent to `summon[ClassTag[Int]]`.

Fixes scala#14970
Fixes scala#14964

> ⚠️ This is a binary breaking change.

> the Previous version generated the `def f: Int` and `def f: Object` variants of the method.
> In the new one, we only generate the `def f: Int` version.
> Unfortunately, the previous version called the boxed version of the interface that does not exist anymore.
>
> Is this something that we encounter in practice?
bishabosha pushed a commit to dotty-staging/dotty that referenced this issue Oct 18, 2022
This make the erasure different for value types as they now correctly
erase to the primitive types instead of `Object`.

Aligns | Nothing with & Any and Nothing | with Any & for value types.

This also fixes `summon[ClassTag[Int | Nothing]]` as it is now equivalent to `summon[ClassTag[Int]]`.

Fixes scala#14970
Fixes scala#14964

> ⚠️ This is a binary breaking change.

> the Previous version generated the `def f: Int` and `def f: Object` variants of the method.
> In the new one, we only generate the `def f: Int` version.
> Unfortunately, the previous version called the boxed version of the interface that does not exist anymore.
>
> Is this something that we encounter in practice?
@Kordyjan Kordyjan added this to the 3.2.0 milestone Aug 1, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants