Skip to content
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

Scala 2.13.6 Compiler Throws AssertionError #12467

Closed
jrduncans opened this issue Sep 30, 2021 · 5 comments · Fixed by scala/scala#9777
Closed

Scala 2.13.6 Compiler Throws AssertionError #12467

jrduncans opened this issue Sep 30, 2021 · 5 comments · Fixed by scala/scala#9777

Comments

@jrduncans
Copy link

jrduncans commented Sep 30, 2021

reproduction steps

import akka.stream.scaladsl.Source
import akka.stream.stage._
import akka.stream.{Attributes, Outlet, SourceShape}
import cats.syntax.all._

import scala.concurrent.duration.{Duration, _}
import scala.concurrent.{Await, ExecutionContext, Future}

trait PagedRequest[A, PageIdentifier, Response] {
  def getPage(a: A)(id: PageIdentifier): Future[Response]
  def start(a: A)(implicit pagedResponse: PagedResponse[Response, PageIdentifier]): pagedResponse.NextPage
}

// scalastyle:off structural.type
object PagedResponse {
  type Aux[A0, PageIdentifier0, Item0] = PagedResponse[A0, PageIdentifier0] { type Item = Item0 }
}

trait PagedResponse[A, PageIdentifier] {
  type Item
  sealed trait NextPage
  case class Next(page: PageIdentifier) extends NextPage
  case class NoMorePages() extends NextPage

  def nextPage(a: A): NextPage
  def elements(a: A): List[Item]
}

object PagingSource {
  def apply[Request : ({ type PR[A] = PagedRequest[A, PageIdentifier, Response] })#PR, Response, PageIdentifier, Item](
    paged: Request,
    timeout: Duration = 5.seconds
  )(
    implicit ec: ExecutionContext,
    responseOps: PagedResponse.Aux[Response, PageIdentifier, Item]
  ): Source[Item, akka.NotUsed] =
    Source.fromGraph(new PagingSource(paged, timeout))
}

class PagingSource[
  Request : ({ type PR[A] = PagedRequest[A, PageIdentifier, Response] })#PR,
  Response,
  PageIdentifier,
  Item
](paged: Request, timeout: Duration)(
  implicit ec: ExecutionContext,
  responseOps: PagedResponse.Aux[Response, PageIdentifier, Item]
) extends GraphStage[SourceShape[Item]] {

  val out: Outlet[Item] = Outlet("Output")
  override val shape: SourceShape[Item] = SourceShape(out)

  val pagedOps = implicitly[PagedRequest[Request, PageIdentifier, Response]]

  override def createLogic(inheritedAttributes: Attributes): GraphStageLogic = new GraphStageLogic(shape) {
    var nextPage: PagedResponse.Aux[Response, PageIdentifier, Item]#NextPage = pagedOps.start(paged)
    val queue = scala.collection.mutable.Queue.empty[Item]

    setHandler(
      out,
      new OutHandler {
        override def onPull(): Unit =
          if (queue.nonEmpty) {
            push(out, queue.dequeue())
          } else {
            nextPage match {
              case _: PagedResponse.Aux[Response, PageIdentifier, Item]#NoMorePages => completeStage()
              case next: PagedResponse.Aux[Response, PageIdentifier, Item]#Next =>
                (for {
                  returnedPage <- Either.catchNonFatal {
                    Await.result(pagedOps.getPage(paged)(next.page), timeout)
                  }
                } yield {
                  queue ++= responseOps.elements(returnedPage)
                  nextPage = responseOps.nextPage(returnedPage)
                }).bimap(
                  exception => fail(out, exception),
                  _ => if (queue.nonEmpty) push(out, queue.dequeue()) else completeStage()
                )
            }
          }
      }
    )
  }
}

Produces error:

[error] ## Exception when compiling 1 sources to /Users/user/workspace/playground/clone-error-test/target/scala-2.13/classes
[error] java.lang.AssertionError: assertion failed:
[error]   mkAttributedQualifier(example.PagedResponse[Response,PageIdentifier]{type Item = Item}, <none>) parents = List(example.PagedResponse[Response,PageIdentifier])
[error]      while compiling: /Users/user/workspace/playground/clone-error-test/src/main/scala/example/Hello.scala
[error]         during phase: patmat
[error]      library version: version 2.13.6
[error]     compiler version: version 2.13.6
[error]
[error]   last tree to typer: Ident(x)
[error]        tree position: line 25 of /Users/user/workspace/playground/clone-error-test/src/main/scala/example/Hello.scala
[error]             tree tpe: Boolean
[error]               symbol: value x
[error]    symbol definition: x: Boolean (a TermSymbol)
[error]       symbol package: <none>
[error]        symbol owners: value x
[error]            call site: method onPull in package example
[error]
[error] == Source file context for tree position ==
[error]
[error]     22   type Item
[error]     23   sealed trait NextPage
[error]     24   case class Next(page: PageIdentifier) extends NextPage
[error]     25   case class NoMorePages() extends NextPage
[error]     26
[error]     27   def nextPage(a: A): NextPage
[error]     28   def elements(a: A): List[Item]
[error] scala.reflect.internal.SymbolTable.throwAssertionError(SymbolTable.scala:171)
[error] scala.reflect.internal.TreeGen.mkAttributedQualifier(TreeGen.scala:117)
[error] scala.reflect.internal.TreeGen.mkAttributedQualifier(TreeGen.scala:74)
[error] scala.reflect.internal.TreeGen.mkAttributedQualifierIfPossible(TreeGen.scala:152)
[error] scala.tools.nsc.transform.patmat.MatchTreeMaking$TreeMakers$TypeTestTreeMaker$treeCondStrategy$.withOuterTest(MatchTreeMaking.scala:431)
[error] scala.tools.nsc.transform.patmat.MatchTreeMaking$TreeMakers$TypeTestTreeMaker$treeCondStrategy$.withOuterTest(MatchTreeMaking.scala:339)
[error] scala.tools.nsc.transform.patmat.MatchTreeMaking$TreeMakers$TypeTestTreeMaker.addOuterTest$1(MatchTreeMaking.scala:520)
[error] scala.tools.nsc.transform.patmat.MatchTreeMaking$TreeMakers$TypeTestTreeMaker.mkDefault$1(MatchTreeMaking.scala:530)
[error] scala.tools.nsc.transform.patmat.MatchTreeMaking$TreeMakers$TypeTestTreeMaker.renderCondition(MatchTreeMaking.scala:554)

