scala / bug

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

`-quickfix` produces invalid syntax #12863

Open mrdziuban opened 9 months ago

mrdziuban commented 9 months ago

Reproduction steps

Scala version: 2.13.12

With -Xsource:3 and -quickfix:any enabled, the quickfix applied to val parallel in this code is syntactically invalid

import cats.{~>, Parallel}
import cats.data.Kleisli

object test {
  implicit def parallel[M[_], A](implicit P: Parallel[M]): Parallel.Aux[Kleisli[M, A, *], Kleisli[P.F, A, *]] =
    new Parallel[Kleisli[M, A, *]] {
      type F[a] = Kleisli[P.F, A, a]

      val parallel = new (Kleisli[M, A, *] ~> Kleisli[P.F, A, *]) {
        def apply[B](k: Kleisli[M, A, B]) = Kleisli(a => P.parallel(k.run(a)))
      }

      lazy val sequential: Nothing = ???
      lazy val applicative: Nothing = ???
      lazy val monad: Nothing = ???
    }
}

The resulting code for val parallel is:

val parallel : [γ$3$]cats.data.Kleisli[M,A,γ$3$] ~> [γ$4$]cats.data.Kleisli[P.F,A,γ$4$]= new (Kleisli[M, A, *] ~> Kleisli[P.F, A, *]) {
  def apply[B](k: Kleisli[M, A, B]) = Kleisli(a => P.parallel(k.run(a)))
}

which results in a compile error on next compile:

[error] /Users/matt/test-scala-2.13.12-quickfix/src/main/scala/example/Test.scala:9:22: [rewritten by -quickfix] identifier expected but '[' found.
[error]       val parallel : [γ$3$]cats.data.Kleisli[M,A,γ$3$] ~> [γ$4$]cats.data.Kleisli[P.F,A,γ$4$]= new (Kleisli[M, A, *] ~> Kleisli[P.F, A, *]) {
[error]                      ^

Problem

Ideally any changes applied by the compiler would then compile successfully. I imagine this particular case might be tough because it involves type lambdas but figured I'd report it anyway

SethTisue commented 9 months ago

fyi @lrytz

xuwei-k commented 8 months ago

another example

build.sbt

resolvers += "scala-integration" at "https://scala-ci.typesafe.com/artifactory/scala-integration/"

// https://github.com/scala/scala/tree/31539736462078b1da615880ef11890a6538b45e
scalaVersion := "2.13.13-bin-3153973"

scalacOptions += "-quickfix:any"

A.scala

object A {
  type Const[B] = {
    type C[D] = B
  }

  class E[F[_]]

  implicit def x = new E[Const[Int]#C]
}

   class E[F[_]]

-  implicit def x = new E[Const[Int]#C]
+  implicit def x: A.E[[D]Int] = new E[Const[Int]#C]
lrytz commented 8 months ago

In both examples the issue is that Type.toString returns something that's not a valid type in source. The invalid toString also shows up in the error messages:

[error] under -Xsource:3, inferred [γ$2$]cats.data.Kleisli[M,A,γ$2$] ~> this.F instead of [γ$3$]cats.data.Kleisli[M,A,γ$3$] ~> [γ$4$]cats.data.Kleisli[P.F,A,γ$4$]
Test.scala:26: warning: Implicit definition should have explicit type (inferred A.E[[D]Int])

The type A.E[[D]Int] is represented as TypeRef(A.E, PolyType(List(D), Int)), which seems fine. Maybe we could try to identify types of which we know toString is not valid source code and not offer the quick fix in this case. Not sure.

lrytz commented 8 months ago

(the wrong formatting visible here is fixed in current 2.13.x):

val parallel : [γ$3$]cats.data.Kleisli[M,A,γ$3$] ~> [γ$4$]cats.data.Kleisli[P.F,A,γ$4$]= new ...
joroKr21 commented 8 months ago

We could change PolyType.toString to give you the poor-man's type lambda A.E[({ type λ[D] = Int })#λ]. But also there is some dealiasing going on because we lost the original type. Fixing that is harder.