Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
14 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
48 changes: 48 additions & 0 deletions MIGRATION.md
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,31 @@ the bottom of this file. Restoration ships incrementally per feature area.
compiles).
- `enum` was renamed to `e` at one call site in `GenKeyCodec` (`enum` is reserved in Scala 3).
- `@targetName` annotation added to `CloseableIterator` overloaded methods.
- `implicit val/def` typeclass instances rewritten to `given` across `serialization`, `cbor`,
`meta`, `misc`, `tuples` (slice 3.3). Named-import callers that referenced these by name
(e.g. `GenCodec.bseqCodec`, `GenKeyCodec.IntKeyCodec`, `TypeString.codec`) must switch to
`summon[GenCodec[BSeq[T]]]` or use `import X.given` for given-import semantics. Anonymous
`given T = …` preferred for canonical instances per fork pattern.
- Named-import compatibility shims: `@deprecated def NAME: T = summon[T]` aliases added in
`BoxingUnboxing` (`BooleanBoxing` … `DoubleBoxing`, `BooleanUnboxing` … `DoubleUnboxing`)
and `GenKeyCodec` (`BooleanKeyCodec` … `BytesKeyCodec`) so downstream callers using
`GenKeyCodec.IntKeyCodec`-style named lookup keep compiling. Each shim emits a deprecation
warning pointing to `summon[T]`. Mirrors `BsonGenCodecs` source-compat layer from fork
commit `8f70be80`.
- `OptArg.argToOptArg` PRESERVED as `implicit def` — polymorphic `Conversion[A, OptArg[A]]`
would generate a clashing JVM erasure bridge (both `A` and the `OptArg` value class erase to
`Object`). Verbatim explanatory comment from fork `39c047eb` retained inline.
- `GenRef.fun2GenRef` PRESERVED as `implicit def` (currently a `???` Phase-2 stub; Phase 4
feature-port will restore the macro-splice body; macro-splice-over-inline-arg rationale per
fork `ebffde26` documented as preservation rule).
- `RunNowEC.Implicits.executionContext` / `RunInQueueEC.Implicits.executionContext` PRESERVED
as `implicit val` — the wildcard-import-into-`Implicits`-object idiom is the public API
(`import RunNowEC.Implicits._`). Converting to `given` would silently stop providing the EC
to wildcard-import callers (givens require `import X.given`).
- `(implicit X: T)` parameter lists left in place across slice-3.1 extension-shim sites
(`SharedExtensions.implicit def *Ops`, jiop, jsiop, `Components.autoComponent`, etc.). Those
are conversion shims for `implicit class` value-class wrappers and are being rewritten to
`extension` blocks in slice 3.1 (PR #868), which deletes the conversion entirely.

### mongo

Expand All @@ -63,10 +88,33 @@ the bottom of this file. Restoration ships incrementally per feature area.
Scala 3 forbids type projections on non-concrete prefixes). Public-API signature change.
- `BsonValueOutput.write` / `BsonValueInput.read` call sites require explicit `using` keyword.
- `MongoPolyDataCompanion` / `TypedMapFormat` / `TypedMapRefOps` widened from `K[_]` / `D[_]` to `K[Any]` / `D[Any]`.
- `(implicit X: T)` parameter lists rewritten to `(using X: T)` across 19 mongo files in
slice 3.3 (BsonCodec, BsonRef, DocKey, Filter, GenCodecProvider, BsonRefIterable*, Sorting,
MongoOps, TextSearchLanguage, DataTypeDsl, MongoEntityCompanion, MongoIndex,
MongoPolyDataCompanion, MongoRef, MongoUpdateOperator, ProjectionZippers, QueryOperatorsDsl,
TypedMongoCollection). Source-compat: positional call sites unchanged (Scala 3 accepts both
syntaxes); named-arg call sites must update from `foo(x = …)` to `foo(using x = …)`.
- `BsonGenCodecs` rewritten per fork `8f70be80`: trait uses `export BsonGenCodecs.given`,
object holds anonymous `given GenCodec[X] = …` declarations + `@deprecated def name: T = summon`
shims for source-compat with named-import callers (`BsonGenCodecs.objectIdCodec`, etc.).
- `MongoFormat.codec` / `MongoAdtFormat.codec`/`dataClassTag` are now `given` in trait
declarations; consumers using `import meta.format._` to bring `codec`/`dataClassTag` into
implicit scope must switch to `import meta.format.{given, _}` for given-import semantics
(already applied internally in `TypedMongoCollection.mkNativeCollection`).
- `KeyGetter.bsonRefKeyGetter` / `docKeyKeyGetter` rewritten from `implicit object … extends T`
to `given X: T with { … }`. Source-compat: positional resolution unchanged; `import X._`
callers must switch to `import X.given`.