problem

This code compiled under numerous previous version of Scala, including Scala 2.13.5.

@SethTisue
Copy link
Member

SethTisue commented Sep 30, 2021

That's a lot of code — have you attempted to minimize it?

A proper minimization would 1) have less code in it, probably a lot less, and 2) if at all possible, not involve an external dependency.

(Regardless, thanks for the report, it is already valuable.)

@jrduncans
Copy link
Author

Not having a clue what the error means, I didn't have any idea where to start minimizing. I will update if I find the time to trial and error into anything simpler.

@griggt
Copy link

griggt commented Oct 1, 2021

Minimized to:

object PagedResponse {
  type Aux[Item0] = PagedResponse { type Item = Item0 }
}

trait PagedResponse {
  type Item
  sealed trait NextPage
  case class NoMorePages() extends NextPage
}

object Test {
  def foo[A](next: PagedResponse.Aux[A]#NextPage): Unit = next match {
    case _: PagedResponse.Aux[A]#NoMorePages => ???
  }
}
$ scalac -2.12.15 t12467.scala     // ok
$ scalac -2.13.5  t12467.scala     // ok
$ scalac -3.0.2   t12467.scala     // ok
$ scalac -2.13.6  t12467.scala
error: java.lang.AssertionError: assertion failed:
  mkAttributedQualifier(PagedResponse{type Item = A}, <none>) parents = List(PagedResponse)
     while compiling: t12467.scala
        during phase: patmat
     library version: version 2.13.6
    compiler version: version 2.13.6
  reconstructed args:

  last tree to typer: Ident(x)
       tree position: line 8 of t12467.scala
            tree tpe: Boolean
              symbol: value x
   symbol definition: x: Boolean (a TermSymbol)
      symbol package: <none>
       symbol owners: value x
           call site: method foo in object Test in package <empty>

== Source file context for tree position ==

     5 trait PagedResponse {
     6   type Item
     7   sealed trait NextPage
     8   case class NoMorePages() extends NextPage
     9 }
    10
    11 object Test {
	at scala.reflect.internal.SymbolTable.throwAssertionError(SymbolTable.scala:171)
	at scala.reflect.internal.TreeGen.mkAttributedQualifier(TreeGen.scala:117)
	at scala.reflect.internal.TreeGen.mkAttributedQualifier(TreeGen.scala:74)
	at scala.reflect.internal.TreeGen.mkAttributedQualifierIfPossible(TreeGen.scala:152)
	at scala.tools.nsc.transform.patmat.MatchTreeMaking$TreeMakers$TypeTestTreeMaker$treeCondStrategy$.withOuterTest(MatchTreeMaking.scala:431)
	at scala.tools.nsc.transform.patmat.MatchTreeMaking$TreeMakers$TypeTestTreeMaker$treeCondStrategy$.withOuterTest(MatchTreeMaking.scala:339)
	at scala.tools.nsc.transform.patmat.MatchTreeMaking$TreeMakers$TypeTestTreeMaker.addOuterTest$1(MatchTreeMaking.scala:520)
	at scala.tools.nsc.transform.patmat.MatchTreeMaking$TreeMakers$TypeTestTreeMaker.mkDefault$1(MatchTreeMaking.scala:530)
	at scala.tools.nsc.transform.patmat.MatchTreeMaking$TreeMakers$TypeTestTreeMaker.renderCondition(MatchTreeMaking.scala:554)
	at scala.tools.nsc.transform.patmat.MatchTreeMaking$TreeMakers$TypeTestTreeMaker.<init>(MatchTreeMaking.scala:558)

@SethTisue
Copy link
Member

Thanks, Tom!

It isn't obvious to me what PR might be responsible. @lrytz @dwijnand do you have a guess? if not, I guess the next step would be bisecting it

@dwijnand
Copy link
Member

dwijnand commented Oct 1, 2021

Thanks for the minimisation, Tom!

scala/scala#9504. That's @retronym's code, that looks to improving how we validate that the prefixes align. But here the prefixes are not stable values, they're just refined types (behind the aux type alias) so there's no outer test to emit. I'll send a patch.

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