scala / bug

Scala 2 bug reports only. Please, no questions — proper bug reports only.
https://scala-lang.org
232 stars 21 forks source link

Type mismatch under `-Xsource:3` with inferred overridden types #12707

Closed hmemcpy closed 1 year ago

hmemcpy commented 1 year ago

Reproduction steps

A recent change in Scala 2.13.9 (#9891) caused a lot of compilation errors in our code base that was previously compiling. We're using ZIO, and heavily rely on type inference, so most of our codebase omits type signatures. The following snippet is compiles fine in Scala 2.13 with -Xsource:3 before 2.13.9:

import zio.*
import zio.console.Console

object Server {
  type Pizza
  type Broccoli

  val start: ZIO[Console & Broccoli, Nothing, Unit] = {
    val handler = (ServiceImpl.foo _).tupled
    handler("blah", 1).unit
  }
}

trait Service[-R] {
  def foo(s: String, i: Int): ZIO[R, Nothing, String]
}

object ServiceImpl extends Service[Console & Pizza]{
  def foo(s: String, i: Int) =
    zio.console.putStrLn("blah").orDie.as("")
}

Causing the following mismatch:

type mismatch;
 found   : zio.ZIO[zio.console.Console with Server.Pizza,Nothing,Unit]
    (which expands to)  zio.ZIO[zio.Has[zio.console.Console.Service] with Server.Pizza,Nothing,Unit]
 required: zio.ZIO[zio.console.Console with Server.Broccoli,Nothing,Unit]
    (which expands to)  zio.ZIO[zio.Has[zio.console.Console.Service] with Server.Broccoli,Nothing,Unit]
    handler("blah", 1).unit

I understand the nature of the change, but I would like a workaround that does not require me to change hundreds of type signatures... Please advise.

som-snytt commented 1 year ago

This is zio 1.0.17. It's helpful to provide a minimal build (or scala-cli header). The example needs an import Server.Pizza to compile.

Dotty says

[error] -- [E007] Type Mismatch Error: .../t12707/src/main/scala/t12707.scala:13:23
[error] 13 |    handler("blah", 1).unit
[error]    |    ^^^^^^^^^^^^^^^^^^^^^^^
[error]    | Found:    zio.ZIO[zio.console.Console & Server.Pizza, Nothing, Unit]
[error]    | Required: zio.ZIO[zio.console.Console & Server.Broccoli, Nothing, Unit]
[error]    |
[error]    | longer explanation available when compiling with `-explain`
[error] one error found
[error] (Compile / compileIncremental) Compilation failed
[error] Total time: 6 s, completed Jan 1, 2023, 10:50:35 AM

If it is agreed that this is correct behavior, then -Xsource:3 is doing the right thing, which is to show what will happen under migration. (Matching Dotty behavior is best-effort.)

The type inferred from RHS was type C0 = zio.ZIO[zio.console.Console, Nothing, String].

The reason to prefer to infer the overridden type was that the RHS (as a co-variant subtype) is too constraining, such as an Option[_] narrowed to None. But perhaps inference should be more loosey-goosey with contravariant type params. As in the example, the RHS expresses a subtype that is less constrained in that type param. (But consider further overriding.)

som-snytt commented 1 year ago

Further questions about contravariance and override: https://github.com/lampepfl/dotty/issues/10079

SethTisue commented 1 year ago

a meta-issue here is that we don't have good documentation for -Xsource: https://github.com/scala/scala-dev/issues/470

SethTisue commented 7 months ago

For anyone happening to land on this ticket, note that as of 2.13.13 the behavior change with inferred return types on overrides no longer occurs under -Xsource:3, only under the new -Xsource:3-cross.