fs2 icon indicating copy to clipboard operation
fs2 copied to clipboard

`compile.to(ByteVector)` sometimes causes `java.lang.ClassCastException` in scala3

Open dzanot opened this issue 3 years ago • 3 comments

I encountered this in a cross built app and it worked for 2.12/2.13

Here is a scastie repro from @ChristopherDavenport via Discord

I attempted my own repro before I found Chris's, and to(ByteVector) worked in the case I came up with, for example

dzanot avatar Oct 04 '22 23:10 dzanot

Here's a scala-cli repro

//> using scala "3.2.0"
//> using lib "org.http4s::http4s-client::0.23.16"

import cats.effect._
import cats.syntax.all._
import org.http4s._
import org.http4s.implicits._
import org.http4s.client._
import fs2._
import scodec.bits._
import org.typelevel.ci._

  object CRC32 {
    def hash(data: Array[Byte]): Long = {
      val c = new java.util.zip.CRC32()
      c.update(data)
      c.getValue()
    }
  }

def buffered[F[_]: Concurrent](client: Client[F]): Client[F] = Client[F]{ (req: Request[F]) => 
   Resource.eval(req.body.compile.to(ByteVector)).map(c => req.withBodyStream(Stream.chunk(c)).covary[F]).flatMap(client.run)
}

def hashed[F[_]: Concurrent](client: Client[F]): Client[F] = Client[F]{ (req: Request[F]) =>
  Resource.eval(req.body.compile.to(ByteVector).map(_.toArray).map(CRC32.hash)).flatMap(hash => 
    client.run(req.putHeaders("crc32" -> hash.toString))
  )
}

val app = cats.data.Kleisli{(req: Request[IO]) => req.headers.get(CIString("crc32")).traverse_(IO.println) >> IO.pure(Response[IO]())}
val iClient = Client.fromHttpApp(app)

val req = Request[IO]().withEntity("Hello There!")

val client = hashed(buffered(iClient))




import cats.effect.unsafe.implicits.global

@main def main = client.run(req).use(_ => IO.unit).unsafeRunSync()

armanbilge avatar Oct 05 '22 00:10 armanbilge

Turns out Collector was getting inferred as Nothing here https://discord.com/channels/632277896739946517/632310980449402880/1027012526178832404 Not sure if this is still the best place for this issue?

dzanot avatar Oct 05 '22 00:10 dzanot

Checkpointing my minimization:

//> using scala "3.2.2-RC1-bin-20221003-5d1497d-NIGHTLY"
//> using lib "co.fs2::fs2-core::3.3.0"

import cats.effect._
import cats.syntax.all._
import fs2._
import scodec.bits._

def buffered[F[_]: Concurrent](body: Stream[F, Byte]): Resource[F, Unit] = 
   Resource.eval(body.compile.to(ByteVector)).map(c => Chunk.byteVector(c)).void

import cats.effect.unsafe.implicits.global

@main def main = buffered[IO](Stream(1.toByte)).use_.unsafeRunSync()

armanbilge avatar Oct 05 '22 02:10 armanbilge