From 00dcf50b621524b1ab8f08f90fe1a12dec7a0064 Mon Sep 17 00:00:00 2001 From: Matt Dziuban Date: Mon, 12 Jun 2023 17:58:03 -0400 Subject: [PATCH] Remove shapeless dependency in scala 3. --- build.sbt | 6 +++- .../eu/timepit/refined/api/RefType.scala | 13 --------- .../eu/timepit/refined/boolean.scala | 29 +++++++++---------- .../eu/timepit/refined/collection.scala | 8 ++--- .../eu/timepit/refined/internal/ToInt.scala | 14 ++++----- .../timepit/refined/internal/WitnessAs.scala | 5 ++-- .../eu/timepit/refined/numeric.scala | 18 +++++------- .../eu/timepit/refined/package.scala | 9 ------ .../eu/timepit/refined/types/string.scala | 3 +- .../pureconfig/RefTypeConfigConvertSpec.scala | 4 +-- 10 files changed, 42 insertions(+), 67 deletions(-) diff --git a/build.sbt b/build.sbt index 54b77fa0a..3ae882288 100644 --- a/build.sbt +++ b/build.sbt @@ -173,8 +173,12 @@ lazy val core = myCrossProject("core") scalaOrganization.value % "scala-reflect" % scalaVersion.value, scalaOrganization.value % "scala-compiler" % scalaVersion.value ) + ) ++ ( + if (isScala3Setting.value) + Seq() + else + Seq("com.chuusai" %%% "shapeless" % shapelessVersion) ) ++ Seq( - ("com.chuusai" %%% "shapeless" % shapelessVersion).cross(CrossVersion.for3Use2_13), "org.scalacheck" %%% "scalacheck" % scalaCheckVersion % Test ) }, diff --git a/modules/core/shared/src/main/scala-3.0+/eu/timepit/refined/api/RefType.scala b/modules/core/shared/src/main/scala-3.0+/eu/timepit/refined/api/RefType.scala index 0861ff0dd..43be576e7 100644 --- a/modules/core/shared/src/main/scala-3.0+/eu/timepit/refined/api/RefType.scala +++ b/modules/core/shared/src/main/scala-3.0+/eu/timepit/refined/api/RefType.scala @@ -1,7 +1,6 @@ package eu.timepit.refined.api import eu.timepit.refined.internal._ -import shapeless.tag.@@ /** * Type class that allows `F` to be used as carrier type of a refinement. @@ -92,18 +91,6 @@ object RefType { Refined.unsafeApply(ta.value) } - implicit val tagRefType: RefType[@@] = - new RefType[@@] { - override def unsafeWrap[T, P](t: T): T @@ P = - t.asInstanceOf[T @@ P] - - override def unwrap[T, P](tp: T @@ P): T = - tp - - override def unsafeRewrap[T, A, B](ta: T @@ A): T @@ B = - ta.asInstanceOf[T @@ B] - } - final class RefTypeOps[F[_, _], T, P](tp: F[T, P])(implicit F: RefType[F]) { def unwrap: T = F.unwrap(tp) diff --git a/modules/core/shared/src/main/scala-3.0+/eu/timepit/refined/boolean.scala b/modules/core/shared/src/main/scala-3.0+/eu/timepit/refined/boolean.scala index 1e766195f..2f3529fbc 100644 --- a/modules/core/shared/src/main/scala-3.0+/eu/timepit/refined/boolean.scala +++ b/modules/core/shared/src/main/scala-3.0+/eu/timepit/refined/boolean.scala @@ -4,7 +4,6 @@ import eu.timepit.refined.api._ import eu.timepit.refined.api.Inference.==> import eu.timepit.refined.boolean._ import eu.timepit.refined.internal.Resources -import shapeless.{::, HList, HNil} /** Module for logical predicates. */ object boolean extends BooleanInference0 { @@ -178,20 +177,20 @@ object boolean extends BooleanInference0 { } object AllOf { - implicit def allOfHNilValidate[T]: Validate.Plain[T, AllOf[HNil]] = - Validate.alwaysPassed(AllOf(HList())) + implicit def allOfEmptyTupleValidate[T]: Validate.Plain[T, AllOf[EmptyTuple]] = + Validate.alwaysPassed(AllOf(EmptyTuple)) - implicit def allOfHConsValidate[T, PH, RH, PT <: HList, RT <: HList](implicit + implicit def allOfTupleConsValidate[T, PH, RH, PT <: Tuple, RT <: Tuple](implicit vh: Validate.Aux[T, PH, RH], vt: Validate.Aux[T, AllOf[PT], AllOf[RT]] - ): Validate.Aux[T, AllOf[PH :: PT], AllOf[vh.Res :: RT]] = - new Validate[T, AllOf[PH :: PT]] { - override type R = AllOf[vh.Res :: RT] + ): Validate.Aux[T, AllOf[PH *: PT], AllOf[vh.Res *: RT]] = + new Validate[T, AllOf[PH *: PT]] { + override type R = AllOf[vh.Res *: RT] override def validate(t: T): Res = { val rh = vh.validate(t) val rt = vt.validate(t) - Result.fromBoolean(rh.isPassed && rt.isPassed, AllOf(rh :: rt.detail.ps)) + Result.fromBoolean(rh.isPassed && rt.isPassed, AllOf(rh *: rt.detail.ps)) } override def showExpr(t: T): String = @@ -203,20 +202,20 @@ object boolean extends BooleanInference0 { } object AnyOf { - implicit def anyOfHNilValidate[T]: Validate.Plain[T, AnyOf[HNil]] = - Validate.alwaysFailed(AnyOf(HList())) + implicit def anyOfEmptyTupleValidate[T]: Validate.Plain[T, AnyOf[EmptyTuple]] = + Validate.alwaysFailed(AnyOf(EmptyTuple)) - implicit def anyOfHConsValidate[T, PH, RH, PT <: HList, RT <: HList](implicit + implicit def anyOfHConsValidate[T, PH, RH, PT <: Tuple, RT <: Tuple](implicit vh: Validate.Aux[T, PH, RH], vt: Validate.Aux[T, AnyOf[PT], AnyOf[RT]] - ): Validate.Aux[T, AnyOf[PH :: PT], AnyOf[vh.Res :: RT]] = - new Validate[T, AnyOf[PH :: PT]] { - override type R = AnyOf[vh.Res :: RT] + ): Validate.Aux[T, AnyOf[PH *: PT], AnyOf[vh.Res *: RT]] = + new Validate[T, AnyOf[PH *: PT]] { + override type R = AnyOf[vh.Res *: RT] override def validate(t: T): Res = { val rh = vh.validate(t) val rt = vt.validate(t) - Result.fromBoolean(rh.isPassed || rt.isPassed, AnyOf(rh :: rt.detail.ps)) + Result.fromBoolean(rh.isPassed || rt.isPassed, AnyOf(rh *: rt.detail.ps)) } override def showExpr(t: T): String = diff --git a/modules/core/shared/src/main/scala-3.0+/eu/timepit/refined/collection.scala b/modules/core/shared/src/main/scala-3.0+/eu/timepit/refined/collection.scala index d7beae2db..b55788c97 100644 --- a/modules/core/shared/src/main/scala-3.0+/eu/timepit/refined/collection.scala +++ b/modules/core/shared/src/main/scala-3.0+/eu/timepit/refined/collection.scala @@ -7,8 +7,6 @@ import eu.timepit.refined.collection._ import eu.timepit.refined.generic.Equal import eu.timepit.refined.internal.Resources import eu.timepit.refined.numeric.{GreaterEqual, Interval} -import shapeless.Witness -import shapeless.nat.{_0, _1} /** Module for collection predicates. */ object collection extends CollectionInference { @@ -87,7 +85,7 @@ object collection extends CollectionInference { * Predicate that checks if the size of an `Iterable` is less than * or equal to `N`. */ - type MaxSize[N] = Size[Interval.Closed[_0, N]] + type MaxSize[N] = Size[Interval.Closed[0, N]] /** Predicate that checks if an `Iterable` is not empty. */ type NonEmpty = Not[Empty] @@ -179,7 +177,7 @@ object collection extends CollectionInference { implicit def indexValidate[A, P, R, N <: Int, T](implicit v: Validate.Aux[A, P, R], ev: T => PartialFunction[Int, A], - wn: Witness.Aux[N] + wn: ValueOf[N] ): Validate.Aux[T, Index[N, P], Index[N, Option[v.Res]]] = new Validate[T, Index[N, P]] { override type R = Index[N, Option[v.Res]] @@ -344,7 +342,7 @@ private[refined] trait CollectionInference { p1.adapt("sizeInference(%s)") implicit def sizeGreaterEqual1NonEmptyInference[A](implicit - p1: A ==> GreaterEqual[_1] + p1: A ==> GreaterEqual[1] ): Size[A] ==> NonEmpty = p1.adapt("sizeGreaterEqual1NonEmptyInference(%s)") } diff --git a/modules/core/shared/src/main/scala-3.0+/eu/timepit/refined/internal/ToInt.scala b/modules/core/shared/src/main/scala-3.0+/eu/timepit/refined/internal/ToInt.scala index 0a8a9d600..ba16e3046 100644 --- a/modules/core/shared/src/main/scala-3.0+/eu/timepit/refined/internal/ToInt.scala +++ b/modules/core/shared/src/main/scala-3.0+/eu/timepit/refined/internal/ToInt.scala @@ -1,21 +1,21 @@ package eu.timepit.refined.internal import scala.compiletime.erasedValue -import shapeless.{_0, Nat, Succ} +import scala.compiletime.ops.int.S -trait ToInt[N <: Nat] { +trait ToInt[N <: Int] { def apply(): Int } object ToInt { - def apply[N <: Nat](implicit toInt: ToInt[N]): ToInt[N] = toInt + def apply[N <: Int](implicit toInt: ToInt[N]): ToInt[N] = toInt - inline implicit def materialize[N <: Nat]: ToInt[N] = + inline implicit def materialize[N <: Int]: ToInt[N] = new ToInt[N] { override def apply(): Int = toInt[N] } - private inline def toInt[N <: Nat]: Int = + private inline def toInt[N <: Int]: Int = inline erasedValue[N] match { - case _: _0 => 0 - case _: Succ[n] => toInt[n] + 1 + case _: 0 => 0 + case _: S[n] => toInt[n] + 1 } } diff --git a/modules/core/shared/src/main/scala-3.0+/eu/timepit/refined/internal/WitnessAs.scala b/modules/core/shared/src/main/scala-3.0+/eu/timepit/refined/internal/WitnessAs.scala index 03ca6dea2..39dfc0a04 100644 --- a/modules/core/shared/src/main/scala-3.0+/eu/timepit/refined/internal/WitnessAs.scala +++ b/modules/core/shared/src/main/scala-3.0+/eu/timepit/refined/internal/WitnessAs.scala @@ -1,7 +1,6 @@ package eu.timepit.refined.internal import scala.compiletime.{constValue, error} -import shapeless.{Nat, Witness} /** * `WitnessAs[A, B]` provides the singleton value of type `A` in `fst` @@ -28,8 +27,8 @@ final case class WitnessAs[A, B](fst: A, snd: B) object WitnessAs extends WitnessAs1 { def apply[A, B](implicit ev: WitnessAs[A, B]): WitnessAs[A, B] = ev - implicit def natWitnessAs[B, A <: Nat](implicit - wa: Witness.Aux[A], + implicit def intWitnessAs[B, A <: Int](implicit + wa: ValueOf[A], ta: ToInt[A], nb: Numeric[B] ): WitnessAs[A, B] = diff --git a/modules/core/shared/src/main/scala-3.0+/eu/timepit/refined/numeric.scala b/modules/core/shared/src/main/scala-3.0+/eu/timepit/refined/numeric.scala index c4c10337d..b3eddb80d 100644 --- a/modules/core/shared/src/main/scala-3.0+/eu/timepit/refined/numeric.scala +++ b/modules/core/shared/src/main/scala-3.0+/eu/timepit/refined/numeric.scala @@ -6,8 +6,6 @@ import eu.timepit.refined.boolean.{And, Not} import eu.timepit.refined.internal.ToInt import eu.timepit.refined.internal.WitnessAs import eu.timepit.refined.numeric._ -import shapeless.Nat -import shapeless.nat.{_0, _2} /** * Module for numeric predicates. @@ -50,25 +48,25 @@ object numeric extends NumericInference { type GreaterEqual[N] = Not[Less[N]] /** Predicate that checks if a numeric value is positive (> 0). */ - type Positive = Greater[_0] + type Positive = Greater[0] /** Predicate that checks if a numeric value is zero or negative (<= 0). */ type NonPositive = Not[Positive] /** Predicate that checks if a numeric value is negative (< 0). */ - type Negative = Less[_0] + type Negative = Less[0] /** Predicate that checks if a numeric value is zero or positive (>= 0). */ type NonNegative = Not[Negative] /** Predicate that checks if an integral value is evenly divisible by `N`. */ - type Divisible[N] = Modulo[N, _0] + type Divisible[N] = Modulo[N, 0] /** Predicate that checks if an integral value is not evenly divisible by `N`. */ type NonDivisible[N] = Not[Divisible[N]] /** Predicate that checks if an integral value is evenly divisible by 2. */ - type Even = Divisible[_2] + type Even = Divisible[2] /** Predicate that checks if an integral value is not evenly divisible by 2. */ type Odd = Not[Even] @@ -135,11 +133,11 @@ private[refined] trait NumericInference { ): Less[A] ==> Less[B] = Inference(nc.lt(wa.snd, wb.snd), s"lessInference(${wa.snd}, ${wb.snd})") - implicit def lessInferenceNat[A <: Nat, B <: Nat](implicit + implicit def lessInferenceInt[A <: Int, B <: Int](implicit ta: ToInt[A], tb: ToInt[B] ): Less[A] ==> Less[B] = - Inference(ta() < tb(), s"lessInferenceNat(${ta()}, ${tb()})") + Inference(ta() < tb(), s"lessInferenceInt(${ta()}, ${tb()})") implicit def greaterInference[C, A, B](implicit wa: WitnessAs[A, C], @@ -148,11 +146,11 @@ private[refined] trait NumericInference { ): Greater[A] ==> Greater[B] = Inference(nc.gt(wa.snd, wb.snd), s"greaterInference(${wa.snd}, ${wb.snd})") - implicit def greaterInferenceNat[A <: Nat, B <: Nat](implicit + implicit def greaterInferenceNat[A <: Int, B <: Int](implicit ta: ToInt[A], tb: ToInt[B] ): Greater[A] ==> Greater[B] = - Inference(ta() > tb(), s"greaterInferenceNat(${ta()}, ${tb()})") + Inference(ta() > tb(), s"greaterInferenceInt(${ta()}, ${tb()})") implicit def greaterEqualInference[A]: Greater[A] ==> GreaterEqual[A] = Inference.alwaysValid("greaterEqualInference") diff --git a/modules/core/shared/src/main/scala-3.0+/eu/timepit/refined/package.scala b/modules/core/shared/src/main/scala-3.0+/eu/timepit/refined/package.scala index f8f8187fe..4ac4be621 100644 --- a/modules/core/shared/src/main/scala-3.0+/eu/timepit/refined/package.scala +++ b/modules/core/shared/src/main/scala-3.0+/eu/timepit/refined/package.scala @@ -2,7 +2,6 @@ package eu.timepit import eu.timepit.refined.api.{Refined, RefType} import eu.timepit.refined.internal._ -import shapeless.tag.@@ package object refined { @@ -13,12 +12,4 @@ package object refined { * Note: `V` stands for '''v'''alue class. */ def refineV[P]: RefinePartiallyApplied[Refined, P] = RefType.refinedRefType.refine[P] - - /** - * Alias for `[[api.RefType.refine]][P]` with `shapeless.tag.@@` as type - * parameter for `[[api.RefType]]`. - * - * Note: `T` stands for '''t'''ag. - */ - def refineT[P]: RefinePartiallyApplied[@@, P] = RefType.tagRefType.refine[P] } diff --git a/modules/core/shared/src/main/scala-3.0+/eu/timepit/refined/types/string.scala b/modules/core/shared/src/main/scala-3.0+/eu/timepit/refined/types/string.scala index 025fd281f..5b678caf8 100644 --- a/modules/core/shared/src/main/scala-3.0+/eu/timepit/refined/types/string.scala +++ b/modules/core/shared/src/main/scala-3.0+/eu/timepit/refined/types/string.scala @@ -4,7 +4,6 @@ import eu.timepit.refined.api.{Refined, RefinedType, RefinedTypeOps} import eu.timepit.refined.collection.{MaxSize, NonEmpty, Size} import eu.timepit.refined.numeric.Interval import eu.timepit.refined.string.{HexStringSpec, Trimmed} -import shapeless.Nat._1 /** Module for `String` refined types. */ object string { @@ -59,7 +58,7 @@ object string { object NonEmptyString extends RefinedTypeOps[NonEmptyString, String] /** A `String` that is not empty with length less than or equal to `N`. */ - type NonEmptyFiniteString[N] = String Refined Size[Interval.Closed[_1, N]] + type NonEmptyFiniteString[N] = String Refined Size[Interval.Closed[1, N]] object NonEmptyFiniteString { class NonEmptyFiniteStringOps[N <: Int](implicit diff --git a/modules/pureconfig/shared/src/test/scala/eu/timepit/refined/pureconfig/RefTypeConfigConvertSpec.scala b/modules/pureconfig/shared/src/test/scala/eu/timepit/refined/pureconfig/RefTypeConfigConvertSpec.scala index d44b55ff1..06ce1475a 100644 --- a/modules/pureconfig/shared/src/test/scala/eu/timepit/refined/pureconfig/RefTypeConfigConvertSpec.scala +++ b/modules/pureconfig/shared/src/test/scala/eu/timepit/refined/pureconfig/RefTypeConfigConvertSpec.scala @@ -72,10 +72,10 @@ class RefTypeConfigConvertSpec extends Properties("RefTypeConfigConvert") { // scala 3 macro provide type representation in this way val expected3 = expectedFailure( - "eu.timepit.refined.api.Refined[scala.Int, eu.timepit.refined.numeric.Greater[shapeless.nat._0]]" + "eu.timepit.refined.api.Refined[scala.Int, eu.timepit.refined.numeric.Greater[0]]" ) val expected4 = expectedFailure( - s"eu.timepit.refined.api.Refined$$package.Refined[scala.Int, eu.timepit.refined.numeric.Greater[shapeless.nat._0]]" + s"eu.timepit.refined.api.Refined$$package.Refined[scala.Int, eu.timepit.refined.numeric.Greater[0]]" ) val actual = loadConfigWithValue("0")