Skip to content

-quickfix produces invalid syntax #12863

Open
@mrdziuban

Description

@mrdziuban

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

Activity

SethTisue

SethTisue commented on Sep 11, 2023

@SethTisue
Member

fyi @lrytz

xuwei-k

xuwei-k commented on Oct 13, 2023

@xuwei-k

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]
added this to the 2.13.13 milestone on Oct 13, 2023
lrytz

lrytz commented on Oct 18, 2023

@lrytz
Member

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

lrytz commented on Oct 18, 2023

@lrytz
Member

(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

joroKr21 commented on Oct 19, 2023

@joroKr21
Member

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.

modified the milestones: 2.13.13, Backlog on Nov 21, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

      Development

      No branches or pull requests

        Participants

        @lrytz@SethTisue@xuwei-k@joroKr21@mrdziuban

        Issue actions

          `-quickfix` produces invalid syntax · Issue #12863 · scala/bug