### hocon

- `SealedEnumCompanion.values` override now `lazy val` (see core notes).
- `HoconGenCodecs` codec instances (`ConfigCodec`, `FiniteDurationCodec`, `JavaDurationCodec`,
`PeriodCodec`, `SizeInBytesCodec`, `ClassKeyCodec`, `ClassCodec`) rewritten from
`implicit final val` to `given` (slice 3.3). Same named-import caveat as the core entry
applies.
- `ConfigObjectCompanion.codec` instance and `DefaultConfigCompanion` macro-instance
parameter rewritten to `using`.
- `HTree.HIncludeQualifier` / `HStringSyntax` constructor implicit param rewritten to `using`.

## 4. Binary-compat breaks

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,13 +18,13 @@ class GenCodecBenchmarks {

@Benchmark
def cleanSomeWriting: String = {
implicit val cleanCodec: GenCodec[Option[String]] = GenCodecBenchmarks.cleanOptionCodec[String]
given cleanCodec: GenCodec[Option[String]] = GenCodecBenchmarks.cleanOptionCodec[String]
JsonStringOutput.write(GenCodecBenchmarks.somes)
}

@Benchmark
def cleanNoneWriting: String = {
implicit val cleanCodec: GenCodec[Option[String]] = GenCodecBenchmarks.cleanOptionCodec[String]
given cleanCodec: GenCodec[Option[String]] = GenCodecBenchmarks.cleanOptionCodec[String]
JsonStringOutput.write(GenCodecBenchmarks.nones)
}

Expand All @@ -34,7 +34,7 @@ class GenCodecBenchmarks {
}

object GenCodecBenchmarks {
implicit def cleanOptionCodec[T: GenCodec]: GenCodec[Option[T]] =
given cleanOptionCodec[T: GenCodec]: GenCodec[Option[T]] =
GenCodec.create[Option[T]](
i => if (i.readNull()) None else Some(GenCodec.read[T](i)),
(o, vo) =>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@ case class Toplevel(int: Int, nested: Nested, str: String)
case class Nested(list: List[Int], int: Int)

object Toplevel {
implicit val nestedCodec: GenCodec[Nested] = GenCodec.materialize[Nested]
implicit val codec: GenCodec[Toplevel] = GenCodec.materialize[Toplevel]
given nestedCodec: GenCodec[Nested] = GenCodec.materialize[Nested]
given codec: GenCodec[Toplevel] = GenCodec.materialize[Toplevel]
}

@Warmup(iterations = 10)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import com.avsystem.commons.misc.{AbstractValueEnum, AbstractValueEnumCompanion,
/** Specifies format used by `NativeJsonOutput.writeLong` / `NativeJsonInput.readLong` to represent [[Long]]. JS does
* not support 64-bit representation.
*/
final class NativeLongFormat(implicit ctx: EnumCtx) extends AbstractValueEnum
final class NativeLongFormat(using ctx: EnumCtx) extends AbstractValueEnum
object NativeLongFormat extends AbstractValueEnumCompanion[NativeLongFormat] {
final val RawString: Value = new NativeLongFormat
final val JsNumber: Value = new NativeLongFormat
Expand All @@ -16,7 +16,7 @@ object NativeLongFormat extends AbstractValueEnumCompanion[NativeLongFormat] {
/** Specifies format used by `NativeJsonOutput.writeTimestamp` / `NativeJsonInput.readTimestamp` to represent
* timestamps.
*/
final class NativeDateFormat(implicit ctx: EnumCtx) extends AbstractValueEnum
final class NativeDateFormat(using ctx: EnumCtx) extends AbstractValueEnum
object NativeDateFormat extends AbstractValueEnumCompanion[NativeDateFormat] {
final val RawString: Value = new NativeDateFormat
final val JsNumber: Value = new NativeDateFormat
Expand All @@ -27,7 +27,7 @@ object NativeDateFormat extends AbstractValueEnumCompanion[NativeDateFormat] {
*
* Note that [[scala.scalajs.js.JSON.stringify]] does not know how to serialize a BigInt and throws an error
*/
final class NativeBigIntFormat(implicit ctx: EnumCtx) extends AbstractValueEnum
final class NativeBigIntFormat(using ctx: EnumCtx) extends AbstractValueEnum
object NativeBigIntFormat extends AbstractValueEnumCompanion[NativeBigIntFormat] {
final val RawString: Value = new NativeBigIntFormat
final val JsBigInt: Value = new NativeBigIntFormat
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ abstract class BlockingUtils {

/** Default scheduler used to run `Task`s and `Observable`s. This scheduler is not meant for blocking code.
*/
implicit def scheduler: Scheduler
given scheduler: Scheduler

/** Scheduler used for running blocking code.
*/
Expand Down Expand Up @@ -71,6 +71,6 @@ abstract class BlockingUtils {
}

object DefaultBlocking extends BlockingUtils {
implicit def scheduler: Scheduler = Scheduler.global
given scheduler: Scheduler = Scheduler.global
lazy val ioScheduler: Scheduler = Scheduler.io()
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ class ObservableBlockingIterator[T](
timeout: Long,
unit: TimeUnit,
bufferSize: Int,
)(implicit val scheduler: Scheduler
)(using val scheduler: Scheduler
) extends CloseableIterator[T]
with Subscriber[T] {

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -67,13 +67,13 @@ class RunInQueueEC extends ExecutionContextExecutor {
}

trait HasExecutionContext {
protected implicit def executionContext: ExecutionContext
protected given executionContext: ExecutionContext
}

trait HasRunNowEC extends HasExecutionContext {
protected implicit final def executionContext: ExecutionContext = RunNowEC
protected implicit val executionContext: ExecutionContext = RunNowEC
}

trait HasRunInQueueEC extends HasExecutionContext {
protected implicit final def executionContext: ExecutionContext = RunInQueueEC
protected implicit val executionContext: ExecutionContext = RunInQueueEC
}
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ object ComponentInfo {
)

@compileTimeOnly("implicit ComponentInfo is only available inside code passed to component/singleton macro")
implicit def info: ComponentInfo = sys.error("stub")
given info: ComponentInfo = sys.error("stub")
}

/** Represents a lazily initialized component in a dependency injection setting. The name "component" indicates that the
Expand Down
9 changes: 5 additions & 4 deletions core/src/main/scala/com/avsystem/commons/di/Components.scala
Original file line number Diff line number Diff line change
Expand Up @@ -43,11 +43,12 @@ trait Components extends ComponentsLowPrio {
// avoids divergent implicit expansion involving `inject`
// this is not strictly necessary but makes compiler error messages nicer
// i.e. the compiler will emit "could not find implicit value" instead of "divergent implicit expansion"
implicit def ambiguousArbitraryComponent1[T]: Component[T] = null
implicit def ambiguousArbitraryComponent2[T]: Component[T] = null
given ambiguousArbitraryComponent1[T]: Component[T] = null
given ambiguousArbitraryComponent2[T]: Component[T] = null

// TODO[scala3-port]: autoComponent (Scala 2 macro def) (L)
implicit def autoComponent[T](definition: => T)(implicit sourceInfo: SourceInfo): AutoComponent[T] = ???
// Kept as `implicit def`: macro-stubbed and takes a by-name parameter, which a non-inline `given Conversion` cannot carry.
implicit def autoComponent[T](definition: => T)(using sourceInfo: SourceInfo): AutoComponent[T] = ???

// TODO[scala3-port]: optEmptyComponent (depends on stubbed singleton macro) (S)
protected def optEmptyComponent: Component[Opt[Nothing]] = ???
Expand All @@ -65,5 +66,5 @@ trait ComponentsLowPrio {
@compileTimeOnly(
"implicit Component[T] => implicit T inference only works inside code passed to component/singleton macro"
)
implicit def inject[T](implicit component: Component[T]): T = sys.error("stub")
given inject[T](using component: Component[T]): T = sys.error("stub")
}
Original file line number Diff line number Diff line change
Expand Up @@ -45,5 +45,5 @@ object MacroInstances {
final class materializeWith(prefix: Any, materializer: String = "materialize") extends StaticAnnotation

// TODO[scala3-port]: materialize (Scala 2 macro def) (L)
implicit def materialize[Implicits, Instances]: MacroInstances[Implicits, Instances] = ???
given materialize[Implicits, Instances]: MacroInstances[Implicits, Instances] = ???
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,9 @@ import scala.annotation.implicitNotFound
* metadata class constructor
*/
trait MetadataCompanion[M[_]] {
final def apply[Real](implicit metadata: M[Real]): M[Real] = metadata
final def apply[Real](using metadata: M[Real]): M[Real] = metadata

implicit final def fromFallback[Real](implicit fallback: Fallback[M[Real]]): M[Real] = fallback.value
given fromFallback[Real](using fallback: Fallback[M[Real]]): M[Real] = fallback.value

final class Lazy[Real](metadata: => M[Real]) {
lazy val value: M[Real] = metadata
Expand All @@ -25,10 +25,10 @@ trait MetadataCompanion[M[_]] {

// macro effectively turns `metadata` param into by-name param (implicit params by themselves cannot be by-name)
// TODO[scala3-port]: lazyMetadata (Scala 2 macro def) (L)
implicit def lazyMetadata[Real](implicit metadata: M[Real]): Lazy[Real] = ???
given lazyMetadata[Real](using metadata: M[Real]): Lazy[Real] = ???

@implicitNotFound("#{forNotLazy}")
implicit def notFound[T](implicit forNotLazy: ImplicitNotFound[M[T]]): ImplicitNotFound[Lazy[T]] =
given notFound[T](using forNotLazy: ImplicitNotFound[M[T]]): ImplicitNotFound[Lazy[T]] =
ImplicitNotFound()
}
}
Expand All @@ -44,9 +44,9 @@ trait MetadataCompanion[M[_]] {
*/
// cannot share code with MetadataCompanion because of binary compatibility problems, must copy
trait BoundedMetadataCompanion[Hi, Lo <: Hi, M[_ >: Lo <: Hi]] {
final def apply[Real >: Lo <: Hi](implicit metadata: M[Real]): M[Real] = metadata
final def apply[Real >: Lo <: Hi](using metadata: M[Real]): M[Real] = metadata

implicit final def fromFallback[Real >: Lo <: Hi](implicit fallback: Fallback[M[Real]]): M[Real] = fallback.value
given fromFallback[Real >: Lo <: Hi](using fallback: Fallback[M[Real]]): M[Real] = fallback.value

final class Lazy[Real >: Lo <: Hi](metadata: => M[Real]) {
lazy val value: M[Real] = metadata
Expand All @@ -56,10 +56,10 @@ trait BoundedMetadataCompanion[Hi, Lo <: Hi, M[_ >: Lo <: Hi]] {

// macro effectively turns `metadata` param into by-name param (implicit params by themselves cannot be by-name)
// TODO[scala3-port]: lazyMetadata (bounded) (Scala 2 macro def) (L)
implicit def lazyMetadata[Real >: Lo <: Hi](implicit metadata: M[Real]): Lazy[Real] = ???
given lazyMetadata[Real >: Lo <: Hi](using metadata: M[Real]): Lazy[Real] = ???

@implicitNotFound("#{forNotLazy}")
implicit def notFound[T >: Lo <: Hi](implicit forNotLazy: ImplicitNotFound[M[T]]): ImplicitNotFound[Lazy[T]] =
given notFound[T >: Lo <: Hi](using forNotLazy: ImplicitNotFound[M[T]]): ImplicitNotFound[Lazy[T]] =
ImplicitNotFound()
}
}
14 changes: 6 additions & 8 deletions core/src/main/scala/com/avsystem/commons/meta/OptionLike.scala
Original file line number Diff line number Diff line change
Expand Up @@ -53,19 +53,19 @@ final class OptionLikeImpl[O, A](
object OptionLike {
type Aux[O, V] = OptionLike[O] { type Value = V }

implicit def optionOptionLike[A]: BaseOptionLike[Option[A], A] =
given optionOptionLike[A]: BaseOptionLike[Option[A], A] =
new OptionLikeImpl(None, Some(_), _.isDefined, _.get, ignoreNulls = true)

implicit def optOptionLike[A]: BaseOptionLike[Opt[A], A] =
given optOptionLike[A]: BaseOptionLike[Opt[A], A] =
new OptionLikeImpl(Opt.Empty, Opt.some, _.isDefined, _.get, ignoreNulls = true)

implicit def optRefOptionLike[A >: Null]: BaseOptionLike[OptRef[A], A] =
given optRefOptionLike[A >: Null]: BaseOptionLike[OptRef[A], A] =
new OptionLikeImpl(OptRef.Empty, OptRef.some, _.isDefined, _.get, ignoreNulls = true)

implicit def optArgOptionLike[A]: BaseOptionLike[OptArg[A], A] =
given optArgOptionLike[A]: BaseOptionLike[OptArg[A], A] =
new OptionLikeImpl(OptArg.Empty, OptArg.some, _.isDefined, _.get, ignoreNulls = true)

implicit def nOptOptionLike[A]: BaseOptionLike[NOpt[A], A] =
given nOptOptionLike[A]: BaseOptionLike[NOpt[A], A] =
new OptionLikeImpl(NOpt.Empty, NOpt.some, _.isDefined, _.get, ignoreNulls = false)
}

Expand All @@ -82,8 +82,6 @@ object AutoOptionalParam {
}

trait AutoOptionalParams {
implicit def allAutoOptionalParams[T](
implicit optionLike: OptionLike[T]
): AutoOptionalParam[T] = AutoOptionalParam[T]
given allAutoOptionalParams[T](using optionLike: OptionLike[T]): AutoOptionalParam[T] = AutoOptionalParam[T]
}
object AutoOptionalParams extends AutoOptionalParams
14 changes: 7 additions & 7 deletions core/src/main/scala/com/avsystem/commons/misc/AnnotationOf.scala
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import scala.annotation.implicitNotFound
case class AnnotationOf[A, T](annot: A) extends AnyVal
object AnnotationOf {
// TODO[scala3-port]: AnnotationOf.materialize (Scala 2 macro def) (L)
implicit def materialize[A, T]: AnnotationOf[A, T] = ???
given materialize[A, T]: AnnotationOf[A, T] = ???
}

/** A typeclass which captures a possible annotation of type `A` applied on a class/trait/object associated with type
Expand All @@ -20,7 +20,7 @@ object AnnotationOf {
case class OptAnnotationOf[A, T](annotOpt: Opt[A])
object OptAnnotationOf {
// TODO[scala3-port]: OptAnnotationOf.materialize (Scala 2 macro def) (L)
implicit def materialize[A, T]: OptAnnotationOf[A, T] = ???
given materialize[A, T]: OptAnnotationOf[A, T] = ???
}

/** A typeclass which captures all annotations of type `A` applied on a class/trait/object associated with type `T`.
Expand All @@ -29,7 +29,7 @@ object OptAnnotationOf {
case class AnnotationsOf[A, T](annots: List[A]) extends AnyVal
object AnnotationsOf {
// TODO[scala3-port]: AnnotationsOf.materialize (Scala 2 macro def) (L)
implicit def materialize[A, T]: AnnotationsOf[A, T] = ???
given materialize[A, T]: AnnotationsOf[A, T] = ???
}

/** A typeclass which serves as an evidence that an annotation of type `A` is applied on a class/trait/object associated
Expand All @@ -44,7 +44,7 @@ object HasAnnotation {
def create[A, T]: HasAnnotation[A, T] = reusable.asInstanceOf[HasAnnotation[A, T]]

// TODO[scala3-port]: HasAnnotation.materialize (Scala 2 macro def) (L)
implicit def materialize[A, T]: HasAnnotation[A, T] = ???
given materialize[A, T]: HasAnnotation[A, T] = ???
}

/** A typeclass which may be used in an implicit constructor parameter of an abstract class. Captures an annotation of
Expand All @@ -67,7 +67,7 @@ object HasAnnotation {
case class SelfAnnotation[A](annot: A) extends AnyVal
object SelfAnnotation {
// TODO[scala3-port]: SelfAnnotation.materialize (Scala 2 macro def) (L)
implicit def materialize[A]: SelfAnnotation[A] = ???
given materialize[A]: SelfAnnotation[A] = ???
}

/** A typeclass which may be used in an implicit constructor parameter of an abstract class. Captures a possible
Expand All @@ -90,7 +90,7 @@ object SelfAnnotation {
case class SelfOptAnnotation[A](annotOpt: Opt[A])
object SelfOptAnnotation {
// TODO[scala3-port]: SelfOptAnnotation.materialize (Scala 2 macro def) (L)
implicit def materialize[A]: SelfOptAnnotation[A] = ???
given materialize[A]: SelfOptAnnotation[A] = ???
}

/** A typeclass which may be used in an implicit constructor parameter of an abstract class. Captures all annotations of
Expand All @@ -112,5 +112,5 @@ object SelfOptAnnotation {
case class SelfAnnotations[A](annots: List[A]) extends AnyVal
object SelfAnnotations {
// TODO[scala3-port]: SelfAnnotations.materialize (Scala 2 macro def) (L)
implicit def materialize[A]: SelfAnnotations[A] = ???
given materialize[A]: SelfAnnotations[A] = ???
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ trait Applier[T] {
}
object Applier {
// TODO[scala3-port]: Applier.materialize (Scala 2 macro def) (L)
implicit def materialize[T]: Applier[T] = ???
given materialize[T]: Applier[T] = ???
}

/** Typeclass which captures case class `unapply`/`unapplySeq` method in a raw form that returns untyped sequence of
Expand All @@ -23,7 +23,7 @@ trait Unapplier[T] {
}
object Unapplier {
// TODO[scala3-port]: Unapplier.materialize (Scala 2 macro def) (L)
implicit def materialize[T]: Unapplier[T] = ???
given materialize[T]: Unapplier[T] = ???
}

class ProductUnapplier[T <: Product] extends Unapplier[T] {
Expand All @@ -35,5 +35,5 @@ abstract class ProductApplierUnapplier[T <: Product] extends ProductUnapplier[T]
trait ApplierUnapplier[T] extends Applier[T] with Unapplier[T]
object ApplierUnapplier {
// TODO[scala3-port]: ApplierUnapplier.materialize (Scala 2 macro def) (L)
implicit def materialize[T]: ApplierUnapplier[T] = ???
given materialize[T]: ApplierUnapplier[T] = ???
}
Loading
Loading