From 5b5a934c175d7e60cecaa9152dfa2ad81f9ac0ea Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Kozak?= Date: Wed, 26 Aug 2026 21:17:49 +0200 Subject: [PATCH] Enable full compiler flag set (-Wsafe-init -Werror -Wunused:all + debug flags) --- project.scala | 9 +++++++-- src/mcodec/CborInput.scala | 7 +++++-- src/mcodec/Derivation.scala | 7 +++++++ test/mcodec/ExtendedStdCodecsTest.scala | 3 +-- test/mcodec/IoContractExtTest.scala | 6 +++--- test/mcodec/JavaHashSetIntTest.scala | 2 -- 6 files changed, 23 insertions(+), 11 deletions(-) diff --git a/project.scala b/project.scala index 5575473..3ff90c6 100644 --- a/project.scala +++ b/project.scala @@ -7,8 +7,13 @@ //> using options -deprecation -feature -new-syntax -unchecked //> using options -language:noAutoTupling -//> using options -Yexplicit-nulls -// //> using options -Wsafe-init -Werror -Wunused:all +//> using options -Vprofile -Xprint-inline +//> using options -Ycheck:macros -Ydebug-flags -Ydebug-missing-refs +//> using options -Ycheck:all +//> using options -Yexplain-lowlevel -Yexplicit-nulls +//> using options -Yshow-suppressed-errors -Yshow-var-bounds +//> using options -Wsafe-init -Werror -Wunused:all +////> using options -Yprofile-enabled" -Yprofile-trace:debug/compile-trace.json" //> using publish.organization com.halotukozak //> using publish.name mcodec diff --git a/src/mcodec/CborInput.scala b/src/mcodec/CborInput.scala index dcd200a..a0baada 100644 --- a/src/mcodec/CborInput.scala +++ b/src/mcodec/CborInput.scala @@ -229,14 +229,17 @@ class CborInput(reader: CborReader) extends InputAndSimpleInput: case _ => () case _ => throw ReadFailure(s"cannot skip major type $major") - private def skipChunks(major: Int): Unit = + // TODO: `major` is accepted but never checked against each chunk's own major type + // (discarded below as `_`) — malformed CBOR with mismatched chunk major types + // inside an indefinite-length container is currently accepted rather than rejected. + private def skipChunks(@scala.annotation.unused major: Int): Unit = var done = false while !done do if reader.peekU8() == 0xff then reader.u8() done = true else - val (cm, ca) = reader.readInitial() + val (_, ca) = reader.readInitial() reader.readBytes(reader.readArg(ca).toInt) // Skip an indefinite container's items until the 0xFF break. `perItem` is the diff --git a/src/mcodec/Derivation.scala b/src/mcodec/Derivation.scala index 3427c33..4d9a67a 100644 --- a/src/mcodec/Derivation.scala +++ b/src/mcodec/Derivation.scala @@ -3,11 +3,17 @@ package halotukozak.mcodec import halotukozak.made.* import halotukozak.made.annotation.optionalParam import halotukozak.commons.* +import scala.annotation.nowarn trait Derivation: this: MCodec.type => transparent inline def derivedRec[T: Made.Of as m]: MCodec[T] = val deferred = new Deferred[T] + // `self` isn't referenced by name here, but it's what lets a recursive/self-referential + // T resolve MCodec[T] via implicit search during its own derivation below (deferred ties + // the knot). -Wunused can't see that usage since it only appears after this transparent + // inline def is expanded at call sites, so it's suppressed rather than removed. + @nowarn("msg=unused local definition") given self: MCodec[T] = deferred val built = deriveDispatch[T](m) deferred.underlying = built @@ -118,6 +124,7 @@ trait Derivation: val c = compiletime.summonFrom: case given MCodec[`head`] => compiletime.summonInline[MCodec[head]] case _ => MCodec.derived[head] + : @nowarn("msg=unused pattern variable") c.asInstanceOf[MCodec[Any]] :: summonOrDeriveCases[tail] diff --git a/test/mcodec/ExtendedStdCodecsTest.scala b/test/mcodec/ExtendedStdCodecsTest.scala index 1323b4e..a42abf5 100644 --- a/test/mcodec/ExtendedStdCodecsTest.scala +++ b/test/mcodec/ExtendedStdCodecsTest.scala @@ -1,11 +1,10 @@ package halotukozak.mcodec import halotukozak.mcodec.MValue.* -import org.scalacheck.{Arbitrary, Gen} +import org.scalacheck.Arbitrary import java.lang as jl import java.util as ju -import scala.jdk.CollectionConverters.* class ExtendedStdCodecsTest extends RoundTrip(InMemoryBackend), JsonConv: diff --git a/test/mcodec/IoContractExtTest.scala b/test/mcodec/IoContractExtTest.scala index c0969e2..37da882 100644 --- a/test/mcodec/IoContractExtTest.scala +++ b/test/mcodec/IoContractExtTest.scala @@ -68,7 +68,7 @@ class IoContractExtTest extends munit.FunSuite: intercept[ReadFailure](imRead(MString(""))(_.readChar())) // ===== Float precision ===== - private val floatCases = + private lazy val floatCases = Seq(Float.MinValue, Float.MaxValue, Float.MinPositiveValue, -0.0f, 0.0f, 1.1f, 1.4e-45f, 3.14159f) test("Float round-trips EXACTLY via InMemory"): @@ -93,7 +93,7 @@ class IoContractExtTest extends munit.FunSuite: assert(jsonHarvest(_.writeFloat(Float.NaN)).startsWith("\"")) // ===== Timestamp ===== - private val tsCases = Seq(0L, 1L, 1L << 50, Long.MaxValue, -1000L) + private lazy val tsCases = Seq(0L, 1L, 1L << 50, Long.MaxValue, -1000L) test("Timestamp round-trips via InMemory"): for t <- tsCases do assertEquals(imRead(imHarvest(_.writeTimestamp(t)))(_.readTimestamp()), t) @@ -106,7 +106,7 @@ class IoContractExtTest extends munit.FunSuite: assertEquals(jsonHarvest(_.writeTimestamp(1750000000000L)), "1750000000000") // ===== Binary ===== - private val binCases: Seq[Array[Byte]] = + private lazy val binCases: Seq[Array[Byte]] = Seq( Array.empty[Byte], Array[Byte](1, 2, 3), diff --git a/test/mcodec/JavaHashSetIntTest.scala b/test/mcodec/JavaHashSetIntTest.scala index 06c910c..cbfb356 100644 --- a/test/mcodec/JavaHashSetIntTest.scala +++ b/test/mcodec/JavaHashSetIntTest.scala @@ -2,8 +2,6 @@ package halotukozak.mcodec -import halotukozak.mcodec.MValue.* - import java.util as ju // Passes on JVM and Scala.js; crashes the Scala Native runtime with