scala3 icon indicating copy to clipboard operation
scala3 copied to clipboard

Type computed to `any`, works in Scala 2

Open He-Pin opened this issue 3 years ago • 7 comments

Compiler version

3.1.2

Rrror: https://github.com/akka/akka/runs/8294129202?check_suite_focus=true From: https://github.com/akka/akka/pull/31345

Minimized code

Sorry I have not minimized it :(

  def combine[T, U, M](
      sources: java.util.List[_ <: Graph[SourceShape[T], _<: M]],
      fanInGraph: Graph[UniformFanInShape[T, U], NotUsed]): Source[U, java.util.List[M]] = {
    val seq = if (sources != null) Util.immutableSeq(sources).collect {
      case source: Source[T @unchecked, M @unchecked] => source.asScala
      case other                                      => other
    } else immutable.Seq()
    import akka.util.ccompat.JavaConverters._
    new Source(scaladsl.Source.combine(seq)(fanInGraph).mapMaterializedValue(_.asJava))
  }

if I change to :

  def combine[T, U, M](
      sources: java.util.List[_ <: Graph[SourceShape[T], M]],
      fanInGraph: Graph[UniformFanInShape[T, U], NotUsed]): Source[U, java.util.List[M]] = {
    val seq = if (sources != null) Util.immutableSeq(sources).collect {
      case source: Source[T @unchecked, M @unchecked] => source.asScala
      case other                                      => other
    } else immutable.Seq()
    import akka.util.ccompat.JavaConverters._
    new Source(scaladsl.Source.combine(seq)(fanInGraph).mapMaterializedValue(_.asJava))
  }

The only difference is _<:M and M.

Output


[error] -- [E007] Type Mismatch Error: /home/runner/work/akka/akka/akka-stream/src/main/scala/akka/stream/javadsl/Sink.scala:397:76 
[error] 397 |    new Sink(scaladsl.Sink.combine(seq)(fanoutGraph).mapMaterializedValue(_.asJava))
[error]     |                                                                          ^^^^^^^^
[error]     |                                         Found:    java.util.List[Any]
[error]     |                                         Required: java.util.List[M]
[error] -- [E007] Type Mismatch Error: /home/runner/work/akka/akka/akka-stream/src/main/scala/akka/stream/javadsl/Source.scala:682:79 
[error] 682 |    new Source(scaladsl.Source.combine(seq)(fanInGraph).mapMaterializedValue(_.asJava))
[error]     |                                                                             ^^^^^^^^
[error]     |                                         Found:    java.util.List[Any]
[error]     |                                         Required: java.util.List[M]
[error] two errors found

image

Expectation

Compile as Scala 2.

I think that should be computed to java.util.List[M] not java.util.List[Any]

He-Pin avatar Sep 11 '22 18:09 He-Pin

Here is an attempt to minimize:

object Test {
    class Box[T](val value: T)
    def f[T](l: List[Box[_ <: T]]): List[T] = l.map(_.value)
}

I am not sure if this captures every aspect of your problem or if this is over-simplified.

The above snippet compiles with Scala 2.12, 3.1.2 and 3.2.0 but fails with Scala 2.13, 3.1.1 and 3.1.3.

Output
➜  ~/scala-snippets scala-cli compile --server=false --scala-version=2.12 type_param_any.scala 
➜  ~/scala-snippets scala-cli compile --server=false --scala-version=2.13 type_param_any.scala 
/Users/mbovel/scala-snippets/type_param_any.scala:3: error: type mismatch;
 found   : Test.Box[_ <: T] => x$1.value.type forSome { val x$1: Test.Box[_ <: T] }
 required: Test.Box[_ <: T] => (some other)_$1(in value l)
    def f[T](l: List[Box[_ <: T]]): List[T] = l.map(_.value)
                                                      ^
1 error
Compilation failed
➜  ~/scala-snippets scala-cli compile --server=false --scala-version=3.1.1 type_param_any.scala 
-- Error: /Users/mbovel/scala-snippets/type_param_any.scala:3:52 ---------------
3 |    def f[T](l: List[Box[_ <: T]]): List[T] = l.map(_.value)
  |                                                    ^^^^^^^
  |                          return type B of lambda cannot be made hygienic;
  |                          it is not a supertype of the hygienic type Any
-- Error: /Users/mbovel/scala-snippets/type_param_any.scala:3:51 ---------------
3 |    def f[T](l: List[Box[_ <: T]]): List[T] = l.map(_.value)
  |                                                   ^
  |       Inaccessible variables captured in instantation of type variable B.
  |       _$1.T was fixed to Any,
  |       but the latter type does not conform to the upper bound T
-- Error: /Users/mbovel/scala-snippets/type_param_any.scala:3:8 ----------------
3 |    def f[T](l: List[Box[_ <: T]]): List[T] = l.map(_.value)
  |        ^
  |       Inaccessible variables captured in instantation of type variable B.
  |       _$1.T was fixed to Any,
  |       but the latter type does not conform to the upper bound T
-- Error: /Users/mbovel/scala-snippets/type_param_any.scala:1:7 ----------------
1 |object Test {
  |       ^
  |       Inaccessible variables captured in instantation of type variable B.
  |       _$1.T was fixed to Any,
  |       but the latter type does not conform to the upper bound T
-- Error: /Users/mbovel/scala-snippets/type_param_any.scala:1:0 ----------------
1 |object Test {
  |^
  |Inaccessible variables captured in instantation of type variable B.
  |_$1.T was fixed to Any,
  |but the latter type does not conform to the upper bound T
5 errors found
Compilation failed
➜  ~/scala-snippets scala-cli compile --server=false --scala-version=3.1.2 type_param_any.scala 
➜  ~/scala-snippets scala-cli compile --server=false --scala-version=3.1.3 type_param_any.scala 
-- Error: /Users/mbovel/scala-snippets/type_param_any.scala:3:52 ---------------
3 |    def f[T](l: List[Box[_ <: T]]): List[T] = l.map(_.value)
  |                                                    ^^^^^^^
  |                      return type _$1.T of lambda cannot be made hygienic;
  |                      it is not a supertype of the hygienic type Any
1 error found
Compilation failed
➜  ~/scala-snippets scala-cli compile --server=false --scala-version=3.2.0 type_param_any.scala 

I believe this is linked to type avoidance and recent related work from @smarter and @odersky; can you please confirm?

@He-Pin have you tried to compile with Scala 3.2.0? And with 2.13?

mbovel avatar Sep 12 '22 11:09 mbovel

I just updated it, it was 3.1.2 not 3.1.3 .~Akka not compiles with 3.1.3 now.~ image

He-Pin avatar Sep 12 '22 11:09 He-Pin

Hard to tell whether it's avoidance or not. But it works in nightly, right?

odersky avatar Sep 12 '22 15:09 odersky

But it works in nightly, right?

My simplified example compiles with 3.2.0, but I am not sure for the original one.

@He-Pin could please try with 3.2.0 and with the latest nightly?

mbovel avatar Sep 12 '22 15:09 mbovel

@mbovel I am trying to get Akka built at: https://github.com/akka/akka/pull/31578 :) ,that will be the first to come, it currently only compiles with scala 3.1.2,

He-Pin avatar Sep 12 '22 15:09 He-Pin

it's still the same.

[info] compiling 186 Scala sources and 3 Java sources to C:\Users\hepin\IdeaProjects\akka\akka-stream\target\scala-3.2.0\classes ...
[error] -- [E007] Type Mismatch Error: C:\Users\hepin\IdeaProjects\akka\akka-stream\src\main\scala\akka\stream\javadsl\Source.scala:682:79
[error] 682 |    new Source(scaladsl.Source.combine(seq)(fanInGraph).mapMaterializedValue(_.asJava))
[error]     |                                                                             ^^^^^^^^
[error]     |                                         Found:    java.util.List[Any]
[error]     |                                         Required: java.util.List[M]
[error]     |
[error]     | longer explanation available when compiling with `-explain`
[error] one error found
[error] (Compile / compileIncremental) Compilation failed
[error] Total time: 58 s, completed 2022-9-13 14:41:21

I rebased https://github.com/akka/akka/pull/31345 to https://github.com/akka/akka/pull/31579 and change the M to _<:M and then run project akka-stream ++ 3.2.0 compile It shows the same

@mbovel Sorry for not minimize it, you can have a try.

He-Pin avatar Sep 13 '22 06:09 He-Pin

Mian.

import scala.collection.immutable

object Main {

  class Source[+Out, +Mat] extends Graph[SourceShape[Out], Mat]

  class Shape

  class SourceShape[+T] extends Shape

  class Graph[+S <: Shape, +M]

  def combine[T, U, M](sources: java.util.List[_ <: Graph[SourceShape[T], _ <: M]]): Source[U, java.util.List[M]] = {
    val seq: immutable.Seq[Graph[SourceShape[T], M]] = if (sources != null) immutableSeq(sources).collect {
      case source: Source[T, M]@unchecked => source
      case other => other
    } else immutable.Seq()
    ???
  }

  def immutableSeq[T](iterable: java.lang.Iterable[T]): immutable.Seq[T] = ???
}


it gives me:

C:\Users\hepin\IdeaProjects\MtoAnyTest\src\main\scala\Main.scala:16:21
Found:    (other : ?1.CAP)
Required: Main.Source[T, M] & ?1.CAP

where:    ?1 is an unknown value of type scala.runtime.TypeBox[Nothing, Main.Graph[Main.SourceShape[T], ? <: M]]

      case other => other

@mbovel @odersky this code compiles with 2.12.16 and 2.13.8

He-Pin avatar Sep 17 '22 12:09 He-Pin