From 13266ee7327b81616110c6f8fc2d7b6b1de55099 Mon Sep 17 00:00:00 2001 From: Georgi Krastev Date: Fri, 10 Apr 2020 14:53:47 +0200 Subject: [PATCH 01/17] Switch DefaultSymbolicLabelling from Symbol to String --- .../test/scala/shapeless/serialization.scala | 4 +- core/src/main/scala/shapeless/default.scala | 45 +++--- core/src/main/scala/shapeless/generic.scala | 9 +- core/src/main/scala/shapeless/labelled.scala | 87 +++++------ core/src/main/scala/shapeless/lenses.scala | 29 ++-- .../main/scala/shapeless/ops/records.scala | 13 +- core/src/main/scala/shapeless/records.scala | 56 +++---- .../src/main/scala/shapeless/singletons.scala | 21 +-- .../main/scala/shapeless/syntax/records.scala | 3 +- .../main/scala/shapeless/syntax/unions.scala | 3 +- core/src/main/scala/shapeless/typeclass.scala | 108 ++++++------- core/src/main/scala/shapeless/unions.scala | 32 ++-- core/src/test/scala/shapeless/default.scala | 4 +- core/src/test/scala/shapeless/hlist.scala | 2 +- core/src/test/scala/shapeless/implicits.scala | 4 +- .../scala/shapeless/labelledgeneric.scala | 143 ++++++++---------- core/src/test/scala/shapeless/lenses.scala | 12 +- core/src/test/scala/shapeless/product.scala | 10 +- core/src/test/scala/shapeless/records.scala | 123 +++++++-------- .../src/test/scala/shapeless/singletons.scala | 34 +++-- core/src/test/scala/shapeless/unions.scala | 64 ++++---- .../scala/shapeless/examples/derivation.scala | 85 ++++------- .../shapeless/examples/labelledgeneric.scala | 10 +- .../scala/shapeless/examples/partition.scala | 10 +- .../shapeless/examples/recordsubtyping.scala | 10 +- .../shapeless/examples/recursionschemes.scala | 9 +- .../main/scala/shapeless/examples/sexp.scala | 109 ++++++------- .../scala/shapeless/examples/unwrapped.scala | 105 ++++++------- 28 files changed, 509 insertions(+), 635 deletions(-) diff --git a/core/jvm/src/test/scala/shapeless/serialization.scala b/core/jvm/src/test/scala/shapeless/serialization.scala index 1ce87c24d..ab7f9e9f6 100644 --- a/core/jvm/src/test/scala/shapeless/serialization.scala +++ b/core/jvm/src/test/scala/shapeless/serialization.scala @@ -312,7 +312,7 @@ class SerializationTests { val r = Symbol("foo") ->> 23 :: Symbol("bar") ->> "foo" :: Symbol("baz") ->> true :: HNil - type U = Union.`'foo -> Int, 'bar -> String, 'baz -> Boolean`.T + type U = Union.`"foo" -> Int, "bar" -> String, "baz" -> Boolean`.T val u = Union[U](bar = "quux") val t = (23, "foo", true) @@ -1192,7 +1192,7 @@ class SerializationTests { val l10 = optic.hlistNthLens[Int :: String :: Boolean :: HNil, _1] val l11 = optic.recordLens[Record.`'foo -> Int, 'bar -> String, 'baz -> Boolean`.T](Symbol("bar")) val l12 = optic[Tree[Int]].l.r.l.t - val l13 = optic[Node[Int]] >> Symbol("r") + val l13 = optic[Node[Int]] >> "r" val l14 = optic[Node[Int]] >> _1 assertSerializable(l1) diff --git a/core/src/main/scala/shapeless/default.scala b/core/src/main/scala/shapeless/default.scala index 9fed9a118..a1dbcaa04 100644 --- a/core/src/main/scala/shapeless/default.scala +++ b/core/src/main/scala/shapeless/default.scala @@ -69,7 +69,7 @@ object Default { * * val default = Default.AsRecord[CC] * - * // default.Out is Record.`'s -> String`.T + * // default.Out is Record.`"s" -> String`.T * // default() returns Record(s = "b") * }}} * @@ -93,41 +93,38 @@ object Default { type Aux[L <: HList, Labels <: HList, Out0 <: HList] = Helper[L, Labels] { type Out = Out0 } - implicit def hnilHelper: Aux[HNil, HNil, HNil] = + implicit val hnilHelper: Aux[HNil, HNil, HNil] = new Helper[HNil, HNil] { type Out = HNil def apply(l: HNil) = HNil } - implicit def hconsSomeHelper[K <: Symbol, H, T <: HList, LabT <: HList, OutT <: HList] - (implicit - tailHelper: Aux[T, LabT, OutT] - ): Aux[Some[H] :: T, K :: LabT, FieldType[K, H] :: OutT] = + implicit def hconsSomeHelper[K, H, T <: HList, LabT <: HList]( + implicit tailHelper: Helper[T, LabT] + ): Aux[Some[H] :: T, K :: LabT, FieldType[K, H] :: tailHelper.Out] = new Helper[Some[H] :: T, K :: LabT] { - type Out = FieldType[K, H] :: OutT - def apply(l: Some[H] :: T) = field[K](l.head.get) :: tailHelper(l.tail) + type Out = FieldType[K, H] :: tailHelper.Out + def apply(l: Some[H] :: T): Out = field[K](l.head.get) :: tailHelper(l.tail) } - implicit def hconsNoneHelper[K <: Symbol, T <: HList, LabT <: HList, OutT <: HList] - (implicit - tailHelper: Aux[T, LabT, OutT] - ): Aux[None.type :: T, K :: LabT, OutT] = + implicit def hconsNoneHelper[K, T <: HList, LabT <: HList]( + implicit tailHelper: Helper[T, LabT] + ): Aux[None.type :: T, K :: LabT, tailHelper.Out] = new Helper[None.type :: T, K :: LabT] { - type Out = OutT - def apply(l: None.type :: T) = tailHelper(l.tail) + type Out = tailHelper.Out + def apply(l: None.type :: T): Out = tailHelper(l.tail) } } - implicit def asRecord[T, Labels <: HList, Options <: HList, Rec <: HList] - (implicit - default: Default.Aux[T, Options], - labelling: DefaultSymbolicLabelling.Aux[T, Labels], - helper: Helper.Aux[Options, Labels, Rec] - ): Aux[T, Rec] = - new AsRecord[T] { - type Out = Rec - def apply() = helper(default()) - } + implicit def asRecord[T, Labels <: HList, Options <: HList]( + implicit + default: Default.Aux[T, Options], + labelling: DefaultSymbolicLabelling.Aux[T, Labels], + helper: Helper[Options, Labels] + ): Aux[T, helper.Out] = new AsRecord[T] { + type Out = helper.Out + def apply(): Out = helper(default()) + } } diff --git a/core/src/main/scala/shapeless/generic.scala b/core/src/main/scala/shapeless/generic.scala index 0bceeba52..612c49ce6 100644 --- a/core/src/main/scala/shapeless/generic.scala +++ b/core/src/main/scala/shapeless/generic.scala @@ -482,11 +482,14 @@ trait CaseClassMacros extends ReprTypes with CaseClassMacrosVersionSpecifics { abort(s"$tpe is not a case class, case class-like, a sealed trait or Unit") } - def nameAsString(name: Name): String = name.decodedName.toString.trim + def nameAsString(name: Name): String = + name.decodedName.toString.trim - def nameAsValue(name: Name): Constant = Constant(nameAsString(name)) + def nameAsValue(name: Name): Constant = + Constant(nameAsString(name)) - def nameOf(tpe: Type) = tpe.typeSymbol.name + def nameOf(tpe: Type): Name = + tpe.typeSymbol.name def mkHListValue(elems: List[Tree]): Tree = elems.foldRight(q"_root_.shapeless.HNil": Tree) { diff --git a/core/src/main/scala/shapeless/labelled.scala b/core/src/main/scala/shapeless/labelled.scala index 1d0416296..8b94856c3 100644 --- a/core/src/main/scala/shapeless/labelled.scala +++ b/core/src/main/scala/shapeless/labelled.scala @@ -93,22 +93,30 @@ trait FieldOf[V] { @macrocompat.bundle class LabelledMacros(val c: whitebox.Context) extends SingletonTypeUtils with CaseClassMacros { import c.universe._ + import internal.constantType - def mkDefaultSymbolicLabellingImpl[T](implicit tTag: WeakTypeTag[T]): Tree = { - val tTpe = weakTypeOf[T] - val labels: List[String] = - if (isProduct(tTpe)) fieldsOf(tTpe).map(f => nameAsString(f._1)) - else if (isCoproduct(tTpe)) ctorsOf(tTpe).map(tpe => nameAsString(nameOf(tpe))) - else c.abort(c.enclosingPosition, s"$tTpe is not case class like or the root of a sealed family of types") + private def commaSeparated(str: String): Array[String] = { + val trimmed = str.trim + if (trimmed.isEmpty) Array.empty else trimmed.split(',') + } + + private def parseTypeOrFail(tpe: String): Type = + parseType(tpe.trim).getOrElse(c.abort(c.enclosingPosition, s"Malformed literal or standard type $tpe")) - val labelTpes = labels.map(SingletonSymbolType(_)) - val labelValues = labels.map(mkSingletonSymbol) + private def parseLiteralTypeOrFail(tpe: String): Type = + parseLiteralType(tpe.trim).getOrElse(c.abort(c.enclosingPosition, s"Malformed literal type $tpe")) - val labelsTpe = mkHListTpe(labelTpes) - val labelsValue = mkHListValue(labelValues) + def mkDefaultSymbolicLabellingImpl[T: WeakTypeTag]: Tree = { + val tpe = weakTypeOf[T] + val labels: List[Constant] = + if (isProduct(tpe)) fieldsOf(tpe).map(f => nameAsValue(f._1)) + else if (isCoproduct(tpe)) ctorsOf(tpe).map(c => nameAsValue(nameOf(c))) + else c.abort(c.enclosingPosition, s"$tpe is not case class like or the root of a sealed family of types") - val defaultSymbolicLabelling = objectRef[DefaultSymbolicLabelling.type] - q"$defaultSymbolicLabelling.instance[$tTpe, $labelsTpe]($labelsValue)" + val labelsType = mkHListTpe(labels.map(constantType)) + val labelsValue = mkHListValue(labels.map(Literal.apply)) + val labelling = objectRef[DefaultSymbolicLabelling.type] + q"$labelling.instance[$tpe, $labelsType]($labelsValue.asInstanceOf[$labelsType])" } def recordTypeImpl(tpeSelector: Tree): Tree = @@ -122,56 +130,29 @@ class LabelledMacros(val c: whitebox.Context) extends SingletonTypeUtils with Ca appliedType(fieldTypeTpe, List(keyTpe, valueTpe)) val q"${tpeString: String}" = tpeSelector - val fields = - if (tpeString.trim.isEmpty) - Array.empty[(Type, Type)] - else - tpeString.split(",").map(_.trim).map(_.split("->").map(_.trim)).map { - case Array(key, value) => - val keyTpe = - parseLiteralType(key) - .getOrElse(c.abort(c.enclosingPosition, s"Malformed literal type $key")) - - val valueTpe = - parseType(value) - .getOrElse(c.abort(c.enclosingPosition, s"Malformed literal or standard type $value")) - - (keyTpe, valueTpe) - - case _ => - c.abort(c.enclosingPosition, s"Malformed $variety type $tpeString") - } - - val labelledTpe = - fields.foldRight(nilTpe) { case ((keyTpe, valueTpe), acc) => - val fieldTpe = mkFieldTpe(keyTpe, valueTpe) - appliedType(consTpe, List(fieldTpe, acc)) - } + val fields = commaSeparated(tpeString).map(_.trim.split("->") match { + case Array(key, value) => (parseLiteralTypeOrFail(key), parseTypeOrFail(value)) + case _ => c.abort(c.enclosingPosition, s"Malformed $variety type $tpeString") + }) + + val labelledTpe = fields.foldRight(nilTpe) { case ((key, value), acc) => + appliedType(consTpe, List(mkFieldTpe(key, value), acc)) + } typeCarrier(labelledTpe) } def hlistTypeImpl(tpeSelector: Tree): Tree = - nonLabelledTypeImpl(tpeSelector, "hlist", hnilTpe, hconsTpe) + nonLabelledTypeImpl(tpeSelector, hnilTpe, hconsTpe) def coproductTypeImpl(tpeSelector: Tree): Tree = - nonLabelledTypeImpl(tpeSelector, "coproduct", cnilTpe, cconsTpe) + nonLabelledTypeImpl(tpeSelector, cnilTpe, cconsTpe) - def nonLabelledTypeImpl(tpeSelector: Tree, variety: String, nilTpe: Type, consTpe: Type): Tree = { + def nonLabelledTypeImpl(tpeSelector: Tree, nilTpe: Type, consTpe: Type): Tree = { val q"${tpeString: String}" = tpeSelector - val elemTypes = - if (tpeString.trim.isEmpty) - Array.empty[Type] - else - tpeString.split(",").map(_.trim).map { elemTypeStr => - parseType(elemTypeStr) - .getOrElse(c.abort(c.enclosingPosition, s"Malformed literal or standard type $elemTypeStr")) - } - - val tpe = - elemTypes.foldRight(nilTpe) { case (elemTpe, acc) => - appliedType(consTpe, List(elemTpe, acc)) - } + val tpe = commaSeparated(tpeString).foldRight(nilTpe) { case (element, acc) => + appliedType(consTpe, List(parseTypeOrFail(element), acc)) + } typeCarrier(tpe) } diff --git a/core/src/main/scala/shapeless/lenses.scala b/core/src/main/scala/shapeless/lenses.scala index 531c4a908..4427de7b2 100644 --- a/core/src/main/scala/shapeless/lenses.scala +++ b/core/src/main/scala/shapeless/lenses.scala @@ -22,7 +22,6 @@ import labelled.{ FieldType, field } import ops.coproduct.{ Inject, Selector => CSelector } import ops.hlist.{ At, Init, Last, Prepend, Selector, ReplaceAt, Replacer, Tupler } import ops.record.{ Selector => RSelector, Updater } -import tag.@@ trait Lens[S, A] extends LPLens[S, A] { outer => def get(s: S): A @@ -43,8 +42,9 @@ trait Lens[S, A] extends LPLens[S, A] { outer => def >>(k: Witness)(implicit mkLens: MkFieldLens[A, k.T]): Lens[S, mkLens.Elem] = mkLens() compose this - def selectDynamic(k: String) - (implicit mkLens: MkSelectDynamicOptic[Lens[S, A], A, Symbol @@ k.type, Nothing]): mkLens.Out = mkLens(this) + def selectDynamic(k: String)( + implicit mkLens: MkSelectDynamicOptic[Lens[S, A], A, k.type, Nothing] + ): mkLens.Out = mkLens(this) def apply[B](implicit mkPrism: MkCtorPrism[A, B]): Prism[S, B] = mkPrism() compose this @@ -62,8 +62,9 @@ trait Lens[S, A] extends LPLens[S, A] { outer => } trait LPLens[S, A] extends Dynamic with Serializable { self: Lens[S, A] => - def selectDynamic[B](k: String) - (implicit mkLens: MkSelectDynamicOptic[Lens[S, A], A, Symbol @@ k.type, B], dummy: DummyImplicit): mkLens.Out = mkLens(this) + def selectDynamic[B](k: String)( + implicit mkLens: MkSelectDynamicOptic[Lens[S, A], A, k.type, B], dummy: DummyImplicit + ): mkLens.Out = mkLens(this) } trait Prism[S, A] extends LPPrism[S, A] { outer => @@ -81,8 +82,9 @@ trait Prism[S, A] extends LPPrism[S, A] { outer => def set(t: T)(a: A): T = g.modify(t)(outer.set(_)(a)) } - def selectDynamic(k: String) - (implicit mkPrism: MkSelectDynamicOptic[Prism[S, A], A, Symbol @@ k.type, Nothing]): mkPrism.Out = mkPrism(this) + def selectDynamic(k: String)( + implicit mkPrism: MkSelectDynamicOptic[Prism[S, A], A, k.type, Nothing] + ): mkPrism.Out = mkPrism(this) def apply[B](implicit mkPrism: MkCtorPrism[A, B]): Prism[S, B] = mkPrism() compose this @@ -106,8 +108,9 @@ trait Prism[S, A] extends LPPrism[S, A] { outer => } trait LPPrism[S, A] extends Dynamic with Serializable { self: Prism[S, A] => - def selectDynamic[B](k: String) - (implicit mkPrism: MkSelectDynamicOptic[Prism[S, A], A, Symbol @@ k.type, B], dummy: DummyImplicit): mkPrism.Out = mkPrism(this) + def selectDynamic[B](k: String)( + implicit mkPrism: MkSelectDynamicOptic[Prism[S, A], A, k.type, B], dummy: DummyImplicit + ): mkPrism.Out = mkPrism(this) } trait ProductLensBuilder[C, P <: Product] extends Lens[C, P] with Serializable { @@ -538,14 +541,14 @@ trait Segment[P, S, T <: HList] { trait LowPrioritySegment { type Aux[P, S, T <: HList, Out0 <: HList] = Segment[P, S, T] { type Out = Out0 } - implicit def two[P, S, T <: HList]: Aux[P, S, T, Coselect[S] :: Select[Symbol @@ P] :: T] = new Segment[P, S, T] { - type Out = Coselect[S] :: Select[Symbol @@ P] :: T + implicit def two[P, S, T <: HList]: Aux[P, S, T, Coselect[S] :: Select[P] :: T] = new Segment[P, S, T] { + type Out = Coselect[S] :: Select[P] :: T } } object Segment extends LowPrioritySegment { - implicit def one[P, T <: HList]: Aux[P, Nothing, T, Select[Symbol @@ P] :: T] = new Segment[P, Nothing, T] { - type Out = Select[Symbol @@ P] :: T + implicit def one[P, T <: HList]: Aux[P, Nothing, T, Select[P] :: T] = new Segment[P, Nothing, T] { + type Out = Select[P] :: T } } diff --git a/core/src/main/scala/shapeless/ops/records.scala b/core/src/main/scala/shapeless/ops/records.scala index 50a628500..29459f3c2 100644 --- a/core/src/main/scala/shapeless/ops/records.scala +++ b/core/src/main/scala/shapeless/ops/records.scala @@ -631,13 +631,14 @@ package record { type Aux[L <: HList, Out0 <: HList] = Keys[L] { type Out = Out0 } - implicit def hnilKeys[L <: HNil]: Aux[L, HNil] = - new Keys[L] { - type Out = HNil - def apply(): Out = HNil - } + implicit val hnilKeys: Aux[HNil, HNil] = new Keys[HNil] { + type Out = HNil + def apply(): Out = HNil + } - implicit def hlistKeys[K, V, T <: HList](implicit wk: Witness.Aux[K], kt: Keys[T]): Aux[FieldType[K, V] :: T, K :: kt.Out] = + implicit def hlistKeys[K, V, T <: HList]( + implicit wk: Witness.Aux[K], kt: Keys[T] + ): Aux[FieldType[K, V] :: T, K :: kt.Out] = new Keys[FieldType[K, V] :: T] { type Out = K :: kt.Out def apply(): Out = wk.value :: kt() diff --git a/core/src/main/scala/shapeless/records.scala b/core/src/main/scala/shapeless/records.scala index 293ce74e5..5786a525f 100644 --- a/core/src/main/scala/shapeless/records.scala +++ b/core/src/main/scala/shapeless/records.scala @@ -29,7 +29,7 @@ import scala.reflect.macros.whitebox object record { import syntax.RecordOps - implicit def recordOps[L <: HList](l : L) : RecordOps[L] = new RecordOps(l) + implicit def recordOps[L <: HList](l : L): RecordOps[L] = new RecordOps(l) /** * Records encoded as `HLists` of their value types intersected with the @@ -41,7 +41,7 @@ object record { * appears to the compiler as stable, * * {{{ - * type Xyz = Record.`'x -> Int, 'y -> String, 'z -> Boolean`.T + * type Xyz = Record.`"x" -> Int, "y" -> String, "z" -> Boolean`.T * }}} * * The use of singleton-typed `Symbols` as keys would make this type extremely @@ -52,13 +52,12 @@ object record { * * {{{ * val xyz = Record(x = 23, y = "foo", z = true) - * xyz('y) // == "foo" + * xyz("y") // == "foo" * }}} */ object Record extends Dynamic { def applyDynamic(method: String)(rec: Any*): HList = macro RecordMacros.mkRecordEmptyImpl def applyDynamicNamed(method: String)(rec: Any*): HList = macro RecordMacros.mkRecordNamedImpl - def selectDynamic(tpeSelector: String): Any = macro LabelledMacros.recordTypeImpl } } @@ -75,7 +74,7 @@ object record { * to be rewritten as, * * {{{ - * lhs.methodRecord('x ->> 23 :: 'y ->> "foo", 'z ->> true) + * lhs.methodRecord("x" ->> 23 :: "y" ->> "foo", "z" ->> true) * }}} * * ie. the named arguments are rewritten as record fields with the argument name @@ -94,7 +93,7 @@ trait RecordArgs extends Dynamic { * Mixing in this trait enables method applications of the form, * * {{{ - * lhs.methodRecord('x ->> 23 :: 'y ->> "foo" :: 'z ->> true :: HNil) + * lhs.methodRecord("x" ->> 23 :: "y" ->> "foo" :: "z" ->> true :: HNil) * }}} * * to be rewritten as, @@ -117,22 +116,20 @@ class RecordMacros(val c: whitebox.Context) { import internal.constantType import labelled.FieldType - val hconsValueTree = reify { :: }.tree - val hnilValueTree = reify { HNil: HNil }.tree - val fieldTypeTpe = typeOf[FieldType[_, _]].typeConstructor - val SymTpe = typeOf[scala.Symbol] - val atatTpe = typeOf[tag.@@[_,_]].typeConstructor + val hconsValueTree: Tree = reify(::).tree + val hnilValueTree: Tree = reify(HNil: HNil).tree + val fieldTypeTpe: Type = typeOf[FieldType[_, _]].typeConstructor def mkRecordEmptyImpl(method: Tree)(rec: Tree*): Tree = { - if(rec.nonEmpty) + if (rec.nonEmpty) c.abort(c.enclosingPosition, "this method must be called with named arguments") - q"_root_.shapeless.HNil" + hnilValueTree } def mkRecordNamedImpl(method: Tree)(rec: Tree*): Tree = { val q"${methodString: String}" = method - if(methodString != "apply") + if (methodString != "apply") c.abort(c.enclosingPosition, s"this method must be called as 'apply' not '$methodString'") mkRecordImpl(rec: _*) @@ -145,14 +142,13 @@ class RecordMacros(val c: whitebox.Context) { val lhsTpe = lhs.tpe val q"${methodString: String}" = method - val methodName = TermName(methodString+"Record") + val methodName = TermName(methodString + "Record") - if(lhsTpe.member(methodName) == NoSymbol) + if (lhsTpe.member(methodName) == NoSymbol) c.abort(c.enclosingPosition, s"missing method '$methodName'") val recTree = mkRecordImpl(rec: _*) - - q""" $lhs.$methodName($recTree) """ + q"$lhs.$methodName($recTree)" } def forwardFromRecordImpl[L <: HList](method: Tree)(rec: Expr[L]): Tree = { @@ -166,16 +162,13 @@ class RecordMacros(val c: whitebox.Context) { val methodName = TermName(methodString.replaceAll("Record$", "")) - if(!lhsTpe.member(methodName).isMethod) + if (!lhsTpe.member(methodName).isMethod) c.abort(c.enclosingPosition, s"missing method '$methodName'") val params = mkParamsImpl(lhsTpe.member(methodName).asMethod, rec) - q""" $lhs.$methodName(...$params) """ + q"$lhs.$methodName(...$params)" } - def mkSingletonSymbolType(c: Constant): Type = - appliedType(atatTpe, List(SymTpe, constantType(c))) - def mkFieldTpe(keyTpe: Type, valueTpe: Type): Type = appliedType(fieldTypeTpe, List(keyTpe, valueTpe.widen)) @@ -184,23 +177,22 @@ class RecordMacros(val c: whitebox.Context) { q"$value.asInstanceOf[${mkFieldTpe(keyTpe, value.tpe)}]" def promoteElem(elem: Tree): Tree = elem match { - case q""" $prefix(${Literal(k: Constant)}, $v) """ => mkElem(mkSingletonSymbolType(k), v) - case _ => - c.abort(c.enclosingPosition, s"$elem has the wrong shape for a record field") + case q"$_(${Literal(k)}, $v)" => mkElem(constantType(k), v) + case _ => c.abort(c.enclosingPosition, s"$elem has the wrong shape for a record field") } - rec.foldRight(hnilValueTree) { - case(elem, acc) => q""" $hconsValueTree(${promoteElem(elem)}, $acc) """ + rec.foldRight(hnilValueTree) { case (elem, acc) => + q"$hconsValueTree(${promoteElem(elem)}, $acc)" } } def mkParamsImpl[L <: HList](method: MethodSymbol, rec: Expr[L]): List[List[Tree]] = { + val selector = reify(ops.hlist.Selector) def mkElem(keyTpe: Type, value: Tree): Tree = - q"_root_.scala.Predef.implicitly[_root_.shapeless.ops.hlist.Selector[${rec.actualType}, ${mkFieldTpe(keyTpe, value.tpe)}]].apply($rec)" + q"$selector[${rec.actualType}, ${mkFieldTpe(keyTpe, value.tpe)}].apply($rec)" - method.paramLists.filterNot(_.forall(x => x.isImplicit)).map(_.map { x => - mkElem(mkSingletonSymbolType(Constant(x.name.decodedName.toString)), q"${x.typeSignature}") + method.paramLists.filterNot(_.forall(_.isImplicit)).map(_.map { p => + mkElem(constantType(Constant(p.name.decodedName.toString)), q"${p.typeSignature}") }) - } } diff --git a/core/src/main/scala/shapeless/singletons.scala b/core/src/main/scala/shapeless/singletons.scala index 980d85875..5896cb519 100644 --- a/core/src/main/scala/shapeless/singletons.scala +++ b/core/src/main/scala/shapeless/singletons.scala @@ -299,21 +299,14 @@ class SingletonTypeMacros(val c: whitebox.Context) extends SingletonTypeUtils wi } def extractSingletonValue(tpe: Type): Tree = - tpe match { - case ConstantType(Constant(s: scala.Symbol)) => mkSingletonSymbol(s.name) - - case ConstantType(c: Constant) => Literal(c) - - case t: SingleType => mkAttributedQualifier(t) - - case SingletonSymbolType(c) => mkSingletonSymbol(c) - + SingletonSymbolType.unrefine(tpe) match { + case ConstantType(Constant(sym: scala.Symbol)) => mkSingletonSymbol(sym.name) + case ConstantType(const) => Literal(const) + case singleton: SingleType => mkAttributedQualifier(singleton) + case SingletonSymbolType(name) => mkSingletonSymbol(name) case ThisType(sym) => This(sym) - - case t@TypeRef(_, sym, _) if sym.isModuleClass => mkAttributedQualifier(t) - - case _ => - c.abort(c.enclosingPosition, s"Type argument $tpe is not a singleton type") + case ref @ TypeRef(_, sym, _) if sym.isModuleClass => mkAttributedQualifier(ref) + case _ => c.abort(c.enclosingPosition, s"Type argument $tpe is not a singleton type") } def materializeImpl[T: WeakTypeTag]: Tree = { diff --git a/core/src/main/scala/shapeless/syntax/records.scala b/core/src/main/scala/shapeless/syntax/records.scala index 327e843b7..3589cd54a 100644 --- a/core/src/main/scala/shapeless/syntax/records.scala +++ b/core/src/main/scala/shapeless/syntax/records.scala @@ -18,7 +18,6 @@ package shapeless package syntax import scala.language.dynamics -import tag.@@ /** * Record operations on `HList`'s with field-like elements. @@ -164,5 +163,5 @@ final case class DynamicRecordOps[L <: HList](l : L) extends Dynamic { /** * Allows dynamic-style access to fields of the record whose keys are Symbols. */ - def selectDynamic(key: String)(implicit selector: Selector[L, Symbol @@ key.type]): selector.Out = selector(l) + def selectDynamic(key: String)(implicit selector: Selector[L, key.type]): selector.Out = selector(l) } diff --git a/core/src/main/scala/shapeless/syntax/unions.scala b/core/src/main/scala/shapeless/syntax/unions.scala index 23db01d5e..4c49fc444 100644 --- a/core/src/main/scala/shapeless/syntax/unions.scala +++ b/core/src/main/scala/shapeless/syntax/unions.scala @@ -18,7 +18,6 @@ package shapeless package syntax import scala.language.dynamics -import tag.@@ /** * Discriminated union operations on `Coproducts`'s with field-like elements. @@ -87,5 +86,5 @@ final case class DynamicUnionOps[C <: Coproduct](c : C) extends Dynamic { /** * Allows dynamic-style access to fields of the union whose keys are Symbols. */ - def selectDynamic(key: String)(implicit selector: Selector[C, Symbol @@ key.type]): selector.Out = selector(c) + def selectDynamic(key: String)(implicit selector: Selector[C, key.type]): selector.Out = selector(c) } diff --git a/core/src/main/scala/shapeless/typeclass.scala b/core/src/main/scala/shapeless/typeclass.scala index e9b4c270f..2c5b6271e 100644 --- a/core/src/main/scala/shapeless/typeclass.scala +++ b/core/src/main/scala/shapeless/typeclass.scala @@ -48,8 +48,8 @@ trait ProductTypeClassCompanion[C[_]] extends Serializable { implicit def deriveHNil: C[HNil] = typeClass.emptyProduct - implicit def deriveHCons[H, T <: HList] (implicit ch: Lazy[C[H]], ct: Lazy[C[T]]): C[H :: T] = - typeClass.product(ch.value, ct.value) + implicit def deriveHCons[H, T <: HList](implicit ch: Lazy[C[H]], ct: C[T]): C[H :: T] = + typeClass.product(ch.value, ct) implicit def deriveInstance[F, G](implicit gen: Generic.Aux[F, G], cg: Lazy[C[G]]): C[F] = typeClass.project(cg.value, gen.to _, gen.from _) @@ -97,37 +97,30 @@ trait LabelledProductTypeClassCompanion[C[_]] extends Serializable { type Aux[KV, V0] = Wrap[KV] { type V = V0 } } - implicit def deriveHNil: Wrap.Aux[HNil, HNil] = - new Wrap[HNil] { - type V = HNil - val unwrap = typeClass.emptyProduct - def label(v: HNil): HNil = HNil - def unlabel(rec: HNil): HNil = HNil - } + implicit def deriveHNil: Wrap.Aux[HNil, HNil] = new Wrap[HNil] { + type V = HNil + val unwrap = typeClass.emptyProduct + def label(v: HNil): HNil = HNil + def unlabel(rec: HNil): HNil = HNil + } - implicit def deriveHCons[HK <: Symbol, HV, TKV <: HList] - (implicit - ch: Lazy[C[HV]], - key: Witness.Aux[HK], - ct: Lazy[Wrap[TKV] { type V <: HList }] - ): Wrap.Aux[FieldType[HK, HV] :: TKV, HV :: ct.value.V] = - new Wrap[FieldType[HK, HV] :: TKV] { - type V = HV :: ct.value.V - val unwrap = typeClass.product(key.value.name, ch.value, ct.value.unwrap) - def label(v: HV :: ct.value.V): FieldType[HK, HV] :: TKV = field[HK](v.head) :: ct.value.label(v.tail) - def unlabel(rec: FieldType[HK, HV] :: TKV): HV :: ct.value.V = rec.head :: ct.value.unlabel(rec.tail) - } - - implicit def deriveInstance[T, LKV] - (implicit - lgen: LabelledGeneric.Aux[T, LKV], - lwclkv: Lazy[Wrap[LKV]] - ): C[T] = { - import lwclkv.value._ - val to: T => V = (t: T) => unlabel(lgen.to(t)) - val from: V => T = (v: V) => lgen.from(label(v)) - typeClass.project(unwrap, to, from) - } + implicit def deriveHCons[HK <: String, HV, TKV <: HList]( + implicit key: Witness.Aux[HK], ch: Lazy[C[HV]], ct: Wrap[TKV] { type V <: HList } + ): Wrap.Aux[FieldType[HK, HV] :: TKV, HV :: ct.V] = new Wrap[FieldType[HK, HV] :: TKV] { + type V = HV :: ct.V + val unwrap = typeClass.product(key.value, ch.value, ct.unwrap) + def label(v: V): FieldType[HK, HV] :: TKV = field[HK](v.head) :: ct.label(v.tail) + def unlabel(rec: FieldType[HK, HV] :: TKV): V = rec.head :: ct.unlabel(rec.tail) + } + + implicit def deriveInstance[T, LKV]( + implicit lgen: LabelledGeneric.Aux[T, LKV], lwclkv: Lazy[Wrap[LKV]] + ): C[T] = { + import lwclkv.value._ + val to: T => V = (t: T) => unlabel(lgen.to(t)) + val from: V => T = (v: V) => lgen.from(label(v)) + typeClass.project(unwrap, to, from) + } } /** @@ -152,8 +145,8 @@ trait TypeClassCompanion[C[_]] extends ProductTypeClassCompanion[C] { implicit def deriveCNil: C[CNil] = typeClass.emptyCoproduct - implicit def deriveCCons[H, T <: Coproduct] (implicit ch: Lazy[C[H]], ct: Lazy[C[T]]): C[H :+: T] = - typeClass.coproduct(ch.value, ct.value) + implicit def deriveCCons[H, T <: Coproduct](implicit ch: Lazy[C[H]], ct: C[T]): C[H :+: T] = + typeClass.coproduct(ch.value, ct) } /** @@ -178,32 +171,25 @@ trait LabelledTypeClass[C[_]] extends LabelledProductTypeClass[C] { trait LabelledTypeClassCompanion[C[_]] extends LabelledProductTypeClassCompanion[C] { val typeClass: LabelledTypeClass[C] - implicit def deriveCNil: Wrap.Aux[CNil, CNil] = - new Wrap[CNil] { - type V = CNil - val unwrap = typeClass.emptyCoproduct - def label(v: CNil): CNil = ??? - def unlabel(rec: CNil): CNil = ??? - } + implicit def deriveCNil: Wrap.Aux[CNil, CNil] = new Wrap[CNil] { + type V = CNil + val unwrap = typeClass.emptyCoproduct + def label(v: CNil): CNil = ??? + def unlabel(rec: CNil): CNil = ??? + } - implicit def deriveCCons[HK <: Symbol, HV, TKV <: Coproduct] - (implicit - ch: Lazy[C[HV]], - key: Witness.Aux[HK], - ct: Lazy[Wrap[TKV] { type V <: Coproduct }] - ): Wrap.Aux[FieldType[HK, HV] :+: TKV, HV :+: ct.value.V] = - new Wrap[FieldType[HK, HV] :+: TKV] { - type V = HV :+: ct.value.V - val unwrap = typeClass.coproduct(key.value.name, ch.value, ct.value.unwrap) - def label(v: HV :+: ct.value.V): FieldType[HK, HV] :+: TKV = - v match { - case Inl(hv) => Inl(field[HK](hv)) - case Inr(tv) => Inr(ct.value.label(tv)) - } - def unlabel(rec: FieldType[HK, HV] :+: TKV): HV :+: ct.value.V = - rec match { - case Inl(hkv) => Inl(hkv) - case Inr(tkv) => Inr(ct.value.unlabel(tkv)) - } - } + implicit def deriveCCons[HK <: String, HV, TKV <: Coproduct]( + implicit key: Witness.Aux[HK], ch: Lazy[C[HV]], ct: Wrap[TKV] { type V <: Coproduct } + ): Wrap.Aux[FieldType[HK, HV] :+: TKV, HV :+: ct.V] = new Wrap[FieldType[HK, HV] :+: TKV] { + type V = HV :+: ct.V + val unwrap = typeClass.coproduct(key.value, ch.value, ct.unwrap) + def label(v: V): FieldType[HK, HV] :+: TKV = v match { + case Inl(hv) => Inl(field[HK](hv)) + case Inr(tv) => Inr(ct.label(tv)) + } + def unlabel(rec: FieldType[HK, HV] :+: TKV): V = rec match { + case Inl(hkv) => Inl(hkv) + case Inr(tkv) => Inr(ct.unlabel(tkv)) + } + } } diff --git a/core/src/main/scala/shapeless/unions.scala b/core/src/main/scala/shapeless/unions.scala index 0f15bc5f3..9cb201624 100644 --- a/core/src/main/scala/shapeless/unions.scala +++ b/core/src/main/scala/shapeless/unions.scala @@ -36,7 +36,7 @@ object union { * appears to the compiler as stable, * * {{{ - * type Xyz = Union.`'x -> Int, 'y -> String, 'z -> Boolean`.T + * type Xyz = Union.`"x" -> Int, "y" -> String, "z" -> Boolean`.T * }}} * * The use of singleton-typed `Symbols` as keys would make this type extremely @@ -47,12 +47,11 @@ object union { * * {{{ * val y = Union[Xyz](y = "foo") - * y.get('y) // == Some("foo") + * y.get("y") // == Some("foo") * }}} */ object Union extends Dynamic { def applyDynamicNamed[U <: Coproduct](method: String)(elems: Any*): U = macro UnionMacros.mkUnionNamedImpl[U] - def selectDynamic(tpeSelector: String): Any = macro LabelledMacros.unionTypeImpl } } @@ -63,13 +62,9 @@ class UnionMacros(val c: whitebox.Context) { import internal.constantType import labelled.FieldType - val fieldTypeTpe = typeOf[FieldType[_, _]].typeConstructor - val SymTpe = typeOf[scala.Symbol] - val atatTpe = typeOf[tag.@@[_,_]].typeConstructor - def mkUnionNamedImpl[U <: Coproduct : WeakTypeTag](method: Tree)(elems: Tree*): Tree = { - def mkSingletonSymbolType(c: Constant): Type = - appliedType(atatTpe, List(SymTpe, constantType(c))) + val fieldTypeTpe = typeOf[FieldType[_, _]].typeConstructor + val coproduct = reify(Coproduct) def mkFieldTpe(keyTpe: Type, valueTpe: Type): Type = appliedType(fieldTypeTpe, List(keyTpe, valueTpe.widen)) @@ -78,22 +73,19 @@ class UnionMacros(val c: whitebox.Context) { q"$value.asInstanceOf[${mkFieldTpe(keyTpe, value.tpe)}]" def promoteElem(elem: Tree): Tree = elem match { - case q""" $prefix(${Literal(k: Constant)}, $v) """ => mkElem(mkSingletonSymbolType(k), v) - case _ => - c.abort(c.enclosingPosition, s"$elem has the wrong shape for a record field") + case q"$_(${Literal(k)}, $v)" => mkElem(constantType(k), v) + case _ => c.abort(c.enclosingPosition, s"$elem has the wrong shape for a record field") } val q"${methodString: String}" = method - if(methodString != "apply") + if (methodString != "apply") c.abort(c.enclosingPosition, s"this method must be called as 'apply' not '$methodString'") - val elem = - elems match { - case Seq(e) => e - case _ => - c.abort(c.enclosingPosition, s"only one branch of a union may be inhabited") - } + val elem = elems match { + case Seq(e) => e + case _ => c.abort(c.enclosingPosition, "only one branch of a union may be inhabited") + } - q""" _root_.shapeless.Coproduct[${weakTypeOf[U]}](${promoteElem(elem)}) """ + q"$coproduct[${weakTypeOf[U]}](${promoteElem(elem)})" } } diff --git a/core/src/test/scala/shapeless/default.scala b/core/src/test/scala/shapeless/default.scala index 00270c723..f1de92fd5 100644 --- a/core/src/test/scala/shapeless/default.scala +++ b/core/src/test/scala/shapeless/default.scala @@ -109,7 +109,7 @@ class DefaultTests { @Test def simpleAsRecord: Unit = { val default = Default.AsRecord[CC].apply() - assertTypedEquals[Record.`'s -> String, 'flagOpt -> Option[Boolean]`.T]( + assertTypedEquals[Record.`"s" -> String, "flagOpt" -> Option[Boolean]`.T]( Record(s = "b", flagOpt = Some(true)), default ) @@ -118,7 +118,7 @@ class DefaultTests { @Test def simpleFromPathAsRecord: Unit = { val default = Default.AsRecord[definitions.CC].apply() - assertTypedEquals[Record.`'s -> String, 'flagOpt -> Option[Boolean]`.T]( + assertTypedEquals[Record.`"s" -> String, "flagOpt" -> Option[Boolean]`.T]( Record(s = "b", flagOpt = Some(true)), default ) diff --git a/core/src/test/scala/shapeless/hlist.scala b/core/src/test/scala/shapeless/hlist.scala index 07a119d20..165a7d45b 100644 --- a/core/src/test/scala/shapeless/hlist.scala +++ b/core/src/test/scala/shapeless/hlist.scala @@ -3154,7 +3154,7 @@ class HListTests { NonSingletonHNilTC(SFoo()) val quux = Quux(23, "foo", true) - val ib = selectAll(Symbol("i"), Symbol("b")).from(quux) + val ib = selectAll("i", "b").from(quux) typed[(Int, Boolean)](ib) assertEquals((23, true), ib) } diff --git a/core/src/test/scala/shapeless/implicits.scala b/core/src/test/scala/shapeless/implicits.scala index 1bf862fe4..5c928cd3a 100644 --- a/core/src/test/scala/shapeless/implicits.scala +++ b/core/src/test/scala/shapeless/implicits.scala @@ -182,8 +182,8 @@ class CachedTest { val h: Int = gen.to(q).head val th: String = gen.to(q).tail.head - val lh: FieldType[Witness.`'i`.T, Int] = lgen.to(q).head - val lth: FieldType[Witness.`'s`.T, String] = lgen.to(q).tail.head + val lh: FieldType[Witness.`"i"`.T, Int] = lgen.to(q).head + val lth: FieldType[Witness.`"s"`.T, String] = lgen.to(q).tail.head } @Test diff --git a/core/src/test/scala/shapeless/labelledgeneric.scala b/core/src/test/scala/shapeless/labelledgeneric.scala index 1fd293e78..158276bf6 100644 --- a/core/src/test/scala/shapeless/labelledgeneric.scala +++ b/core/src/test/scala/shapeless/labelledgeneric.scala @@ -57,11 +57,11 @@ object LabelledGenericTestsAux { (Symbol("authors") ->> Seq("Erich Gamma", "Richard Helm", "Ralph Johnson", "John Vlissides")) :: HNil - type BookRec = Record.`'author -> String, 'title -> String, 'id -> Int, 'price -> Double`.T + type BookRec = Record.`"author" -> String, "title" -> String, "id" -> Int, "price" -> Double`.T type BookKeys = Keys[BookRec] type BookValues = Values[BookRec] - type BookWithMultipleAuthorsRec = Record.`'title -> String, 'id -> Int, 'authors -> Seq[String]`.T + type BookWithMultipleAuthorsRec = Record.`"title" -> String, "id" -> Int, "authors" -> Seq[String]`.T sealed trait Tree @@ -106,54 +106,35 @@ object ScalazTaggedAux { } object TC extends TCLowPriority { - implicit val intTC: TC[Int] = - new TC[Int] { - def apply() = "Int" - } - - implicit val booleanTC: TC[Boolean] = - new TC[Boolean] { - def apply() = "Boolean" - } - - implicit val taggedIntTC: TC[Int @@ CustomTag] = - new TC[Int @@ CustomTag] { - def apply() = s"TaggedInt" - } - - implicit val hnilTC: TC[HNil] = - new TC[HNil] { - def apply() = "HNil" - } - - implicit def hconsTC[K <: Symbol, H, T <: HList](implicit - key: Witness.Aux[K], - headTC: Lazy[TC[H]], - tailTC: TC[T] - ): TC[FieldType[K, H] :: T] = - new TC[FieldType[K, H] :: T] { - def apply() = s"${key.value.name}: ${headTC.value()} :: ${tailTC()}" - } - - implicit def projectTC[F, G](implicit - lgen: LabelledGeneric.Aux[F, G], - tc: Lazy[TC[G]] - ): TC[F] = - new TC[F] { - def apply() = s"Proj(${tc.value()})" - } + implicit val intTC: TC[Int] = instance("Int") + implicit val booleanTC: TC[Boolean] = instance("Boolean") + implicit val taggedIntTC: TC[Int @@ CustomTag] = instance("TaggedInt") + implicit val hnilTC: TC[HNil] = instance("HNil") + + implicit def hconsTC[K <: String, H, T <: HList]( + implicit key: Witness.Aux[K], headTC: Lazy[TC[H]], tailTC: TC[T] + ): TC[FieldType[K, H] :: T] = instance { + s"${key.value}: ${headTC.value()} :: ${tailTC()}" + } + + implicit def projectTC[F, G]( + implicit lgen: LabelledGeneric.Aux[F, G], tc: Lazy[TC[G]] + ): TC[F] = instance { + s"Proj(${tc.value()})" + } } abstract class TCLowPriority { + def instance[T](display: String): TC[T] = new TC[T] { + def apply(): String = display + } + // FIXME: Workaround #309 - implicit def hconsTCTagged[K <: Symbol, H, HT, T <: HList](implicit - key: Witness.Aux[K], - headTC: Lazy[TC[H @@ HT]], - tailTC: TC[T] - ): TC[FieldType[K, H @@ HT] :: T] = - new TC[FieldType[K, H @@ HT] :: T] { - def apply() = s"${key.value.name}: ${headTC.value()} :: ${tailTC()}" - } + implicit def hconsTCTagged[K <: String, H, HT, T <: HList]( + implicit key: Witness.Aux[K], headTC: Lazy[TC[H @@ HT]], tailTC: TC[T] + ): TC[FieldType[K, H @@ HT] :: T] = instance { + s"${key.value}: ${headTC.value()} :: ${tailTC()}" + } } } @@ -173,7 +154,7 @@ class LabelledGenericTests { assertEquals(tapl, b1) val keys = b0.keys - assertEquals(Symbol("author").narrow :: Symbol("title").narrow :: Symbol("id").narrow :: Symbol("price").narrow :: HNil, keys) + assertEquals("author".narrow :: "title".narrow :: "id".narrow :: "price".narrow :: HNil, keys) val values = b0.values assertEquals("Benjamin Pierce" :: "Types and Programming Languages" :: 262162091 :: 44.11 :: HNil, values) @@ -185,11 +166,11 @@ class LabelledGenericTests { val gen2 = LabelledGeneric[Private2] val gen3 = LabelledGeneric[Private3] val gen4 = LabelledGeneric[Private4] - val ab = Symbol("a").narrow :: Symbol("b").narrow :: HNil + val ab = "a".narrow :: "b".narrow :: HNil val p1 = Private1(1) val r1 = gen1.to(p1) - assertTypedEquals(Symbol("a").narrow :: HNil, r1.keys) + assertTypedEquals("a".narrow :: HNil, r1.keys) assertTypedEquals(1 :: HNil, r1.values) assertEquals(p1, gen1.from(r1)) @@ -221,7 +202,7 @@ class LabelledGenericTests { assertEquals(dpRecord, b0) val keys = b0.keys - assertEquals(Symbol("title").narrow :: Symbol("id").narrow :: Symbol("authors").narrow :: HNil, keys) + assertEquals("title".narrow :: "id".narrow :: "authors".narrow :: HNil, keys) val values = b0.values assertEquals( @@ -236,19 +217,19 @@ class LabelledGenericTests { val b0 = gen.to(tapl) - val e1 = b0.get(Symbol("author")) + val e1 = b0.get("author") typed[String](e1) assertEquals("Benjamin Pierce", e1) - val e2 = b0.get(Symbol("title")) + val e2 = b0.get("title") typed[String](e2) assertEquals( "Types and Programming Languages", e2) - val e3 = b0.get(Symbol("id")) + val e3 = b0.get("id") typed[Int](e3) assertEquals(262162091, e3) - val e4 = b0.get(Symbol("price")) + val e4 = b0.get("price") typed[Double](e4) assertEquals(44.11, e4, Double.MinPositiveValue) } @@ -259,19 +240,19 @@ class LabelledGenericTests { val b0 = gen.to(tapl) - val e1 = b0(Symbol("author")) + val e1 = b0("author") typed[String](e1) assertEquals("Benjamin Pierce", e1) - val e2 = b0(Symbol("title")) + val e2 = b0("title") typed[String](e2) assertEquals( "Types and Programming Languages", e2) - val e3 = b0(Symbol("id")) + val e3 = b0("id") typed[Int](e3) assertEquals(262162091, e3) - val e4 = b0(Symbol("price")) + val e4 = b0("price") typed[Double](e4) assertEquals(44.11, e4, Double.MinPositiveValue) } @@ -305,8 +286,8 @@ class LabelledGenericTests { val b0 = gen.to(tapl) - val b1 = b0.updated(Symbol("title"), "Types and Programming Languages (2nd Ed.)") - val b2 = b1.updated(Symbol("price"), 46.11) + val b1 = b0.updated("title", "Types and Programming Languages (2nd Ed.)") + val b2 = b1.updated("price", 46.11) val updated = gen.from(b2) assertEquals(tapl2, updated) @@ -318,8 +299,8 @@ class LabelledGenericTests { val b0 = gen.to(tapl) - val b1 = b0.updateWith(Symbol("title"))(_+" (2nd Ed.)") - val b2 = b1.updateWith(Symbol("price"))(_+2.0) + val b1 = b0.updateWith("title")(_+" (2nd Ed.)") + val b2 = b1.updateWith("price")(_+2.0) val updated = gen.from(b2) assertEquals(tapl2, updated) @@ -331,7 +312,7 @@ class LabelledGenericTests { val gen2 = LabelledGeneric[ExtendedBook] val b0 = gen.to(tapl) - val b1 = b0 + (Symbol("inPrint") ->> true) + val b1 = b0 + ("inPrint" ->> true) val b2 = gen2.from(b1) typed[ExtendedBook](b2) @@ -340,7 +321,7 @@ class LabelledGenericTests { @Test def testCoproductBasics: Unit = { - type TreeUnion = Union.`'Leaf -> Leaf, 'Node -> Node`.T + type TreeUnion = Union.`"Leaf" -> Leaf, "Node" -> Node`.T val gen = LabelledGeneric[Tree] @@ -355,35 +336,35 @@ class LabelledGenericTests { val nccb = new NonCCB(true, 2.0) val ancc: AbstractNonCC = ncca - type NonCCARec = Record.`'i -> Int, 's -> String`.T - type NonCCBRec = Record.`'b -> Boolean, 'd -> Double`.T - type AbsUnion = Union.`'NonCCA -> NonCCA, 'NonCCB -> NonCCB`.T + type NonCCARec = Record.`"i" -> Int, "s" -> String`.T + type NonCCBRec = Record.`"b" -> Boolean, "d" -> Double`.T + type AbsUnion = Union.`"NonCCA" -> NonCCA, "NonCCB" -> NonCCB`.T val genA = LabelledGeneric[NonCCA] val genB = LabelledGeneric[NonCCB] val genAbs = LabelledGeneric[AbstractNonCC] val rA = genA.to(ncca) - assertTypedEquals[NonCCARec](Symbol("i") ->> 23 :: Symbol("s") ->> "foo" :: HNil, rA) + assertTypedEquals[NonCCARec]("i" ->> 23 :: "s" ->> "foo" :: HNil, rA) val rB = genB.to(nccb) - assertTypedEquals[NonCCBRec](Symbol("b") ->> true :: Symbol("d") ->> 2.0 :: HNil, rB) + assertTypedEquals[NonCCBRec]("b" ->> true :: "d" ->> 2.0 :: HNil, rB) val rAbs = genAbs.to(ancc) - val injA = Coproduct[AbsUnion](Symbol("NonCCA") ->> ncca) + val injA = Coproduct[AbsUnion]("NonCCA" ->> ncca) assertTypedEquals[AbsUnion](injA, rAbs) - val fA = genA.from(Symbol("i") ->> 13 :: Symbol("s") ->> "bar" :: HNil) + val fA = genA.from("i" ->> 13 :: "s" ->> "bar" :: HNil) typed[NonCCA](fA) assertEquals(13, fA.i) assertEquals("bar", fA.s) - val fB = genB.from(Symbol("b") ->> false :: Symbol("d") ->> 3.0 :: HNil) + val fB = genB.from("b" ->> false :: "d" ->> 3.0 :: HNil) typed[NonCCB](fB) assertEquals(false, fB.b) assertEquals(3.0, fB.d, Double.MinPositiveValue) - val injB = Coproduct[AbsUnion](Symbol("NonCCB") ->> nccb) + val injB = Coproduct[AbsUnion]("NonCCB" ->> nccb) val fAbs = genAbs.from(injB) typed[AbstractNonCC](fAbs) assertTrue(fAbs.isInstanceOf[NonCCB]) @@ -395,15 +376,15 @@ class LabelledGenericTests { def testNonCCWithCompanion: Unit = { val nccc = NonCCWithCompanion(23, "foo") - val rec = (Symbol("i") ->> 23) :: (Symbol("s") ->> "foo") :: HNil - type NonCCRec = Record.`'i -> Int, 's -> String`.T + val rec = ("i" ->> 23) :: ("s" ->> "foo") :: HNil + type NonCCRec = Record.`"i" -> Int, "s" -> String`.T val gen = LabelledGeneric[NonCCWithCompanion] val r = gen.to(nccc) assertTypedEquals[NonCCRec](rec, r) - val f = gen.from(Symbol("i") ->> 13 :: Symbol("s") ->> "bar" :: HNil) + val f = gen.from("i" ->> 13 :: "s" ->> "bar" :: HNil) typed[NonCCWithCompanion](f) assertEquals(13, f.i) assertEquals("bar", f.s) @@ -414,15 +395,15 @@ class LabelledGenericTests { lazy val (a: NonCCLazy, b: NonCCLazy, c: NonCCLazy) = (new NonCCLazy(c, b), new NonCCLazy(a, c), new NonCCLazy(b, a)) - val rec = Symbol("prev") ->> a :: Symbol("next") ->> c :: HNil - type LazyRec = Record.`'prev -> NonCCLazy, 'next -> NonCCLazy`.T + val rec = "prev" ->> a :: "next" ->> c :: HNil + type LazyRec = Record.`"prev" -> NonCCLazy, "next" -> NonCCLazy`.T val gen = LabelledGeneric[NonCCLazy] val rB = gen.to(b) assertTypedEquals[LazyRec](rec, rB) - val fD = gen.from(Symbol("prev") ->> a :: Symbol("next") ->> c :: HNil) + val fD = gen.from("prev" ->> a :: "next" ->> c :: HNil) typed[NonCCLazy](fD) assertEquals(a, fD.prev) assertEquals(c, fD.next) @@ -452,12 +433,12 @@ class LabelledGenericTests { implicitly[TC[DummyTagged]] - type R = Record.`'i -> Int @@ CustomTag`.T + type R = Record.`"i" -> Int @@ CustomTag`.T val lgen = LabelledGeneric[Dummy] implicitly[lgen.Repr =:= R] implicitly[TC[R]] - type RT = Record.`'b -> Boolean, 'i -> Int @@ CustomTag`.T + type RT = Record.`"b" -> Boolean, "i" -> Int @@ CustomTag`.T val lgent = LabelledGeneric[DummyTagged] implicitly[lgent.Repr =:= RT] implicitly[TC[RT]] diff --git a/core/src/test/scala/shapeless/lenses.scala b/core/src/test/scala/shapeless/lenses.scala index df06faa07..8f4327494 100644 --- a/core/src/test/scala/shapeless/lenses.scala +++ b/core/src/test/scala/shapeless/lenses.scala @@ -292,12 +292,12 @@ class LensTestsNat extends LensTests { } class LensTestsKey extends LensTests { - val nameLens = lens[Person] >> Symbol("name") - val ageLens = lens[Person] >> Symbol("age") - val addressLens = lens[Person] >> Symbol("address") - val streetLens = lens[Person] >> Symbol("address") >> Symbol("street") - val cityLens = lens[Person] >> Symbol("address") >> Symbol("city") - val postcodeLens = lens[Person] >> Symbol("address") >> Symbol("postcode") + val nameLens = lens[Person] >> "name" + val ageLens = lens[Person] >> "age" + val addressLens = lens[Person] >> "address" + val streetLens = lens[Person] >> "address" >> "street" + val cityLens = lens[Person] >> "address" >> "city" + val postcodeLens = lens[Person] >> "address" >> "postcode" } class OpticTestsDynamic extends LensTests { diff --git a/core/src/test/scala/shapeless/product.scala b/core/src/test/scala/shapeless/product.scala index 0e83c38cd..47078fc9c 100644 --- a/core/src/test/scala/shapeless/product.scala +++ b/core/src/test/scala/shapeless/product.scala @@ -144,14 +144,14 @@ class ProductTests { // With explicit type arguments, >: or =:= to the inferred ones respectively { - val fooL = foo.toRecord[Record.`'i -> AnyVal, 's -> String`.T] + val fooL = foo.toRecord[Record.`"i" -> AnyVal, "s" -> String`.T] val expectedFooL = Record(i=1: AnyVal, s="b") equalInferredTypes(expectedFooL, fooL) assertTypedEquals(expectedFooL, fooL) } { - val barL = bar.toRecord[Record.`'b -> Boolean, 'f -> Foo`.T] + val barL = bar.toRecord[Record.`"b" -> Boolean, "f" -> Foo`.T] val expectedBarL = Record(b=true, f=foo) equalInferredTypes(expectedBarL, barL) assertTypedEquals(expectedBarL, barL) @@ -318,14 +318,14 @@ class ProductTests { { val m = foo.toMap - val expected = Map(Symbol("i").narrow -> 1, Symbol("s").narrow -> "b") + val expected = Map("i".narrow -> 1, "s".narrow -> "b") equalInferredTypes(expected, m) assertTypedEquals(expected, m) } { - val m = foo.toMap[Symbol, Any] - val expected = Map[Symbol, Any](Symbol("i") -> 1, Symbol("s") -> "b") + val m = foo.toMap[String, Any] + val expected = Map[String, Any]("i" -> 1, "s" -> "b") equalInferredTypes(expected, m) assertTypedEquals(expected, m) } diff --git a/core/src/test/scala/shapeless/records.scala b/core/src/test/scala/shapeless/records.scala index ca41fb637..341582b67 100644 --- a/core/src/test/scala/shapeless/records.scala +++ b/core/src/test/scala/shapeless/records.scala @@ -352,17 +352,17 @@ class RecordTests { val inner1 = Record(d = 3, m = 2D, x= "X") val outer1 = Record(x = "foo", d = -1, e = inner1) - type i = Record.`'x -> String, 'd -> Int`.T - type i1 = Record.`'x -> Any, 'd -> Any`.T + type i = Record.`"x" -> String, "d" -> Int`.T + type i1 = Record.`"x" -> Any, "d" -> Any`.T val extRes = Record(e = Record(x = "X", d = 3), d = -1) - assertTypedEquals(extRes)(outer1.extract[Record.`'e -> i, 'd -> Int`.T]) + assertTypedEquals(extRes)(outer1.extract[Record.`"e" -> i, "d" -> Int`.T]) //covariance - assertEquals(extRes, outer1.extract[Record.`'e -> i1, 'd -> Any`.T]) + assertEquals(extRes, outer1.extract[Record.`"e" -> i1, "d" -> Any`.T]) - type ill1 = Record.`'d -> Int, 'z -> Int`.T - type ill2 = Record.`'x -> i`.T - type illIner = Record.`'m -> String, 'd -> Int`.T - type ill3 = Record.`'e -> illIner, 'd -> Int`.T + type ill1 = Record.`"d" -> Int, "z" -> Int`.T + type ill2 = Record.`"x" -> i`.T + type illIner = Record.`"m" -> String, "d" -> Int`.T + type ill3 = Record.`"e" -> illIner, "d" -> Int`.T illTyped("outer1.extract[ill1]") @@ -575,34 +575,34 @@ class RecordTests { @Test def testReplace: Unit = { - type R = Record.`'a -> Int, 'b -> String`.T + type R = Record.`"a" -> Int, "b" -> String`.T val a = Record(a = 1, b = "2") - val r = a.replace(Symbol("a"), 2) + val r = a.replace("a", 2) typed[R](r) assertEquals(Record(a = 2, b = "2"), r) - illTyped(""" a.replace(Symbol("a"), ()) """) + illTyped("""a.replace("a", ())""") } @Test def testLacksKey: Unit = { def without[R <: HList, O <: HList](k: Witness)(r: R)(f: R => O)(implicit ev: LacksKey[R, k.T]): O = f(r) - type R1 = Record.`'a -> Int, 'b -> String, 'c -> Boolean`.T - type R2 = Record.`'c -> Boolean, 'a -> Int, 'b -> String`.T + type R1 = Record.`"a" -> Int, "b" -> String, "c" -> Boolean`.T + type R2 = Record.`"c" -> Boolean, "a" -> Int, "b" -> String`.T val a = Record(a = 1, b = "2") - val r1 = without(Symbol("c"))(a)(_ :+ (Symbol("c") ->> true)) + val r1 = without("c")(a)(_ :+ ("c" ->> true)) typed[R1](r1) assertEquals(Record(a = 1, b = "2", c = true), r1) - val r2 = without(Symbol("c"))(a)((Symbol("c") ->> true) +: _) + val r2 = without("c")(a)(("c" ->> true) +: _) typed[R2](r2) assertEquals(Record(c = true, a = 1, b = "2"), r2) - illTyped(""" without(Symbol("a"))(a)(identity) """) + illTyped("""without("a")(a)(identity)""") } @Test @@ -830,7 +830,7 @@ class RecordTests { @Test def testSelectDynamic: Unit = { - val r = (Symbol("foo") ->> 23) :: (Symbol("bar") ->> true) :: HNil + val r = ("foo" ->> 23) :: ("bar" ->> true) :: HNil val d = r.record val v1 = d.foo @@ -869,40 +869,32 @@ class RecordTests { @Test def testNamedArgs: Unit = { - { - val r = Record() - typed[HNil](r) - } + val r1 = Record() + typed[HNil](r1) - { - val r = Record(i = 23, s = "foo", b = true) - typed[Record.`'i -> Int, 's -> String, 'b -> Boolean`.T](r) - } + val r2 = Record(i = 23, s = "foo", b = true) + typed[Record.`"i" -> Int, "s" -> String, "b" -> Boolean`.T](r2) - { - illTyped(""" Record(2, "a") """) - } + illTyped("""Record(2, "a")""") } @Test def testNamedArgsInject: Unit = { val r = Record(i = 23, s = "foo", b = true) - val v1 = r.get(Symbol("i")) + val v1 = r.get("i") typed[Int](v1) assertEquals(23, v1) - val v2 = r.get(Symbol("s")) + val v2 = r.get("s") typed[String](v2) assertEquals("foo", v2) - val v3 = r.get(Symbol("b")) + val v3 = r.get("b") typed[Boolean](v3) assertEquals(true, v3) - illTyped(""" - r.get(Symbol("foo")) - """) + illTyped("""r.get("foo")""") } object Foo extends RecordArgs { @@ -912,23 +904,21 @@ class RecordTests { @Test def testRecordArgs: Unit = { val r = Foo(i = 23, s = "foo", b = true) - typed[Record.`'i -> Int, 's -> String, 'b -> Boolean`.T](r) + typed[Record.`"i" -> Int, "s" -> String, "b" -> Boolean`.T](r) - val v1 = r.get(Symbol("i")) + val v1 = r.get("i") typed[Int](v1) assertEquals(23, v1) - val v2 = r.get(Symbol("s")) + val v2 = r.get("s") typed[String](v2) assertEquals("foo", v2) - val v3 = r.get(Symbol("b")) + val v3 = r.get("b") typed[Boolean](v3) assertEquals(true, v3) - illTyped(""" - r.get(Symbol("foo")) - """) + illTyped("""r.get("foo")""") } object Bar extends FromRecordArgs { @@ -939,33 +929,26 @@ class RecordTests { @Test def testFromRecordArgs: Unit = { - val r = (Symbol("i1") ->> 1) :: (Symbol("i2") ->> 3) :: HNil + val r = ("i1" ->> 1) :: ("i2" ->> 3) :: HNil val v1 = Bar.sumRecord(r) typed[Int](v1) assertEquals(4, v1) - val r2 = r.merge((Symbol("i2") ->> 2) :: HNil) + val r2 = r.merge(("i2" ->> 2) :: HNil) val v2 = Bar.sumMultipleParamListRecord(r2) typed[Int](v2) assertEquals(3, v2) - illTyped(""" - Bar.sumImplicitRecord((Symbol("i1") ->> 1) :: (Symbol("i2") ->> 3) :: HNil) - """) + illTyped("""Bar.sumImplicitRecord(("i1" ->> 1) :: ("i2" ->> 3) :: HNil)""") implicit val i2 = 7 val v3 = Bar.sumImplicitRecord(r) typed[Int](v2) assertEquals(8, v3) - illTyped(""" - Bar.sumRecord((Symbol("i1") ->> 1) :: (Symbol("i3") ->> 3) :: HNil) - """) - - illTyped(""" - Bar.sumMultipleParamListRecord((Symbol("i1") ->> 1) :: (Symbol("i3") ->> 3) :: HNil) - """) + illTyped("""Bar.sumRecord(("i1" ->> 1) :: ("i3" ->> 3) :: HNil)""") + illTyped("""Bar.sumMultipleParamListRecord(("i1" ->> 1) :: ("i3" ->> 3) :: HNil)""") } @Test @@ -984,7 +967,7 @@ class RecordTests { { val f = r.fields - assertTypedEquals((Symbol("i").narrow -> 23) :: (Symbol("s").narrow -> "foo") :: (Symbol("b").narrow -> true) :: HNil, f) + assertTypedEquals(("i".narrow -> 23) :: ("s".narrow -> "foo") :: ("b".narrow -> true) :: HNil, f) } val rs = ("first" ->> Some(2)) :: ("second" ->> Some(true)) :: ("third" ->> Option.empty[String]) :: HNil @@ -1009,12 +992,12 @@ class RecordTests { assertTypedEquals(HNil: HNil, uf.values(HNil: HNil)) } - type R = Record.`'i -> Int, 's -> String, 'b -> Boolean`.T + type R = Record.`"i" -> Int, "s" -> String, "b" -> Boolean`.T val r: R = Record(i = 23, s = "foo", b = true) { val uf = UnzipFields[R] - assertTypedEquals(Symbol("i").narrow :: Symbol("s").narrow :: Symbol("b").narrow :: HNil, uf.keys) + assertTypedEquals("i".narrow :: "s".narrow :: "b".narrow :: HNil, uf.keys) assertTypedEquals(23 :: "foo" :: true :: HNil, uf.values(r)) } @@ -1049,12 +1032,12 @@ class RecordTests { { val m = r.toMap - assertTypedEquals(Map[Symbol, Any](Symbol("i") -> 23, Symbol("s") -> "foo", Symbol("b") -> true), m) + assertTypedEquals(Map[String, Any]("i" -> 23, "s" -> "foo", "b" -> true), m) } { - val m = r.toMap[Symbol, Any] - assertTypedEquals(Map[Symbol, Any](Symbol("i") -> 23, Symbol("s") -> "foo", Symbol("b") -> true), m) + val m = r.toMap[String, Any] + assertTypedEquals(Map[String, Any]("i" -> 23, "s" -> "foo", "b" -> true), m) } val rs = ("first" ->> Some(2)) :: ("second" ->> Some(true)) :: ("third" ->> Option.empty[String]) :: HNil @@ -1087,7 +1070,7 @@ class RecordTests { { val r = Record(i = 23, s = "foo", b = true) val res = r.mapValues(f) - assertTypedEquals[Record.`'i -> Boolean, 's -> String, 'b -> String`.T](Record(i = true, s = "s: foo", b = "Yup"), res) + assertTypedEquals[Record.`"i" -> Boolean, "s" -> String, "b" -> String`.T](Record(i = true, s = "s: foo", b = "Yup"), res) } { @@ -1129,20 +1112,20 @@ class RecordTests { @Test def alignByKeys: Unit = { - type TestRecord = Record.`'a -> String, 'b -> Int, 'c -> Double`.T + type TestRecord = Record.`"a" -> String, "b" -> Int, "c" -> Double`.T - type Keys1 = HList.`'a, 'b, 'c`.T - type Keys2 = HList.`'b, 'c, 'a`.T - type Keys3 = HList.`'b, 'a, 'c`.T - type Keys4 = HList.`'c, 'a, 'b`.T + type Keys1 = HList.`"a", "b", "c"`.T + type Keys2 = HList.`"b", "c", "a"`.T + type Keys3 = HList.`"b", "a", "c"`.T + type Keys4 = HList.`"c", "a", "b"`.T val v = Record(a = "foo", b = 42, c = 33.3) assertTypedEquals[TestRecord](v, AlignByKeys[TestRecord, Keys1].apply(v)) - assertTypedEquals[Record.`'b -> Int, 'c -> Double, 'a -> String`.T](Record(b = 42, c = 33.3, a = "foo"), AlignByKeys[TestRecord, Keys2].apply(v)) + assertTypedEquals[Record.`"b" -> Int, "c" -> Double, "a" -> String`.T](Record(b = 42, c = 33.3, a = "foo"), AlignByKeys[TestRecord, Keys2].apply(v)) - assertTypedEquals[Record.`'b -> Int, 'a -> String, 'c -> Double`.T](Record(b = 42, a = "foo", c = 33.3), v.alignByKeys[Keys3]) - assertTypedEquals[Record.`'c -> Double, 'a -> String, 'b -> Int`.T](Record(c = 33.3, a = "foo", b = 42), v.alignByKeys[Keys4]) + assertTypedEquals[Record.`"b" -> Int, "a" -> String, "c" -> Double`.T](Record(b = 42, a = "foo", c = 33.3), v.alignByKeys[Keys3]) + assertTypedEquals[Record.`"c" -> Double, "a" -> String, "b" -> Int`.T](Record(c = 33.3, a = "foo", b = 42), v.alignByKeys[Keys4]) } @Test @@ -1167,7 +1150,7 @@ class RecordTests { val lgt = LabelledGeneric[FooT] val fooT = FooT(tag[TestTag]("test")) - assertEquals(tag[TestTag]("test"), lgt.to(fooT).get(Symbol("bar"))) + assertEquals(tag[TestTag]("test"), lgt.to(fooT).get("bar")) } @Test @@ -1179,6 +1162,6 @@ class RecordTests { val select = Selector[swap.Out, Int] val swapped = swap() - assertTypedEquals[Witness.`'a`.T](swapped.head, select(swapped)) + assertTypedEquals[Witness.`"a"`.T](swapped.head, select(swapped)) } } diff --git a/core/src/test/scala/shapeless/singletons.scala b/core/src/test/scala/shapeless/singletons.scala index a5d9cc565..284ea8958 100644 --- a/core/src/test/scala/shapeless/singletons.scala +++ b/core/src/test/scala/shapeless/singletons.scala @@ -658,42 +658,44 @@ package SingletonTypeTestsAux { package UnrefineTest { import shapeless._ + import shapeless.labelled.{FieldType, KeyTag} import shapeless.ops.record._ import shapeless.syntax.singleton._ trait Foo[A] { type Out - def to(a: A): Out } object Foo { type Aux[A, Out0] = Foo[A] { type Out = Out0 } - def apply[A, Out](implicit foo: Aux[A, Out]) = foo + def apply[A](implicit foo: Foo[A]): Aux[A, foo.Out] = foo - implicit def from[A, Out0](implicit gen: LabelledGeneric.Aux[A, Out0]) = - new Foo[A] { - type Out = Out0 - def to(a: A) = gen.to(a) - } + implicit def from[A]( + implicit gen: LabelledGeneric[A] + ): Aux[A, gen.Repr] = new Foo[A] { + type Out = gen.Repr + def to(a: A): Out = gen.to(a) + } } class Bar[A, HL <: HList](gen: Foo.Aux[A, HL]) { - def modify[K, V, U, Out0 <: HList](k: K, f: V => U)(implicit modifier: Modifier.Aux[HL, K, V, U, Out0]) = - new Bar[A, Out0](new Foo[A] { - type Out = Out0 - def to(a: A): Out = modifier.apply(gen.to(a), f) - }) + def modify[K, V, U](k: K, f: V => U)( + implicit modifier: Modifier[HL, K, V, U] + ): Bar[A, modifier.Out] = new Bar[A, modifier.Out](new Foo[A] { + type Out = modifier.Out + def to(a: A): Out = modifier.apply(gen.to(a), f) + }) - def keys[Out <: HList](implicit keys: Keys.Aux[HL, Out]): Out = keys.apply() + def keys(implicit keys: Keys[HL]): keys.Out = keys() } final case class FooBar(x: String, y: Int) object Test { - new Bar(Foo.from( LabelledGeneric[FooBar] )).modify(Symbol("y").narrow, (_: Int) * 2) - new Bar(Foo.from( LabelledGeneric[FooBar] )).keys - new Bar(Foo.from( LabelledGeneric[FooBar] )).modify(Symbol("y").narrow, (_: Int) * 2).keys + new Bar(Foo.from(LabelledGeneric[FooBar])).modify("y".narrow, (_: Int) * 2) + new Bar(Foo.from(LabelledGeneric[FooBar])).keys + new Bar(Foo.from(LabelledGeneric[FooBar])).modify("y".narrow, (_: Int) * 2).keys } } diff --git a/core/src/test/scala/shapeless/unions.scala b/core/src/test/scala/shapeless/unions.scala index 0345e4d31..37b05ba77 100644 --- a/core/src/test/scala/shapeless/unions.scala +++ b/core/src/test/scala/shapeless/unions.scala @@ -39,36 +39,34 @@ class UnionTests { val sB = Witness(Symbol("b")) type b = sB.T - type U = Union.`'i -> Int, 's -> String, 'b -> Boolean`.T + type U = Union.`"i" -> Int, "s" -> String, "b" -> Boolean`.T @Test def testGetLiterals: Unit = { - val u1 = Coproduct[U](Symbol("i") ->> 23) - val u2 = Coproduct[U](Symbol("s") ->> "foo") - val u3 = Coproduct[U](Symbol("b") ->> true) + val u1 = Coproduct[U]("i" ->> 23) + val u2 = Coproduct[U]("s" ->> "foo") + val u3 = Coproduct[U]("b" ->> true) - val v1 = u1.get(Symbol("i")) + val v1 = u1.get("i") typed[Option[Int]](v1) assertEquals(Some(23), v1) - val v2 = u2.get(Symbol("s")) + val v2 = u2.get("s") typed[Option[String]](v2) assertEquals(Some("foo"), v2) - val v3 = u3.get(Symbol("b")) + val v3 = u3.get("b") typed[Option[Boolean]](v3) assertEquals(Some(true), v3) - illTyped(""" - u1.get(Symbol("foo")) - """) + illTyped("""u1.get("foo")""") } @Test def testSelectDynamic: Unit = { - val u1 = Coproduct[U](Symbol("i") ->> 23).union - val u2 = Coproduct[U](Symbol("s") ->> "foo").union - val u3 = Coproduct[U](Symbol("b") ->> true).union + val u1 = Coproduct[U]("i" ->> 23).union + val u2 = Coproduct[U]("s" ->> "foo").union + val u3 = Coproduct[U]("b" ->> true).union val v1 = u1.i typed[Option[Int]](v1) @@ -197,21 +195,19 @@ class UnionTests { val u2 = Union[U](s = "foo") val u3 = Union[U](b = true) - val v1 = u1.get(Symbol("i")) + val v1 = u1.get("i") typed[Option[Int]](v1) assertEquals(Some(23), v1) - val v2 = u2.get(Symbol("s")) + val v2 = u2.get("s") typed[Option[String]](v2) assertEquals(Some("foo"), v2) - val v3 = u3.get(Symbol("b")) + val v3 = u3.get("b") typed[Option[Boolean]](v3) assertEquals(Some(true), v3) - illTyped(""" - u1.get(Symbol("foo")) - """) + illTyped("""u1.get("foo")""") } @Test @@ -220,16 +216,16 @@ class UnionTests { val u2 = Union[U](s = "foo") val u3 = Union[U](b = true) - type UF = (Witness.`'i`.T, Int) :+: (Witness.`'s`.T, String) :+: (Witness.`'b`.T, Boolean) :+: CNil + type UF = (Witness.`"i"`.T, Int) :+: (Witness.`"s"`.T, String) :+: (Witness.`"b"`.T, Boolean) :+: CNil { val f1 = u1.fields val f2 = u2.fields val f3 = u3.fields - assertTypedEquals(Coproduct[UF](Symbol("i").narrow -> 23), f1) - assertTypedEquals(Coproduct[UF](Symbol("s").narrow -> "foo"), f2) - assertTypedEquals(Coproduct[UF](Symbol("b").narrow -> true), f3) + assertTypedEquals(Coproduct[UF]("i".narrow -> 23), f1) + assertTypedEquals(Coproduct[UF]("s".narrow -> "foo"), f2) + assertTypedEquals(Coproduct[UF]("b".narrow -> true), f3) } type US = Union.`"first" -> Option[Int], "second" -> Option[Boolean], "third" -> Option[String]`.T @@ -262,7 +258,7 @@ class UnionTests { type UV = Coproduct.`Int, String, Boolean`.T - assertTypedEquals(Symbol("i").narrow :: Symbol("s").narrow :: Symbol("b").narrow :: HNil, uf.keys) + assertTypedEquals("i".narrow :: "s".narrow :: "b".narrow :: HNil, uf.keys) assertTypedEquals(Coproduct[UV](23), uf.values(u1)) assertTypedEquals(Coproduct[UV]("foo"), uf.values(u2)) assertTypedEquals(Coproduct[UV](true), uf.values(u3)) @@ -296,19 +292,19 @@ class UnionTests { val m2 = u2.toMap val m3 = u3.toMap - assertTypedEquals(Map[Symbol, Any](Symbol("i") -> 23), m1) - assertTypedEquals(Map[Symbol, Any](Symbol("s") -> "foo"), m2) - assertTypedEquals(Map[Symbol, Any](Symbol("b") -> true), m3) + assertTypedEquals(Map[String, Any]("i" -> 23), m1) + assertTypedEquals(Map[String, Any]("s" -> "foo"), m2) + assertTypedEquals(Map[String, Any]("b" -> true), m3) } { - val m1 = u1.toMap[Symbol, Any] - val m2 = u2.toMap[Symbol, Any] - val m3 = u3.toMap[Symbol, Any] + val m1 = u1.toMap[String, Any] + val m2 = u2.toMap[String, Any] + val m3 = u3.toMap[String, Any] - assertTypedEquals(Map[Symbol, Any](Symbol("i") -> 23), m1) - assertTypedEquals(Map[Symbol, Any](Symbol("s") -> "foo"), m2) - assertTypedEquals(Map[Symbol, Any](Symbol("b") -> true), m3) + assertTypedEquals(Map[String, Any]("i" -> 23), m1) + assertTypedEquals(Map[String, Any]("s" -> "foo"), m2) + assertTypedEquals(Map[String, Any]("b" -> true), m3) } type US = Union.`"first" -> Option[Int], "second" -> Option[Boolean], "third" -> Option[String]`.T @@ -350,7 +346,7 @@ class UnionTests { val u2 = Union[U](s = "foo") val u3 = Union[U](b = true) - type R = Union.`'i -> Boolean, 's -> String, 'b -> String`.T + type R = Union.`"i" -> Boolean, "s" -> String, "b" -> String`.T val res1 = u1.mapValues(f) val res2 = u2.mapValues(f) diff --git a/examples/src/main/scala/shapeless/examples/derivation.scala b/examples/src/main/scala/shapeless/examples/derivation.scala index 42f66ae1b..fa44f00a1 100644 --- a/examples/src/main/scala/shapeless/examples/derivation.scala +++ b/examples/src/main/scala/shapeless/examples/derivation.scala @@ -135,69 +135,50 @@ object TypeClassesDemoAux { } object Show { - def apply[T](implicit st: Lazy[Show[T]]): Show[T] = st.value + def apply[T](implicit show: Show[T]): Show[T] = show - implicit val showString: Show[String] = new Show[String] { - def show(t: String) = t + def instance[T](f: T => String): Show[T] = new Show[T] { + def show(value: T): String = f(value) } - implicit val showBoolean: Show[Boolean] = new Show[Boolean] { - def show(t: Boolean) = t.toString - } + implicit val showString: Show[String] = instance(identity) + implicit val showBoolean: Show[Boolean] = instance(_.toString) implicit def showList[A](implicit showA: Show[A]): Show[List[A]] = new Show[List[A]] { - def show(t: List[A]) = t.map(showA.show).mkString("List(", ", ", ")") + def show(t: List[A]): String = t.map(showA.show).mkString("List(", ", ", ")") } - implicit def deriveHNil: Show[HNil] = - new Show[HNil] { - def show(p: HNil): String = "" - } + implicit val deriveHNil: Show[HNil] = instance(_ => "") + implicit val deriveCNil: Show[CNil] = instance(_ => "") - implicit def deriveHCons[K <: Symbol, V, T <: HList] - (implicit - key: Witness.Aux[K], - sv: Lazy[Show[V]], - st: Lazy[Show[T]] - ): Show[FieldType[K, V] :: T] = - new Show[FieldType[K, V] :: T] { - def show(p: FieldType[K, V] :: T): String = { - val head = s"${key.value.name} = ${sv.value.show(p.head)}" - val tail = st.value.show(p.tail) - if(tail.isEmpty) head else s"$head, $tail" - } - } + implicit def deriveHCons[K <: String, V, T <: HList]( + implicit key: Witness.Aux[K], sv: Lazy[Show[V]], st: Show[T] + ): Show[FieldType[K, V] :: T] = instance { case kv :: t => + val head = s"${key.value} = ${sv.value.show(kv)}" + val tail = st.show(t) + if (tail.isEmpty) head else s"$head, $tail" + } - implicit def deriveCNil: Show[CNil] = - new Show[CNil] { - def show(p: CNil): String = "" + implicit def deriveCCons[K <: String, V, T <: Coproduct]( + implicit key: Witness.Aux[K], sv: Lazy[Show[V]], st: Show[T] + ): Show[FieldType[K, V] :+: T] = instance { c => + // Using match/case + c match { + case Inl(l) => s"${key.value}(${sv.value.show(l)})" + case Inr(r) => st.show(r) } + // Or using eliminate + c.eliminate( + l => s"${key.value}(${sv.value.show(l)})", + r => st.show(r) + ) + } - implicit def deriveCCons[K <: Symbol, V, T <: Coproduct] - (implicit - key: Witness.Aux[K], - sv: Lazy[Show[V]], - st: Lazy[Show[T]] - ): Show[FieldType[K, V] :+: T] = - new Show[FieldType[K, V] :+: T] { - def show(c: FieldType[K, V] :+: T): String = { - //Using match/case - c match { - case Inl(l) => s"${key.value.name}(${sv.value.show(l)})" - case Inr(r) => st.value.show(r) - } - //Or using eliminate - c.eliminate( - l => s"${key.value.name}(${sv.value.show(l)})", - r => st.value.show(r) - ) - } - } - - implicit def deriveInstance[F, G](implicit gen: LabelledGeneric.Aux[F, G], sg: Lazy[Show[G]]): Show[F] = - new Show[F] { - def show(f: F) = sg.value.show(gen.to(f)) - } + implicit def deriveInstance[F, G]( + implicit gen: LabelledGeneric.Aux[F, G], sg: Lazy[Show[G]] + ): Show[F] = instance { f => + sg.value.show(gen.to(f)) + } } trait Show2[T] { diff --git a/examples/src/main/scala/shapeless/examples/labelledgeneric.scala b/examples/src/main/scala/shapeless/examples/labelledgeneric.scala index 90c92060b..0fc17d83f 100644 --- a/examples/src/main/scala/shapeless/examples/labelledgeneric.scala +++ b/examples/src/main/scala/shapeless/examples/labelledgeneric.scala @@ -39,17 +39,17 @@ object LabelledGenericExamples extends App { val rec = bookGen.to(tapl) // Read price field - val currentPrice = rec(Symbol("price")) // Static type is Double + val currentPrice = rec("price") // Static type is Double println("Current price is "+currentPrice) println // Update price field, relying on static type of currentPrice - val updated = bookGen.from(rec.updateWith(Symbol("price"))(_+2.0)) + val updated = bookGen.from(rec.updateWith("price")(_ + 2.0)) println(updated) println // Add a new field, map back into ExtendedBook - val extended = bookExtGen.from(rec + (Symbol("inPrint") ->> true)) // Static type is ExtendedBook + val extended = bookExtGen.from(rec + ("inPrint" ->> true)) // Static type is ExtendedBook println(extended) println @@ -93,11 +93,11 @@ object OldWineNewBottles extends App { val toGen = LabelledGeneric[To] // Define the type of the i field by example - val iField = Field(Symbol("i") ->> 0) + val iField = Field("i" ->> 0) val align = Align[iField.F :: fromGen.Repr, toGen.Repr] - val to = toGen.from(align(Symbol("i") ->> 23 :: fromGen.to(from))) + val to = toGen.from(align("i" ->> 23 :: fromGen.to(from))) println(to) println } diff --git a/examples/src/main/scala/shapeless/examples/partition.scala b/examples/src/main/scala/shapeless/examples/partition.scala index 89104b259..c30153411 100644 --- a/examples/src/main/scala/shapeless/examples/partition.scala +++ b/examples/src/main/scala/shapeless/examples/partition.scala @@ -122,10 +122,10 @@ object ADTPartitionExample extends App { val basket = partitionRecord(fruits) // Confirm that expected record values are present (and not unexpected ones). - typed[List[Apple]](basket(Symbol("Apple"))) - typed[List[Pear]](basket(Symbol("Pear"))) - illTyped("""basket(Symbol("Burger"))""") + typed[List[Apple]](basket("Apple")) + typed[List[Pear]](basket("Pear")) + illTyped("""basket("Burger")""") - assert(basket(Symbol("Apple")) == expectedApples) - assert(basket(Symbol("Pear")) == expectedPears) + assert(basket("Apple") == expectedApples) + assert(basket("Pear") == expectedPears) } diff --git a/examples/src/main/scala/shapeless/examples/recordsubtyping.scala b/examples/src/main/scala/shapeless/examples/recordsubtyping.scala index b0dbf90e3..da1b3bd4f 100644 --- a/examples/src/main/scala/shapeless/examples/recordsubtyping.scala +++ b/examples/src/main/scala/shapeless/examples/recordsubtyping.scala @@ -23,11 +23,11 @@ object recordsubtyping extends App{ val employeeId = Record(firstName = "Jane", lastName = "Doe", title = "software engineer") val employee1 = Record(id = employeeId, city = new PopulatedCity("San Francisco", 2), company = "Foo Inc.") - val employee2 = employee1.updated(Symbol("company"), "Bar Inc.") - val employee3 = employee1.updated(Symbol("city"), new PopulatedCity("Chernobyl", 1) ) + val employee2 = employee1.updated("company", "Bar Inc.") + val employee3 = employee1.updated("city", new PopulatedCity("Chernobyl", 1) ) - type PersonId = Record.`'firstName -> String, 'lastName -> String`.T - type Person = Record.`'id -> PersonId, 'city -> City`.T + type PersonId = Record.`"firstName" -> String, "lastName" -> String`.T + type Person = Record.`"id" -> PersonId, "city" -> City`.T val somePerson: Person = Record(id = Record(firstName = "Jane", lastName = "Doe"), city = new City("San Francisco")) @@ -59,7 +59,7 @@ object recordsubtyping extends App{ //transform Person structure preserving Employee shape //this is only possible if no nominal subtyping relation is present between the record fields ('city' in this case) - val noNominalSubtypingEmployee = employee1.updateWith(Symbol("city"))(c => c: City) + val noNominalSubtypingEmployee = employee1.updateWith("city")(c => c: City) def transform[L <: HList, X <: HList, Y <: HList, O <: HList](input: L)(transform: X => Y) (implicit diff --git a/examples/src/main/scala/shapeless/examples/recursionschemes.scala b/examples/src/main/scala/shapeless/examples/recursionschemes.scala index 6e8191017..6289d0776 100644 --- a/examples/src/main/scala/shapeless/examples/recursionschemes.scala +++ b/examples/src/main/scala/shapeless/examples/recursionschemes.scala @@ -23,7 +23,6 @@ import shapeless.ops.hlist.Tupler import shapeless.ops.union.Selector import shapeless.record._ import shapeless.syntax.DynamicRecordOps -import shapeless.tag.@@ /** * Example adapted from the talk "Recursion Schemes by Example" by Tim Williams. @@ -208,7 +207,7 @@ package recursionschemes { object F extends Dynamic { import shapeless.ops.record.Values - trait Extractor[K <: Symbol] { + trait Extractor[K <: String] { object as { def unapply[C <: Coproduct, R <: HList](c: C)( implicit sel: Selector.Aux[C, K, R] @@ -228,9 +227,9 @@ package recursionschemes { } } - private val extractor = new Extractor[Symbol] { } - def selectDynamic(name: String): Extractor[Symbol @@ name.type] = - extractor.asInstanceOf[Extractor[Symbol @@ name.type]] + private val extractor = new Extractor[String] { } + def selectDynamic(name: String): Extractor[name.type] = + extractor.asInstanceOf[Extractor[name.type]] } } diff --git a/examples/src/main/scala/shapeless/examples/sexp.scala b/examples/src/main/scala/shapeless/examples/sexp.scala index cea7ae15f..6ab3ebf23 100644 --- a/examples/src/main/scala/shapeless/examples/sexp.scala +++ b/examples/src/main/scala/shapeless/examples/sexp.scala @@ -287,72 +287,63 @@ object SexpUserConvert { object SexpConvert { def apply[T](implicit st: Lazy[SexpConvert[T]]): SexpConvert[T] = st.value - implicit def deriveHNil: SexpConvert[HNil] = - new SexpConvert[HNil] { - def deser(s: Sexp) = if (s == SexpNil) Some(HNil) else None - def ser(n: HNil) = SexpNil + implicit val deriveHNil: SexpConvert[HNil] = new SexpConvert[HNil] { + def deser(s: Sexp) = if (s == SexpNil) Some(HNil) else None + def ser(n: HNil) = SexpNil + } + + implicit def deriveHCons[K <: String, V, T <: HList]( + implicit key: Witness.Aux[K], scv: Lazy[SexpConvert[V]], sct: SexpConvert[T] + ): SexpConvert[FieldType[K, V] :: T] = new SexpConvert[FieldType[K, V] :: T] { + def deser(s: Sexp): Option[FieldType[K, V] :: T] = s match { + case SexpProp((label, car), cdr) if label == key.value => + for { + front <- scv.value.deser(car) + back <- sct.deser(cdr) + } yield field[K](front) :: back + + case _ => + println("PRODUCT MISS = " + s) + None } - implicit def deriveHCons[K <: Symbol, V, T <: HList] - (implicit - key: Witness.Aux[K], - scv: Lazy[SexpConvert[V]], - sct: Lazy[SexpConvert[T]] - ): SexpConvert[FieldType[K, V] :: T] = - new SexpConvert[FieldType[K, V] :: T] { - def deser(s: Sexp): Option[FieldType[K, V] :: T] = s match { - case SexpProp((label, car), cdr) if label == key.value.name => - for { - front <- scv.value.deser(car) - back <- sct.value.deser(cdr) - } yield field[K](front) :: back - - case _ => - println("PRODUCT MISS = " + s) - None - } - - def ser(ft: FieldType[K, V] :: T): Sexp = { - val car = SexpProp(key.value.name, scv.value.ser(ft.head)) - sct.value.ser(ft.tail) match { - case SexpNil => car - case cdr => SexpCons(car, cdr) - } - } + def ser(ft: FieldType[K, V] :: T): Sexp = { + val car = SexpProp(key.value, scv.value.ser(ft.head)) + sct.ser(ft.tail) match { + case SexpNil => car + case cdr => SexpCons(car, cdr) } + } + } - implicit def deriveCNil: SexpConvert[CNil] = new SexpConvert[CNil] { + implicit val deriveCNil: SexpConvert[CNil] = new SexpConvert[CNil] { def deser(s: Sexp): Option[CNil] = None def ser(t: CNil) = SexpNil } - implicit def deriveCCons[K <: Symbol, V, T <: Coproduct] - (implicit - key: Witness.Aux[K], - scv: Lazy[SexpConvert[V]], - sct: Lazy[SexpConvert[T]] - ): SexpConvert[FieldType[K, V] :+: T] = - new SexpConvert[FieldType[K, V] :+: T] { - def deser(s: Sexp): Option[FieldType[K, V] :+: T] = s match { - case SexpCons(SexpAtom(impl), cdr) if impl == key.value.name => - scv.value.deser(cdr).map(v => Inl(field[K](v))) - case SexpCons(SexpAtom(impl), cdr) => - sct.value.deser(s).map(Inr(_)) - case _ => - println("COPRODUCT MISS " + s) - None - } - - def ser(lr: FieldType[K, V] :+: T): Sexp = lr match { - case Inl(l) => SexpCons(SexpAtom(key.value.name), scv.value.ser(l)) - case Inr(r) => sct.value.ser(r) - } - } + implicit def deriveCCons[K <: String, V, T <: Coproduct]( + implicit key: Witness.Aux[K], scv: Lazy[SexpConvert[V]], sct: SexpConvert[T] + ): SexpConvert[FieldType[K, V] :+: T] = new SexpConvert[FieldType[K, V] :+: T] { + def deser(s: Sexp): Option[FieldType[K, V] :+: T] = s match { + case SexpCons(SexpAtom(impl), cdr) if impl == key.value => + scv.value.deser(cdr).map(v => Inl(field[K](v))) + case SexpCons(SexpAtom(impl), cdr) => + sct.deser(s).map(Inr(_)) + case _ => + println("COPRODUCT MISS " + s) + None + } - implicit def deriveInstance[F, G] - (implicit gen: LabelledGeneric.Aux[F, G], sg: Lazy[SexpConvert[G]]): SexpConvert[F] = - new SexpConvert[F] { - def deser(s: Sexp): Option[F] = sg.value.deser(s).map(gen.from) - def ser(t: F): Sexp = sg.value.ser(gen.to(t)) - } + def ser(lr: FieldType[K, V] :+: T): Sexp = lr match { + case Inl(l) => SexpCons(SexpAtom(key.value), scv.value.ser(l)) + case Inr(r) => sct.ser(r) + } + } + + implicit def deriveInstance[F, G]( + implicit gen: LabelledGeneric.Aux[F, G], sg: Lazy[SexpConvert[G]] + ): SexpConvert[F] = new SexpConvert[F] { + def deser(s: Sexp): Option[F] = sg.value.deser(s).map(gen.from) + def ser(t: F): Sexp = sg.value.ser(gen.to(t)) + } } diff --git a/examples/src/main/scala/shapeless/examples/unwrapped.scala b/examples/src/main/scala/shapeless/examples/unwrapped.scala index 8d8c90b70..d1ba4a08b 100644 --- a/examples/src/main/scala/shapeless/examples/unwrapped.scala +++ b/examples/src/main/scala/shapeless/examples/unwrapped.scala @@ -43,52 +43,49 @@ object UnwrappedExamples { // doing with it is writing a system to automatically generate serialization // codecs. For example: trait Encode[-T] { - def toJson(t: T): String = - fields(t).map { case (k, v) => s""""$k":$v""" }.mkString("{", ",", "}") + def toJson(t: T): String = fields(t).map { case (k, v) => s""""$k":$v""" }.mkString("{", ",", "}") def fields(t: T): Map[String, String] } + object Encode { - implicit def encodeHNil = new Encode[HNil] { - def fields(hnil: HNil) = Map.empty + def instance[T](f: T => Map[String, String]): Encode[T] = new Encode[T] { + def fields(value: T): Map[String, String] = f(value) } - implicit def encodeHCons[ - K <: Symbol, - V, - Rest <: HList - ](implicit - key: Witness.Aux[K], - encodeV: Lazy[EncodeValue[V]], - encodeRest: Strict[Encode[Rest]] - ) = new Encode[FieldType[K, V] :: Rest] { - def fields(hl: FieldType[K, V] :: Rest) = - encodeRest.value.fields(hl.tail) + - (key.value.name -> encodeV.value.toJsonFragment(hl.head)) + + implicit val encodeHNil: Encode[HNil] = + instance(_ => Map.empty) + + implicit def encodeHCons[K <: String, V, Rest <: HList]( + implicit key: Witness.Aux[K], encodeV: Lazy[EncodeValue[V]], encodeRest: Encode[Rest] + ): Encode[FieldType[K, V] :: Rest] = instance { case h :: t => + encodeRest.fields(t) + (key.value -> encodeV.value.toJsonFragment(h)) } + // the magic one! - implicit def encodeGeneric[T, Repr](implicit - gen: LabelledGeneric.Aux[T, Repr], - encodeRepr: Lazy[Encode[Repr]] - ) = new Encode[T] { - def fields(t: T) = encodeRepr.value.fields(gen.to(t)) + implicit def encodeGeneric[T, Repr]( + implicit gen: LabelledGeneric.Aux[T, Repr], encodeRepr: Lazy[Encode[Repr]] + ): Encode[T] = instance { value => + encodeRepr.value.fields(gen.to(value)) } } trait EncodeValue[-T] { def toJsonFragment(t: T): String } + object EncodeValue { - implicit lazy val encodeString = - new EncodeValue[String] { - def toJsonFragment(s: String) = s""""$s"""" - } - implicit lazy val encodeInt = - new EncodeValue[Int] { - def toJsonFragment(i: Int) = s"""$i""" - } - implicit def encodeRoot[T](implicit r: Lazy[Encode[T]]) = - new EncodeValue[T] { - def toJsonFragment(t: T) = r.value.toJson(t) - } + def instance[T](f: T => String): EncodeValue[T] = new EncodeValue[T] { + def toJsonFragment(value: T): String = f(value) + } + + implicit val encodeString: EncodeValue[String] = + instance(str => s""""$str"""") + + implicit val encodeInt: EncodeValue[Int] = + instance(_.toString) + + implicit def encodeRoot[T](implicit r: Lazy[Encode[T]]): EncodeValue[T] = + instance(value => r.value.toJson(value)) } // OK! Yay! Let's try it out! @@ -104,36 +101,35 @@ object UnwrappedExamples { // through the wrapper types: trait Encode2[-T] { - def toJson(t: T): String = - fields(t).map { case (k, v) => s""""$k":$v""" }.mkString("{", ",", "}") + def toJson(t: T): String = fields(t).map { case (k, v) => s""""$k":$v""" }.mkString("{", ",", "}") def fields(t: T): Map[String, String] } + object Encode2 { - implicit def encodeHNil = new Encode2[HNil] { - def fields(hnil: HNil) = Map.empty + def instance[T](f: T => Map[String, String]): Encode2[T] = new Encode2[T] { + def fields(value: T): Map[String, String] = f(value) } - implicit def encodeHCons[ - K <: Symbol, - V, - U, - Rest <: HList - ](implicit + + implicit val encodeHNil: Encode2[HNil] = + instance(_ => Map.empty) + + implicit def encodeHCons[K <: String, V, U, Rest <: HList]( + implicit key: Witness.Aux[K], - uw: Strict[Unwrapped.Aux[V, U]], + uw: Unwrapped.Aux[V, U], encodeV: Lazy[EncodeValue[U]], - encodeRest: Strict[Encode2[Rest]] - ) = new Encode2[FieldType[K, V] :: Rest] { - def fields(hl: FieldType[K, V] :: Rest) = - encodeRest.value.fields(hl.tail) + - (key.value.name -> encodeV.value.toJsonFragment(uw.value.unwrap(hl.head))) + encodeRest: Encode2[Rest] + ): Encode2[FieldType[K, V] :: Rest] = instance { case h :: t => + encodeRest.fields(t) + (key.value -> encodeV.value.toJsonFragment(uw.unwrap(h))) } - implicit def encodeGeneric[T, Repr](implicit - gen: LabelledGeneric.Aux[T, Repr], - encodeRepr: Lazy[Encode2[Repr]] - ) = new Encode2[T] { - def fields(t: T) = encodeRepr.value.fields(gen.to(t)) + + implicit def encodeGeneric[T, Repr]( + implicit gen: LabelledGeneric.Aux[T, Repr], encodeRepr: Lazy[Encode2[Repr]] + ): Encode2[T] = instance { value => + encodeRepr.value.fields(gen.to(value)) } } + // OK! Let's try again val encoder2 = the[Encode2[User]] println(encoder2.toJson(user)) @@ -144,5 +140,4 @@ object UnwrappedExamples { // Note that there are a few more places you'd probably want to insert unwrapping // if this was a real codec generator (basically, you'd likely want to remove // wrappers on objects too, not just wrappers on their fields) - } From c9c12168b9075966a5d6b71b4dd99e20de0d1319 Mon Sep 17 00:00:00 2001 From: Georgi Krastev Date: Fri, 10 Apr 2020 15:48:43 +0200 Subject: [PATCH 02/17] Rename DefaultSymbolicLabelling to Labelling --- .../test/scala/shapeless/serialization.scala | 4 +- core/src/main/scala/shapeless/default.scala | 2 +- core/src/main/scala/shapeless/generic.scala | 46 +++++++++---------- core/src/main/scala/shapeless/labelled.scala | 21 ++++----- 4 files changed, 35 insertions(+), 38 deletions(-) diff --git a/core/jvm/src/test/scala/shapeless/serialization.scala b/core/jvm/src/test/scala/shapeless/serialization.scala index ab7f9e9f6..792d2f67e 100644 --- a/core/jvm/src/test/scala/shapeless/serialization.scala +++ b/core/jvm/src/test/scala/shapeless/serialization.scala @@ -950,8 +950,8 @@ class SerializationTests { assertSerializable(Generic[(Int, String, Boolean)]) assertSerializable(Generic[Option[Int]]) - assertSerializable(DefaultSymbolicLabelling[(Int, String, Boolean)]) - assertSerializable(DefaultSymbolicLabelling[Option[Int]]) + assertSerializable(Labelling[(Int, String, Boolean)]) + assertSerializable(Labelling[Option[Int]]) assertSerializable(LabelledGeneric[(Int, String, Boolean)]) assertSerializable(LabelledGeneric[Option[Int]]) diff --git a/core/src/main/scala/shapeless/default.scala b/core/src/main/scala/shapeless/default.scala index a1dbcaa04..fbffbc1f6 100644 --- a/core/src/main/scala/shapeless/default.scala +++ b/core/src/main/scala/shapeless/default.scala @@ -119,7 +119,7 @@ object Default { implicit def asRecord[T, Labels <: HList, Options <: HList]( implicit default: Default.Aux[T, Options], - labelling: DefaultSymbolicLabelling.Aux[T, Labels], + labelling: Labelling.Aux[T, Labels], helper: Helper[Options, Labels] ): Aux[T, helper.Out] = new AsRecord[T] { type Out = helper.Out diff --git a/core/src/main/scala/shapeless/generic.scala b/core/src/main/scala/shapeless/generic.scala index 612c49ce6..0d3980c09 100644 --- a/core/src/main/scala/shapeless/generic.scala +++ b/core/src/main/scala/shapeless/generic.scala @@ -226,32 +226,30 @@ object LabelledGeneric { def apply[T](implicit lgen: LabelledGeneric[T]): Aux[T, lgen.Repr] = lgen /** Handles the Product case (fields in a case class, for example) */ - implicit def materializeProduct[T, K <: HList, V <: HList, R <: HList] - (implicit - lab: DefaultSymbolicLabelling.Aux[T, K], - gen: Generic.Aux[T, V], - zip: hlist.ZipWithKeys.Aux[K, V, R], - ev: R <:< V - ): Aux[T, R] = - new LabelledGeneric[T] { - type Repr = R - def to(t: T): Repr = zip(gen.to(t)) - def from(r: Repr): T = gen.from(r) - } + implicit def materializeProduct[T, K <: HList, V <: HList, R <: HList]( + implicit + lab: Labelling.Aux[T, K], + gen: Generic.Aux[T, V], + zip: hlist.ZipWithKeys.Aux[K, V, R], + ev: R <:< V + ): Aux[T, R] = new LabelledGeneric[T] { + type Repr = R + def to(t: T): Repr = zip(gen.to(t)) + def from(r: Repr): T = gen.from(r) + } /** Handles the Coproduct case (specifying subclasses derive from a sealed trait) */ - implicit def materializeCoproduct[T, K <: HList, V <: Coproduct, R <: Coproduct] - (implicit - lab: DefaultSymbolicLabelling.Aux[T, K], - gen: Generic.Aux[T, V], - zip: coproduct.ZipWithKeys.Aux[K, V, R], - ev: R <:< V - ): Aux[T, R] = - new LabelledGeneric[T] { - type Repr = R - def to(t: T): Repr = zip(gen.to(t)) - def from(r: Repr): T = gen.from(r) - } + implicit def materializeCoproduct[T, K <: HList, V <: Coproduct, R <: Coproduct]( + implicit + lab: Labelling.Aux[T, K], + gen: Generic.Aux[T, V], + zip: coproduct.ZipWithKeys.Aux[K, V, R], + ev: R <:< V + ): Aux[T, R] = new LabelledGeneric[T] { + type Repr = R + def to(t: T): Repr = zip(gen.to(t)) + def from(r: Repr): T = gen.from(r) + } } class nonGeneric extends StaticAnnotation diff --git a/core/src/main/scala/shapeless/labelled.scala b/core/src/main/scala/shapeless/labelled.scala index 8b94856c3..765a68305 100644 --- a/core/src/main/scala/shapeless/labelled.scala +++ b/core/src/main/scala/shapeless/labelled.scala @@ -37,21 +37,20 @@ object labelled { } } -trait DefaultSymbolicLabelling[T] extends DepFn0 with Serializable { type Out <: HList } +trait Labelling[T] extends DepFn0 with Serializable { type Out <: HList } -object DefaultSymbolicLabelling { - type Aux[T, Out0] = DefaultSymbolicLabelling[T] { type Out = Out0 } +object Labelling { + type Aux[T, Out0] = Labelling[T] { type Out = Out0 } - def apply[T](implicit lab: DefaultSymbolicLabelling[T]): Aux[T, lab.Out] = lab + def apply[T](implicit lab: Labelling[T]): Aux[T, lab.Out] = lab - implicit def mkDefaultSymbolicLabelling[T]: DefaultSymbolicLabelling[T] = + implicit def mkDefaultSymbolicLabelling[T]: Labelling[T] = macro LabelledMacros.mkDefaultSymbolicLabellingImpl[T] - def instance[T, L <: HList](labels: L): Aux[T, L] = - new DefaultSymbolicLabelling[T] { - type Out = L - def apply(): L = labels - } + def instance[T, L <: HList](labels: L): Aux[T, L] = new Labelling[T] { + type Out = L + def apply(): L = labels + } } /** @@ -115,7 +114,7 @@ class LabelledMacros(val c: whitebox.Context) extends SingletonTypeUtils with Ca val labelsType = mkHListTpe(labels.map(constantType)) val labelsValue = mkHListValue(labels.map(Literal.apply)) - val labelling = objectRef[DefaultSymbolicLabelling.type] + val labelling = objectRef[Labelling.type] q"$labelling.instance[$tpe, $labelsType]($labelsValue.asInstanceOf[$labelsType])" } From ca7b67cc4ca595ddd069e54292870d79664e7339 Mon Sep 17 00:00:00 2001 From: Georgi Krastev Date: Fri, 10 Apr 2020 17:03:13 +0200 Subject: [PATCH 03/17] Fix parsing of complex types in Record macro --- core/src/main/scala/shapeless/labelled.scala | 37 ++++++++++++++------ core/src/test/scala/shapeless/records.scala | 4 +++ 2 files changed, 31 insertions(+), 10 deletions(-) diff --git a/core/src/main/scala/shapeless/labelled.scala b/core/src/main/scala/shapeless/labelled.scala index 765a68305..9df3c9b1b 100644 --- a/core/src/main/scala/shapeless/labelled.scala +++ b/core/src/main/scala/shapeless/labelled.scala @@ -94,28 +94,45 @@ class LabelledMacros(val c: whitebox.Context) extends SingletonTypeUtils with Ca import c.universe._ import internal.constantType - private def commaSeparated(str: String): Array[String] = { - val trimmed = str.trim - if (trimmed.isEmpty) Array.empty else trimmed.split(',') + private def commaSeparated(str: String): List[String] = { + val builder = List.newBuilder[String] + var i, j, k = 0 + while (j < str.length) { + str.charAt(j) match { + case ',' if k == 0 => + builder += str.substring(i, j).trim + i = j + 1 + case '(' | '[' => + k += 1 + case ')' | ']' => + k = k - 1 max 0 + case _ => + } + + j += 1 + } + + val last = str.substring(i, j).trim + if (last.nonEmpty) builder += last + builder.result() } private def parseTypeOrFail(tpe: String): Type = - parseType(tpe.trim).getOrElse(c.abort(c.enclosingPosition, s"Malformed literal or standard type $tpe")) + parseType(tpe).getOrElse(c.abort(c.enclosingPosition, s"Malformed literal or standard type $tpe")) private def parseLiteralTypeOrFail(tpe: String): Type = - parseLiteralType(tpe.trim).getOrElse(c.abort(c.enclosingPosition, s"Malformed literal type $tpe")) + parseLiteralType(tpe).getOrElse(c.abort(c.enclosingPosition, s"Malformed literal type $tpe")) def mkDefaultSymbolicLabellingImpl[T: WeakTypeTag]: Tree = { val tpe = weakTypeOf[T] val labels: List[Constant] = - if (isProduct(tpe)) fieldsOf(tpe).map(f => nameAsValue(f._1)) + if (isProduct(tpe)) fieldsOf(tpe).map { case (f, _) => nameAsValue(f) } else if (isCoproduct(tpe)) ctorsOf(tpe).map(c => nameAsValue(nameOf(c))) else c.abort(c.enclosingPosition, s"$tpe is not case class like or the root of a sealed family of types") val labelsType = mkHListTpe(labels.map(constantType)) val labelsValue = mkHListValue(labels.map(Literal.apply)) - val labelling = objectRef[Labelling.type] - q"$labelling.instance[$tpe, $labelsType]($labelsValue.asInstanceOf[$labelsType])" + q"${reify(Labelling)}.instance[$tpe, $labelsType]($labelsValue.asInstanceOf[$labelsType])" } def recordTypeImpl(tpeSelector: Tree): Tree = @@ -129,8 +146,8 @@ class LabelledMacros(val c: whitebox.Context) extends SingletonTypeUtils with Ca appliedType(fieldTypeTpe, List(keyTpe, valueTpe)) val q"${tpeString: String}" = tpeSelector - val fields = commaSeparated(tpeString).map(_.trim.split("->") match { - case Array(key, value) => (parseLiteralTypeOrFail(key), parseTypeOrFail(value)) + val fields = commaSeparated(tpeString).map(_.split("->") match { + case Array(key, value) => (parseLiteralTypeOrFail(key.trim), parseTypeOrFail(value.trim)) case _ => c.abort(c.enclosingPosition, s"Malformed $variety type $tpeString") }) diff --git a/core/src/test/scala/shapeless/records.scala b/core/src/test/scala/shapeless/records.scala index 341582b67..c9ab17ac0 100644 --- a/core/src/test/scala/shapeless/records.scala +++ b/core/src/test/scala/shapeless/records.scala @@ -43,6 +43,10 @@ class RecordTests { case class Bar(a: Int, b: String) + type MapRec = Record.`'map -> Map[String, Int]`.T + type TupleRec = Record.`'tuple -> (String, Int)`.T + type ComplexRec = Record.`'map -> Map[String, Int], 'tuple -> (String, Int)`.T + @Test def testGet: Unit = { val r1 = From 70076c2cc79eda17bf31c36f2058de4f19bba83f Mon Sep 17 00:00:00 2001 From: Georgi Krastev Date: Sat, 11 Apr 2020 06:14:29 +0200 Subject: [PATCH 04/17] Refactor labelled --- core/src/main/scala/shapeless/coproduct.scala | 2 +- core/src/main/scala/shapeless/hlists.scala | 2 +- core/src/main/scala/shapeless/labelled.scala | 90 +++++++++---------- core/src/main/scala/shapeless/records.scala | 2 +- core/src/main/scala/shapeless/unions.scala | 2 +- .../shapeless/examples/recursionschemes.scala | 77 +++++++++------- 6 files changed, 91 insertions(+), 84 deletions(-) diff --git a/core/src/main/scala/shapeless/coproduct.scala b/core/src/main/scala/shapeless/coproduct.scala index 05b776740..94929dd3e 100644 --- a/core/src/main/scala/shapeless/coproduct.scala +++ b/core/src/main/scala/shapeless/coproduct.scala @@ -156,7 +156,7 @@ object Coproduct extends Dynamic { * type TwoTrueStr = Coproduct.`2, true, "str"`.T * }}} */ - def selectDynamic(tpeSelector: String): Any = macro LabelledMacros.coproductTypeImpl + def selectDynamic(tpeSelector: String): Any = macro LabelledMacros.coproductType /** Allows to inject a runtime value of type `Any` in a `Coproduct` */ def runtimeInject[C <: Coproduct](x: Any)(implicit rinj: RuntimeInject[C]): Option[C] = rinj(x) diff --git a/core/src/main/scala/shapeless/hlists.scala b/core/src/main/scala/shapeless/hlists.scala index ab378462c..0611e7e2e 100644 --- a/core/src/main/scala/shapeless/hlists.scala +++ b/core/src/main/scala/shapeless/hlists.scala @@ -113,7 +113,7 @@ object HList extends Dynamic { * type TwoTrueStr = HList.`2, true, "str"`.T * }}} */ - def selectDynamic(tpeSelector: String): Any = macro LabelledMacros.hlistTypeImpl + def selectDynamic(tpeSelector: String): Any = macro LabelledMacros.hlistType @tailrec def unsafeGet(l: HList, i: Int): Any = diff --git a/core/src/main/scala/shapeless/labelled.scala b/core/src/main/scala/shapeless/labelled.scala index 9df3c9b1b..2f7baf4b2 100644 --- a/core/src/main/scala/shapeless/labelled.scala +++ b/core/src/main/scala/shapeless/labelled.scala @@ -17,23 +17,18 @@ package shapeless import scala.language.experimental.macros - import scala.reflect.macros.whitebox object labelled { - /** - * The type of fields with keys of singleton type `K` and value type `V`. - */ + + /** The type of fields with keys of singleton type `K` and value type `V`. */ type FieldType[K, +V] = V with KeyTag[K, V] trait KeyTag[K, +V] - /** - * Yields a result encoding the supplied value with the singleton type `K` of its key. - */ - def field[K] = new FieldBuilder[K] - - class FieldBuilder[K] { - def apply[V](v : V): FieldType[K, V] = v.asInstanceOf[FieldType[K, V]] + /** Yields a result encoding the supplied value with the singleton type `K` of its key. */ + def field[K]: FieldBuilder[K] = new FieldBuilder(true) + class FieldBuilder[K](private val dummy: Boolean) extends AnyVal { + def apply[V](v: V): FieldType[K, V] = v.asInstanceOf[FieldType[K, V]] } } @@ -41,11 +36,10 @@ trait Labelling[T] extends DepFn0 with Serializable { type Out <: HList } object Labelling { type Aux[T, Out0] = Labelling[T] { type Out = Out0 } - def apply[T](implicit lab: Labelling[T]): Aux[T, lab.Out] = lab - implicit def mkDefaultSymbolicLabelling[T]: Labelling[T] = - macro LabelledMacros.mkDefaultSymbolicLabellingImpl[T] + implicit def mkLabelling[T]: Labelling[T] = + macro LabelledMacros.mkLabelling[T] def instance[T, L <: HList](labels: L): Aux[T, L] = new Labelling[T] { type Out = L @@ -62,15 +56,17 @@ object Labelling { trait FieldPoly extends Poly1 { import labelled._ - class FieldCaseBuilder[A, T] { - def apply[Res](fn: A => Res) = new Case[FieldType[T, A]] { - type Result = FieldType[T, Res] - val value: (A :: HNil) => FieldType[T, Res] = - (l: A :: HNil) => field[T](fn(l.head)) - } + final class FieldCaseBuilder[A, T] { + def apply[Res](fn: A => Res): Case.Aux[FieldType[T, A], FieldType[T, Res]] = + new Case[FieldType[T, A]] { + type Result = FieldType[T, Res] + val value: (A :: HNil) => FieldType[T, Res] = + l => field[T](fn(l.head)) + } } - def atField[A](w: Witness) = new FieldCaseBuilder[A, w.T] + def atField[A](w: Witness): FieldCaseBuilder[A, w.T] = + new FieldCaseBuilder } /** @@ -85,7 +81,6 @@ trait FieldOf[V] { import labelled._ type F = FieldType[this.type, V] - def ->>(v: V): FieldType[this.type, V] = field[this.type](v) } @@ -118,56 +113,55 @@ class LabelledMacros(val c: whitebox.Context) extends SingletonTypeUtils with Ca } private def parseTypeOrFail(tpe: String): Type = - parseType(tpe).getOrElse(c.abort(c.enclosingPosition, s"Malformed literal or standard type $tpe")) + parseType(tpe).getOrElse(abort(s"Malformed literal or standard type $tpe")) private def parseLiteralTypeOrFail(tpe: String): Type = - parseLiteralType(tpe).getOrElse(c.abort(c.enclosingPosition, s"Malformed literal type $tpe")) + parseLiteralType(tpe).getOrElse(abort(s"Malformed literal type $tpe")) - def mkDefaultSymbolicLabellingImpl[T: WeakTypeTag]: Tree = { + def mkLabelling[T: WeakTypeTag]: Tree = { val tpe = weakTypeOf[T] val labels: List[Constant] = if (isProduct(tpe)) fieldsOf(tpe).map { case (f, _) => nameAsValue(f) } else if (isCoproduct(tpe)) ctorsOf(tpe).map(c => nameAsValue(nameOf(c))) - else c.abort(c.enclosingPosition, s"$tpe is not case class like or the root of a sealed family of types") + else abort(s"$tpe is not case class like or the root of a sealed family of types") val labelsType = mkHListTpe(labels.map(constantType)) val labelsValue = mkHListValue(labels.map(Literal.apply)) q"${reify(Labelling)}.instance[$tpe, $labelsType]($labelsValue.asInstanceOf[$labelsType])" } - def recordTypeImpl(tpeSelector: Tree): Tree = - labelledTypeImpl(tpeSelector, "record", hnilTpe, hconsTpe) - - def unionTypeImpl(tpeSelector: Tree): Tree = - labelledTypeImpl(tpeSelector, "union", cnilTpe, cconsTpe) + def recordType(tpeSelector: Tree): Tree = + labelledType(tpeSelector, "record", hnilTpe, hconsTpe) - def labelledTypeImpl(tpeSelector: Tree, variety: String, nilTpe: Type, consTpe: Type): Tree = { - def mkFieldTpe(keyTpe: Type, valueTpe: Type): Type = - appliedType(fieldTypeTpe, List(keyTpe, valueTpe)) + def unionType(tpeSelector: Tree): Tree = + labelledType(tpeSelector, "union", cnilTpe, cconsTpe) + def labelledType(tpeSelector: Tree, variety: String, nilTpe: Type, consTpe: Type): Tree = { val q"${tpeString: String}" = tpeSelector - val fields = commaSeparated(tpeString).map(_.split("->") match { - case Array(key, value) => (parseLiteralTypeOrFail(key.trim), parseTypeOrFail(value.trim)) - case _ => c.abort(c.enclosingPosition, s"Malformed $variety type $tpeString") - }) - - val labelledTpe = fields.foldRight(nilTpe) { case ((key, value), acc) => - appliedType(consTpe, List(mkFieldTpe(key, value), acc)) + val labelledTpe = commaSeparated(tpeString).foldRight(nilTpe) { (element, acc) => + element.split("->") match { + case Array(key, value) => + val keyTpe = parseLiteralTypeOrFail(key.trim) + val valueTpe = parseTypeOrFail(value.trim) + appliedType(consTpe, appliedType(fieldTypeTpe, keyTpe, valueTpe), acc) + case _ => + abort(s"Malformed $variety type $tpeString") + } } typeCarrier(labelledTpe) } - def hlistTypeImpl(tpeSelector: Tree): Tree = - nonLabelledTypeImpl(tpeSelector, hnilTpe, hconsTpe) + def hlistType(tpeSelector: Tree): Tree = + nonLabelledType(tpeSelector, hnilTpe, hconsTpe) - def coproductTypeImpl(tpeSelector: Tree): Tree = - nonLabelledTypeImpl(tpeSelector, cnilTpe, cconsTpe) + def coproductType(tpeSelector: Tree): Tree = + nonLabelledType(tpeSelector, cnilTpe, cconsTpe) - def nonLabelledTypeImpl(tpeSelector: Tree, nilTpe: Type, consTpe: Type): Tree = { + def nonLabelledType(tpeSelector: Tree, nilTpe: Type, consTpe: Type): Tree = { val q"${tpeString: String}" = tpeSelector - val tpe = commaSeparated(tpeString).foldRight(nilTpe) { case (element, acc) => - appliedType(consTpe, List(parseTypeOrFail(element), acc)) + val tpe = commaSeparated(tpeString).foldRight(nilTpe) { (element, acc) => + appliedType(consTpe, parseTypeOrFail(element), acc) } typeCarrier(tpe) diff --git a/core/src/main/scala/shapeless/records.scala b/core/src/main/scala/shapeless/records.scala index 5786a525f..ed8176fe1 100644 --- a/core/src/main/scala/shapeless/records.scala +++ b/core/src/main/scala/shapeless/records.scala @@ -58,7 +58,7 @@ object record { object Record extends Dynamic { def applyDynamic(method: String)(rec: Any*): HList = macro RecordMacros.mkRecordEmptyImpl def applyDynamicNamed(method: String)(rec: Any*): HList = macro RecordMacros.mkRecordNamedImpl - def selectDynamic(tpeSelector: String): Any = macro LabelledMacros.recordTypeImpl + def selectDynamic(tpeSelector: String): Any = macro LabelledMacros.recordType } } diff --git a/core/src/main/scala/shapeless/unions.scala b/core/src/main/scala/shapeless/unions.scala index 9cb201624..3cf2c3be7 100644 --- a/core/src/main/scala/shapeless/unions.scala +++ b/core/src/main/scala/shapeless/unions.scala @@ -52,7 +52,7 @@ object union { */ object Union extends Dynamic { def applyDynamicNamed[U <: Coproduct](method: String)(elems: Any*): U = macro UnionMacros.mkUnionNamedImpl[U] - def selectDynamic(tpeSelector: String): Any = macro LabelledMacros.unionTypeImpl + def selectDynamic(tpeSelector: String): Any = macro LabelledMacros.unionType } } diff --git a/examples/src/main/scala/shapeless/examples/recursionschemes.scala b/examples/src/main/scala/shapeless/examples/recursionschemes.scala index 6289d0776..dab8b2622 100644 --- a/examples/src/main/scala/shapeless/examples/recursionschemes.scala +++ b/examples/src/main/scala/shapeless/examples/recursionschemes.scala @@ -249,7 +249,9 @@ package recursionschemes { trait RecCoproduct[T, U] extends Rec[T, U] { type F[_] <: Coproduct } object Rec extends Rec1 { - implicit def reflexive[T] = new Rec[T, T] { + implicit def reflexive[T]: Rec[T, T] { + type F[x] = x + } = new Rec[T, T] { type F[x] = x def tie(t: T): T = t def untie(t: T): T = t @@ -258,50 +260,56 @@ package recursionschemes { implicit def traverse[H[_], T, U]( implicit H: Traverse[H], U: Rec[T, U] - ) = new Rec[T, H[U]] { + ): Rec[T, H[U]] { + type F[x] = H[U.F[x]] + } = new Rec[T, H[U]] { type F[x] = H[U.F[x]] def tie(ft: F[T]): H[U] = H.map(ft)(U.tie) - def untie(hu: H[U]): F[T] = H.map(hu)(U.untie(_)) - def traverse[G[_], A, B](fa: F[A])(f: A => G[B])( - implicit G: Applicative[G] - ): G[F[B]] = H.traverse(fa)(U.traverse(_)(f)) + def untie(hu: H[U]): F[T] = H.map(hu)(u => U.untie(u)) + def traverse[G[_], A, B](fa: F[A])(f: A => G[B])(implicit G: Applicative[G]): G[F[B]] = + H.traverse(fa)(U.traverse(_)(f)) } } trait Rec1 extends Rec2 { implicit def fieldType[T, K, V]( implicit V: Rec[T, V] - ) = new Rec[T, FieldType[K, V]] { + ): Rec[T, FieldType[K, V]] { + type F[x] = FieldType[K, V.F[x]] + } = new Rec[T, FieldType[K, V]] { type F[x] = FieldType[K, V.F[x]] val key = field[K] def tie(ft: F[T]): FieldType[K, V] = key[V](V.tie(ft: V.F[T])) def untie(kv: FieldType[K, V]): F[T] = key[V.F[T]](V.untie(kv)) - def traverse[G[_], A, B](fa: F[A])(f: A => G[B])( - implicit G: Applicative[G] - ): G[F[B]] = G.map(V.traverse(fa: V.F[A])(f))(key[V.F[B]](_)) + def traverse[G[_], A, B](fa: F[A])(f: A => G[B])(implicit G: Applicative[G]): G[F[B]] = + G.map(V.traverse(fa: V.F[A])(f))(a => key[V.F[B]](a)) } - implicit def hnil[T] = new RecHList[T, HNil] { + implicit def hnil[T]: RecHList[T, HNil] { + type F[x] = HNil + } = new RecHList[T, HNil] { type F[x] = HNil def tie(nil: HNil): HNil = nil def untie(nil: HNil): HNil = nil - def traverse[G[_], A, B](nil: HNil)(f: A => G[B])( - implicit G: Applicative[G] - ): G[HNil] = G.pure(nil) + def traverse[G[_], A, B](nil: HNil)(f: A => G[B])(implicit G: Applicative[G]): G[HNil] = + G.pure(nil) } - implicit def cnil[T] = new RecCoproduct[T, CNil] { + implicit def cnil[T]: RecCoproduct[T, CNil] { + type F[x] = CNil + } = new RecCoproduct[T, CNil] { type F[x] = CNil def tie(nil: CNil): CNil = nil def untie(nil: CNil): CNil = nil - def traverse[G[_], A, B](nil: CNil)(f: A => G[B])( - implicit G: Applicative[G] - ): G[CNil] = G.pure(nil) + def traverse[G[_], A, B](nil: CNil)(f: A => G[B])(implicit G: Applicative[G]): G[CNil] = + G.pure(nil) } implicit def hcons[U, H, T <: HList]( implicit H: Strict[Rec[U, H]], T: RecHList[U, T] - ) = new RecHList[U, H :: T] { + ): RecHList[U, H :: T] { + type F[x] = H.value.F[x] :: T.F[x] + } = new RecHList[U, H :: T] { type F[x] = H.value.F[x] :: T.F[x] def tie(fu: F[U]): H :: T = H.value.tie(fu.head) :: T.tie(fu.tail) def untie(l: H :: T): F[U] = H.value.untie(l.head) :: T.untie(l.tail) @@ -311,7 +319,9 @@ package recursionschemes { implicit def ccons[T, L, R <: Coproduct]( implicit L: Strict[Rec[T, L]], R: RecCoproduct[T, R] - ) = new RecCoproduct[T, L :+: R] { + ): RecCoproduct[T, L :+: R] { + type F[t] = L.value.F[t] :+: R.F[t] + } = new RecCoproduct[T, L :+: R] { type F[t] = L.value.F[t] :+: R.F[t] def tie(ft: F[T]): L :+: R = ft match { @@ -334,36 +344,39 @@ package recursionschemes { implicit def generic[T, U, R]( implicit gen: LabelledGeneric.Aux[U, R], R: Rec[T, R] - ) = new Rec[T, U] { + ): Rec[T, U] { + type F[x] = R.F[x] + } = new Rec[T, U] { type F[x] = R.F[x] def tie(ft: F[T]): U = gen.from(R.tie(ft)) def untie(u: U): F[T] = R.untie(gen.to(u)) - def traverse[G[_], A, B](fa: F[A])(f: A => G[B])( - implicit G: Applicative[G] - ): G[F[B]] = R.traverse(fa)(f) + def traverse[G[_], A, B](fa: F[A])(f: A => G[B])(implicit G: Applicative[G]): G[F[B]] = + R.traverse(fa)(f) } } trait Rec2 { - implicit def const[T, U] = new Rec[T, U] { + implicit def const[T, U]: Rec[T, U] { + type F[x] = U + } = new Rec[T, U] { type F[x] = U def tie(u: U): U = u def untie(u: U): U = u - def traverse[G[_], A, B](u: U)(f: A => G[B])( - implicit G: Applicative[G] - ): G[U] = G.pure(u) + def traverse[G[_], A, B](u: U)(f: A => G[B])(implicit G: Applicative[G]): G[U] = + G.pure(u) } } implicit def morph[T, R]( implicit gen: LabelledGeneric.Aux[T, R], R: Rec[T, R] - ) = new Morph[T] { + ): Morph[T] { + type F[x] = R.F[x] + } = new Morph[T] { type F[x] = R.F[x] def tie(ft: F[T]): T = gen.from(R.tie(ft)) def untie(t: T): F[T] = R.untie(gen.to(t)) - def traverse[G[_], A, B](fa: F[A])(f: A => G[B])( - implicit G: Applicative[G] - ): G[F[B]] = R.traverse(fa)(f) + def traverse[G[_], A, B](fa: F[A])(f: A => G[B])(implicit G: Applicative[G]): G[F[B]] = + R.traverse(fa)(f) } } } From 516ad3deddad9b9bfa8fb110247715f314dfa028 Mon Sep 17 00:00:00 2001 From: Georgi Krastev Date: Sat, 11 Apr 2020 07:33:09 +0200 Subject: [PATCH 05/17] Optimize ZipWithKeys --- .../main/scala/shapeless/ops/coproduct.scala | 36 ++++++++++--------- .../src/main/scala/shapeless/ops/hlists.scala | 34 ++++++++++-------- 2 files changed, 38 insertions(+), 32 deletions(-) diff --git a/core/src/main/scala/shapeless/ops/coproduct.scala b/core/src/main/scala/shapeless/ops/coproduct.scala index 6e1d8b6c0..838a97b9b 100644 --- a/core/src/main/scala/shapeless/ops/coproduct.scala +++ b/core/src/main/scala/shapeless/ops/coproduct.scala @@ -506,30 +506,32 @@ object coproduct { /** Type class that zips an HList with a Coproduct, producing a Coproduct of tuples where each element from * the original coproduct is combined with the matching HList element */ - trait ZipWithKeys[K <: HList, V <: Coproduct] extends DepFn1[V] with Serializable { type Out <: Coproduct } + sealed abstract class ZipWithKeys[K <: HList, V <: Coproduct] extends DepFn1[V] with Serializable { + type Out <: Coproduct + } object ZipWithKeys { import shapeless.labelled._ - def apply[K <: HList, V <: Coproduct] - (implicit zipWithKeys: ZipWithKeys[K, V]): Aux[K, V, zipWithKeys.Out] = zipWithKeys + private val instance = new ZipWithKeys[HList, Coproduct] { + type Out = Coproduct + def apply(v: Coproduct): Coproduct = v + } - type Aux[K <: HList, V <: Coproduct, Out0 <: Coproduct] = ZipWithKeys[K, V] { type Out = Out0 } + def apply[K <: HList, V <: Coproduct]( + implicit zipWithKeys: ZipWithKeys[K, V] + ): Aux[K, V, zipWithKeys.Out] = zipWithKeys - implicit val cnilZipWithKeys: Aux[HNil, CNil, CNil] = new ZipWithKeys[HNil, CNil] { - type Out = CNil - def apply(v: CNil) = v - } + type Aux[K <: HList, V <: Coproduct, Out0 <: Coproduct] = + ZipWithKeys[K, V] { type Out = Out0 } - implicit def cpZipWithKeys[KH, VH, KT <: HList, VT <: Coproduct] (implicit zipWithKeys: ZipWithKeys[KT, VT], wkh: Witness.Aux[KH]) - : Aux[KH :: KT, VH :+: VT, FieldType[KH, VH] :+: zipWithKeys.Out] = - new ZipWithKeys[KH :: KT, VH :+: VT] { - type Out = FieldType[KH, VH] :+: zipWithKeys.Out - def apply(v: VH :+: VT): Out = v match { - case Inl(vh) => Inl(field[wkh.T](vh)) - case Inr(vt) => Inr(zipWithKeys(vt)) - } - } + implicit def cnilZipWithKeys: Aux[HNil, CNil, CNil] = + instance.asInstanceOf[Aux[HNil, CNil, CNil]] + + implicit def cconsZipWithKeys[KH, VH, KT <: HList, VT <: Coproduct]( + implicit wkh: Witness.Aux[KH], zipWithKeys: ZipWithKeys[KT, VT] + ): Aux[KH :: KT, VH :+: VT, FieldType[KH, VH] :+: zipWithKeys.Out] = + instance.asInstanceOf[Aux[KH :: KT, VH :+: VT, FieldType[KH, VH] :+: zipWithKeys.Out]] } /** diff --git a/core/src/main/scala/shapeless/ops/hlists.scala b/core/src/main/scala/shapeless/ops/hlists.scala index a96886cae..8e033e789 100644 --- a/core/src/main/scala/shapeless/ops/hlists.scala +++ b/core/src/main/scala/shapeless/ops/hlists.scala @@ -2371,28 +2371,32 @@ object hlist { * * @author Cody Allen */ - trait ZipWithKeys[K <: HList, V <: HList] extends DepFn1[V] with Serializable { type Out <: HList } + sealed abstract class ZipWithKeys[K <: HList, V <: HList] extends DepFn1[V] with Serializable { + type Out <: HList + } object ZipWithKeys { import shapeless.labelled._ - def apply[K <: HList, V <: HList] - (implicit zipWithKeys: ZipWithKeys[K, V]): Aux[K, V, zipWithKeys.Out] = zipWithKeys + private val instance = new ZipWithKeys[HList, HList] { + type Out = HList + def apply(v: HList): HList = v + } - type Aux[K <: HList, V <: HList, Out0 <: HList] = ZipWithKeys[K, V] { type Out = Out0 } + def apply[K <: HList, V <: HList]( + implicit zipWithKeys: ZipWithKeys[K, V] + ): Aux[K, V, zipWithKeys.Out] = zipWithKeys - implicit val hnilZipWithKeys: Aux[HNil, HNil, HNil] = new ZipWithKeys[HNil, HNil] { - type Out = HNil - def apply(v: HNil) = HNil - } + type Aux[K <: HList, V <: HList, Out0 <: HList] = + ZipWithKeys[K, V] { type Out = Out0 } - implicit def hconsZipWithKeys[KH, VH, KT <: HList, VT <: HList, ZwkOut <: HList] (implicit zipWithKeys: ZipWithKeys.Aux[KT, VT, ZwkOut], wkh: Witness.Aux[KH]) - : Aux[KH :: KT, VH :: VT, FieldType[KH, VH] :: ZwkOut] = - new ZipWithKeys[KH :: KT, VH :: VT] { - type Out = FieldType[KH, VH] :: ZwkOut - def apply(v: VH :: VT): Out = - field[wkh.T](v.head) :: zipWithKeys(v.tail) - } + implicit def hnilZipWithKeys: Aux[HNil, HNil, HNil] = + instance.asInstanceOf[Aux[HNil, HNil, HNil]] + + implicit def hconsZipWithKeys[KH, VH, KT <: HList, VT <: HList, KVT <: HList]( + implicit wkh: Witness.Aux[KH], zipWithKeys: ZipWithKeys.Aux[KT, VT, KVT] + ): Aux[KH :: KT, VH :: VT, FieldType[KH, VH] :: KVT] = + instance.asInstanceOf[Aux[KH :: KT, VH :: VT, FieldType[KH, VH] :: KVT]] } /** From d475d91be59dc5f3e4868f7e1bbd8db02e965a57 Mon Sep 17 00:00:00 2001 From: Georgi Krastev Date: Sat, 11 Apr 2020 08:46:10 +0200 Subject: [PATCH 06/17] Refactor unsafe macros for optimization --- core/src/main/scala/shapeless/generic.scala | 68 ++--- .../main/scala/shapeless/ops/records.scala | 244 +++++++----------- 2 files changed, 136 insertions(+), 176 deletions(-) diff --git a/core/src/main/scala/shapeless/generic.scala b/core/src/main/scala/shapeless/generic.scala index 0d3980c09..84d37eb22 100644 --- a/core/src/main/scala/shapeless/generic.scala +++ b/core/src/main/scala/shapeless/generic.scala @@ -219,7 +219,7 @@ object LabelledGeneric { * @tparam T the type * @tparam Repr0 the labelled generic representation of the type */ - type Aux[T, Repr0] = LabelledGeneric[T]{ type Repr = Repr0 } + type Aux[T, Repr0] = LabelledGeneric[T] { type Repr = Repr0 } /** Provides an instance of LabelledGeneric for the given T. As with [[shapeless.Generic]], * use this method or {{{the[LabelledGeneric[T]]}}} to obtain an instance for suitable given T. */ @@ -494,54 +494,58 @@ trait CaseClassMacros extends ReprTypes with CaseClassMacrosVersionSpecifics { case (elem, acc) => q"_root_.shapeless.::($elem, $acc)" } - def mkCompoundTpe(nil: Type, cons: Type, items: List[Type]): Type = - items.foldRight(nil) { - case (tpe, acc) => appliedType(cons, List(devarargify(tpe), acc)) + def mkCompoundTpe(nil: Type, cons: Type, items: Seq[Type]): Type = + items.foldRight(nil) { (tpe, acc) => + appliedType(cons, List(devarargify(tpe), acc)) } - def mkHListTpe(items: List[Type]): Type = + def mkHListTpe(items: Seq[Type]): Type = mkCompoundTpe(hnilTpe, hconsTpe, items) - def mkCoproductTpe(items: List[Type]): Type = + def mkCoproductTpe(items: Seq[Type]): Type = mkCompoundTpe(cnilTpe, cconsTpe, items) - def unpackHListTpe(tpe: Type): List[Type] = { - @tailrec - def unfold(u: Type, acc: List[Type]): List[Type] = { - val HNilTpe = hnilTpe - val HConsPre = prefix(hconsTpe) - val HConsSym = hconsTpe.typeSymbol - if(u <:< HNilTpe) acc - else (u baseType HConsSym) match { - case TypeRef(pre, _, List(hd, tl)) if pre =:= HConsPre => unfold(tl, hd :: acc) - case _ => abort(s"$tpe is not an HList type") + def unpackHList(tpe: Type): Vector[Type] = + unpackReprType(tpe, hnilTpe, hconsTpe) + + def unpackCoproduct(tpe: Type): Vector[Type] = + unpackReprType(tpe, cnilTpe, cconsTpe) + + def unpackReprType(tpe: Type, nil: Type, cons: Type): Vector[Type] = { + val consSym = cons.typeSymbol + @tailrec def unpack(tpe: Type, acc: Vector[Type]): Vector[Type] = + if (tpe <:< nil) acc else tpe.baseType(consSym) match { + case TypeRef(_, _, List(head, tail)) => unpack(tail, acc :+ head) + case _ => abort(s"$tpe is not an HList or Coproduct type") } - } - unfold(tpe, List()).reverse + unpack(tpe, Vector.empty) } object FieldType { import internal._ - def apply(kTpe: Type, vTpe: Type): Type = - refinedType(List(vTpe, typeRef(prefix(keyTagTpe), keyTagTpe.typeSymbol, List(kTpe, vTpe))), NoSymbol) + private val KeyTagSym = keyTagTpe.typeSymbol - def unapply(fTpe: Type): Option[(Type, Type)] = { - val KeyTagPre = prefix(keyTagTpe) - val KeyTagSym = keyTagTpe.typeSymbol - fTpe.dealias match { - case RefinedType(v0 :+ TypeRef(pre, KeyTagSym, List(k, v1)), scope) - if pre =:= KeyTagPre && refinedType(v0, NoSymbol, scope, NoPosition) =:= v1 => - Some((k, v1)) - case _ => None - } + def apply(key: Type, value: Type): Type = + appliedType(fieldTypeTpe, key, value) + + def unapply(field: Type): Option[(Type, Type)] = field.dealias match { + case RefinedType(List(value, TypeRef(_, KeyTagSym, List(key, _))), scope) + if scope.isEmpty => Some(key -> value) + case RefinedType(parents :+ TypeRef(_, KeyTagSym, List(key, value)), scope) + if value =:= refinedType(parents, scope) => Some(key -> value) + case _ => + None } } - def findField(lTpe: Type, kTpe: Type): Option[(Type, Int)] = - unpackHListTpe(lTpe).zipWithIndex.collectFirst { - case (FieldType(k, v), i) if k =:= kTpe => (v, i) + def findField(record: Type, key: Type): Option[(Type, Int)] = + findField(unpackHList(record), key) + + def findField(fields: Seq[Type], key: Type): Option[(Type, Int)] = + fields.iterator.zipWithIndex.collectFirst { + case (FieldType(k, v), i) if k =:= key => (v, i) } def appliedTypTree1(tpe: Type, param: Type, arg: TypeName): Tree = { diff --git a/core/src/main/scala/shapeless/ops/records.scala b/core/src/main/scala/shapeless/ops/records.scala index 29459f3c2..bc2f65af4 100644 --- a/core/src/main/scala/shapeless/ops/records.scala +++ b/core/src/main/scala/shapeless/ops/records.scala @@ -34,43 +34,37 @@ package record { * * @author Miles Sabin */ - @annotation.implicitNotFound(msg = "No field ${K} in record ${L}") - trait Selector[L <: HList, K] extends DepFn1[L] with Serializable { - type Out - def apply(l : L): Out - } + @annotation.implicitNotFound(msg = "No field ${K} in record ${R}") + sealed abstract class Selector[R <: HList, K] extends DepFn1[R] with Serializable object Selector { - type Aux[L <: HList, K, Out0] = Selector[L, K] { type Out = Out0 } - - def apply[L <: HList, K](implicit selector: Selector[L, K]): Aux[L, K, selector.Out] = selector + type Aux[R <: HList, K, O] = Selector[R, K] { type Out = O } + def apply[R <: HList, K](implicit selector: Selector[R, K]): Aux[R, K, selector.Out] = selector - implicit def mkSelector[L <: HList, K, O]: Aux[L, K, O] = macro SelectorMacros.applyImpl[L, K] + implicit def materialize[R <: HList, K, O]: Aux[R, K, O] = + macro SelectorMacros.materialize[R, K] } - class UnsafeSelector(i: Int) extends Selector[HList, Any] { + final class UnsafeSelector(i: Int) extends Selector[HList, Any] { type Out = Any - def apply(l: HList): Any = HList.unsafeGet(l, i) + def apply(record: HList): Any = HList.unsafeGet(record, i) } @macrocompat.bundle class SelectorMacros(val c: whitebox.Context) extends CaseClassMacros { import c.universe._ - def applyImpl[L <: HList, K](implicit lTag: WeakTypeTag[L], kTag: WeakTypeTag[K]): Tree = { - val lTpe = lTag.tpe.dealias - val kTpe = kTag.tpe.dealias - if(!(lTpe <:< hlistTpe)) - abort(s"$lTpe is not a record type") + def materialize[R <: HList: WeakTypeTag, K: WeakTypeTag]: Tree = { + val record = weakTypeOf[R].dealias + val key = weakTypeOf[K].dealias + if (!(record <:< hlistTpe)) + abort(s"$record is not a record type") - findField(lTpe, kTpe) match { + findField(record, key) match { case Some((v, i)) => - q""" - new _root_.shapeless.ops.record.UnsafeSelector($i). - asInstanceOf[_root_.shapeless.ops.record.Selector.Aux[$lTpe, $kTpe, $v]] - """ + q"new ${typeOf[UnsafeSelector]}($i).asInstanceOf[${reify(Selector)}.Aux[$record, $key, $v]]" case _ => - abort(s"No field $kTpe in record type $lTpe") + abort(s"No field $key in record type $record") } } } @@ -110,42 +104,42 @@ package record { * * @author Miles Sabin */ - trait Updater[L <: HList, F] extends DepFn2[L, F] with Serializable { type Out <: HList } + @annotation.implicitNotFound(msg = "No element of type ${E} in ${L}") + sealed abstract class Updater[L <: HList, E] extends DepFn2[L, E] with Serializable { + type Out <: HList + } object Updater { - type Aux[L <: HList, F, Out0 <: HList] = Updater[L, F] { type Out = Out0 } + type Aux[L <: HList, E, O <: HList] = Updater[L, E] { type Out = O } + def apply[L <: HList, E](implicit updater: Updater[L, E]): Aux[L, E, updater.Out] = updater - def apply[L <: HList, F](implicit updater: Updater[L, F]): Aux[L, F, updater.Out] = updater - - implicit def mkUpdater[L <: HList, F, O]: Aux[L, F, O] = macro UpdaterMacros.applyImpl[L, F] + implicit def meterialize[L <: HList, F, O]: Aux[L, F, O] = + macro UpdaterMacros.materialize[L, F] } - class UnsafeUpdater(i: Int) extends Updater[HList, Any] { + final class UnsafeUpdater(i: Int) extends Updater[HList, Any] { type Out = HList - def apply(l: HList, f: Any): HList = HList.unsafeUpdateAppend(l, i, f) + def apply(l: HList, e: Any): HList = HList.unsafeUpdateAppend(l, i, e) } @macrocompat.bundle class UpdaterMacros(val c: whitebox.Context) extends CaseClassMacros { import c.universe._ - def applyImpl[L <: HList, F](implicit lTag: WeakTypeTag[L], fTag: WeakTypeTag[F]): Tree = { - val lTpe = lTag.tpe.dealias - val fTpe = fTag.tpe.dealias - if(!(lTpe <:< hlistTpe)) - abort(s"$lTpe is not a record type") - - val lTpes = unpackHListTpe(lTpe) - val (uTpes, i) = { - val i0 = lTpes.indexWhere(_ =:= fTpe) - if(i0 < 0) (lTpes :+ fTpe, lTpes.length) - else (lTpes.updated(i0, fTpe), i0) - } - val uTpe = mkHListTpe(uTpes) - q""" - new _root_.shapeless.ops.record.UnsafeUpdater($i) - .asInstanceOf[_root_.shapeless.ops.record.Updater.Aux[$lTpe, $fTpe, $uTpe]] - """ + def materialize[L <: HList: WeakTypeTag, E: WeakTypeTag]: Tree = { + val list = weakTypeOf[L].dealias + val element = weakTypeOf[E].dealias + if (!(list <:< hlistTpe)) + abort(s"$list is not a record type") + + val (updated, i) = { + val elements = unpackHList(list) + val i = elements.indexWhere(_ =:= element) + if (i < 0) (elements :+ element, elements.length) + else (elements.updated(i, element), i) + } + + q"new ${typeOf[UnsafeUpdater]}($i).asInstanceOf[${reify(Updater)}.Aux[$list, $element, ${mkHListTpe(updated)}]]" } } @@ -354,60 +348,43 @@ package record { * * @author Joni Freeman */ - @annotation.implicitNotFound(msg = "No field ${F} with value of type ${A} in record ${L}") - trait Modifier[L <: HList, F, A, B] extends DepFn2[L, A => B] with Serializable { type Out <: HList } + @annotation.implicitNotFound(msg = "No field ${K} with value of type ${A} in record ${R}") + sealed abstract class Modifier[R <: HList, K, A, B] extends DepFn2[R, A => B] with Serializable { + type Out <: HList + } object Modifier { - def apply[L <: HList, F, A, B](implicit modifier: Modifier[L, F, A, B]): Aux[L, F, A, B, modifier.Out] = modifier - - type Aux[L <: HList, F, A, B, Out0 <: HList] = Modifier[L, F, A, B] { type Out = Out0 } - - implicit def mkModifier[L <: HList, K, A, B, O <: HList]: Aux[L, K, A, B, O] = macro ModifierMacros.applyImpl[L, K, A, B] - - @deprecated("Retained for binary compatability", "2.3.1") - def hlistModify1[F, A, B, T <: HList]: Aux[FieldType[F, A] :: T, F, A, B, FieldType[F, B] :: T] = - new Modifier[FieldType[F, A] :: T, F, A, B] { - type Out = FieldType[F, B] :: T - def apply(l: FieldType[F, A] :: T, f: A => B): Out = field[F](f(l.head)) :: l.tail - } + type Aux[R <: HList, K, A, B, O <: HList] = Modifier[R, K, A, B] { type Out = O } + def apply[R <: HList, K, A, B](implicit modifier: Modifier[R, K, A, B]): Aux[R, K, A, B, modifier.Out] = modifier - @deprecated("Retained for binary compatability", "2.3.1") - def hlistModify[H, T <: HList, F, A, B] - (implicit mt: Modifier[T, F, A, B]): Aux[H :: T, F, A, B, H :: mt.Out] = - new Modifier[H :: T, F, A, B] { - type Out = H :: mt.Out - def apply(l: H :: T, f: A => B): Out = l.head :: mt(l.tail, f) - } + implicit def materialize[R <: HList, K, A, B, O <: HList]: Aux[R, K, A, B, O] = + macro ModifierMacros.materialize[R, K, A, B] } - class UnsafeModifier(i: Int) extends Modifier[HList, Any, Any, Any] { + final class UnsafeModifier(i: Int) extends Modifier[HList, Any, Any, Any] { type Out = HList - def apply(l: HList, f: Any => Any): HList = HList.unsafeUpdateWith(l, i, f) + def apply(record: HList, f: Any => Any): HList = HList.unsafeUpdateWith(record, i, f) } @macrocompat.bundle class ModifierMacros(val c: whitebox.Context) extends CaseClassMacros { import c.universe._ - def applyImpl[L <: HList, K, A, B] - (implicit lTag: WeakTypeTag[L], kTag: WeakTypeTag[K], aTag: WeakTypeTag[A], bTag: WeakTypeTag[B]): Tree = { - val lTpe = lTag.tpe.dealias - val kTpe = kTag.tpe.dealias - if(!(lTpe <:< hlistTpe)) - abort(s"$lTpe is not a record type") - val aTpe = aTag.tpe - val bTpe = bTag.tpe - - findField(lTpe, kTpe) match { - case Some((v, i)) if v <:< aTpe => - val (prefix, List(_, suffix @ _*)) = unpackHListTpe(lTpe).splitAt(i) - val outTpe = mkHListTpe(prefix ++ (FieldType(kTpe, bTpe) :: suffix.toList)) - q""" - new _root_.shapeless.ops.record.UnsafeModifier($i). - asInstanceOf[_root_.shapeless.ops.record.Modifier.Aux[$lTpe, $kTpe, $aTpe, $bTpe, $outTpe]] - """ + def materialize[R <: HList: WeakTypeTag, K: WeakTypeTag, A: WeakTypeTag, B: WeakTypeTag]: Tree = { + val record = weakTypeOf[R].dealias + val key = weakTypeOf[K].dealias + if (!(record <:< hlistTpe)) + abort(s"$record is not a record type") + + val a = weakTypeOf[A] + val b = weakTypeOf[B] + val fields = unpackHList(record) + findField(fields, key) match { + case Some((v, i)) if v <:< a => + val out = mkHListTpe(fields.updated(i, FieldType(key, b))) + q"new ${typeOf[UnsafeModifier]}($i).asInstanceOf[${reify(Modifier)}.Aux[$record, $key, $a, $b, $out]]" case _ => - abort(s"No field $kTpe in record type $lTpe") + abort(s"No field $key in record type $record") } } } @@ -417,62 +394,42 @@ package record { * * @author Miles Sabin */ - @annotation.implicitNotFound(msg = "No field ${K} in record ${L}") - trait Remover[L <: HList, K] extends DepFn1[L] with Serializable - - trait LowPriorityRemover { - type Aux[L <: HList, K, Out0] = Remover[L, K] { type Out = Out0 } - - @deprecated("Retained for binary compatability", "2.3.1") - def hlistRemove[H, T <: HList, K, V, OutT <: HList] - (implicit rt: Aux[T, K, (V, OutT)]): Aux[H :: T, K, (V, H :: OutT)] = - new Remover[H :: T, K] { - type Out = (V, H :: OutT) - def apply(l : H :: T): Out = { - val (v, tail) = rt(l.tail) - (v, l.head :: tail) - } - } + @annotation.implicitNotFound(msg = "No field ${K} in record ${R}") + sealed abstract class Remover[R <: HList, K] extends DepFn1[R] with Serializable { + type Out <: (Any, HList) } - object Remover extends LowPriorityRemover { - def apply[L <: HList, K](implicit remover: Remover[L, K]): Aux[L, K, remover.Out] = remover - - implicit def mkRemover[L <: HList, K, V, O <: HList]: Aux[L, K, (V, O)] = macro RemoverMacros.applyImpl[L, K] + object Remover { + type Aux[R <: HList, K, O] = Remover[R, K] { type Out = O } + def apply[R <: HList, K](implicit remover: Remover[R, K]): Aux[R, K, remover.Out] = remover - @deprecated("Retained for binary compatability", "2.3.1") - def hlistRemove1[K, V, T <: HList]: Aux[FieldType[K, V] :: T, K, (V, T)] = - new Remover[FieldType[K, V] :: T, K] { - type Out = (V, T) - def apply(l: FieldType[K, V] :: T): Out = (l.head, l.tail) - } + implicit def materialize[R <: HList, K, V, O <: HList]: Aux[R, K, (V, O)] = + macro RemoverMacros.materialize[R, K] } - class UnsafeRemover(i: Int) extends Remover[HList, Any] { + final class UnsafeRemover(i: Int) extends Remover[HList, Any] { type Out = (Any, HList) - def apply(l: HList): (Any, HList) = HList.unsafeRemove(l, i) + def apply(record: HList): (Any, HList) = HList.unsafeRemove(record, i) } @macrocompat.bundle class RemoverMacros(val c: whitebox.Context) extends CaseClassMacros { import c.universe._ - def applyImpl[L <: HList, K](implicit lTag: WeakTypeTag[L], kTag: WeakTypeTag[K]): Tree = { - val lTpe = lTag.tpe.dealias - val kTpe = kTag.tpe.dealias - if(!(lTpe <:< hlistTpe)) - abort(s"$lTpe is not a record type") + def materialize[R <: HList: WeakTypeTag, K: WeakTypeTag]: Tree = { + val record = weakTypeOf[R].dealias + val key = weakTypeOf[K].dealias + if (!(record <:< hlistTpe)) + abort(s"$record is not a record type") - findField(lTpe, kTpe) match { + val fields = unpackHList(record) + findField(fields, key) match { case Some((v, i)) => - val (prefix, List(_, suffix @ _*)) = unpackHListTpe(lTpe).splitAt(i) - val outTpe = mkHListTpe(prefix ++ suffix) - q""" - new _root_.shapeless.ops.record.UnsafeRemover($i). - asInstanceOf[_root_.shapeless.ops.record.Remover.Aux[$lTpe, $kTpe, ($v, $outTpe)]] - """ + val (prefix, suffix) = fields.splitAt(i) + val out = mkHListTpe(prefix ++ suffix.tail) + q"new ${typeOf[UnsafeRemover]}($i).asInstanceOf[${reify(Remover)}.Aux[$record, $key, ($v, $out)]]" case _ => - abort(s"No field $kTpe in record type $lTpe") + abort(s"No field $key in record type $record") } } } @@ -592,29 +549,28 @@ package record { } } - trait LacksKey[L <: HList, K] - + @annotation.implicitNotFound(msg = "Record ${R} contains field ${K}") + final class LacksKey[R <: HList, K] object LacksKey { - implicit def apply[L <: HList, K]: LacksKey[L, K] = macro LacksKeyMacros.applyImpl[L, K] + def apply[R <: HList, K](implicit ev: LacksKey[R, K]): LacksKey[R, K] = ev + + implicit def materialize[R <: HList, K]: LacksKey[R, K] = + macro LacksKeyMacros.materialize[R, K] } @macrocompat.bundle class LacksKeyMacros(val c: whitebox.Context) extends CaseClassMacros { import c.universe._ - def applyImpl[L <: HList, K](implicit lTag: WeakTypeTag[L], kTag: WeakTypeTag[K]): Tree = { - val lTpe = lTag.tpe.dealias - val kTpe = kTag.tpe.dealias - if(!(lTpe <:< hlistTpe)) - abort(s"$lTpe is not a record type") - - findField(lTpe, kTpe) match { - case None => - q""" - new _root_.shapeless.ops.record.LacksKey[$lTpe, $kTpe] {} - """ - case _ => - abort(s"Record type $lTpe contains field $kTpe") + def materialize[R <: HList: WeakTypeTag, K: WeakTypeTag]: Tree = { + val record = weakTypeOf[R].dealias + val key = weakTypeOf[K].dealias + if (!(record <:< hlistTpe)) + abort(s"$record is not a record type") + + findField(record, key) match { + case None => q"new ${weakTypeOf[LacksKey[R, K]]}" + case _ => abort(s"Record type $record contains field $key") } } } From 31ba5053ff9f781010c140b0aea31d2e8e3459c1 Mon Sep 17 00:00:00 2001 From: Georgi Krastev Date: Sat, 11 Apr 2020 09:36:12 +0200 Subject: [PATCH 07/17] Decouple LabelledGeneric from ZipWithKeys --- core/src/main/scala/shapeless/generic.scala | 35 +++++--------------- core/src/main/scala/shapeless/labelled.scala | 13 +++++++- 2 files changed, 21 insertions(+), 27 deletions(-) diff --git a/core/src/main/scala/shapeless/generic.scala b/core/src/main/scala/shapeless/generic.scala index 84d37eb22..3c07d7bc2 100644 --- a/core/src/main/scala/shapeless/generic.scala +++ b/core/src/main/scala/shapeless/generic.scala @@ -16,8 +16,6 @@ package shapeless -import shapeless.ops.{coproduct, hlist} - import scala.annotation.{StaticAnnotation, tailrec} import scala.language.experimental.macros import scala.reflect.macros.{blackbox, whitebox} @@ -225,31 +223,14 @@ object LabelledGeneric { * use this method or {{{the[LabelledGeneric[T]]}}} to obtain an instance for suitable given T. */ def apply[T](implicit lgen: LabelledGeneric[T]): Aux[T, lgen.Repr] = lgen - /** Handles the Product case (fields in a case class, for example) */ - implicit def materializeProduct[T, K <: HList, V <: HList, R <: HList]( - implicit - lab: Labelling.Aux[T, K], - gen: Generic.Aux[T, V], - zip: hlist.ZipWithKeys.Aux[K, V, R], - ev: R <:< V - ): Aux[T, R] = new LabelledGeneric[T] { - type Repr = R - def to(t: T): Repr = zip(gen.to(t)) - def from(r: Repr): T = gen.from(r) - } - - /** Handles the Coproduct case (specifying subclasses derive from a sealed trait) */ - implicit def materializeCoproduct[T, K <: HList, V <: Coproduct, R <: Coproduct]( - implicit - lab: Labelling.Aux[T, K], - gen: Generic.Aux[T, V], - zip: coproduct.ZipWithKeys.Aux[K, V, R], - ev: R <:< V - ): Aux[T, R] = new LabelledGeneric[T] { + def unsafeInstance[T, R](gen: Generic[T]): Aux[T, R] = new LabelledGeneric[T] { type Repr = R - def to(t: T): Repr = zip(gen.to(t)) - def from(r: Repr): T = gen.from(r) + def to(t: T): Repr = gen.to(t).asInstanceOf[R] + def from(r: Repr): T = gen.from(r.asInstanceOf[gen.Repr]) } + + implicit def materialize[T, R]: Aux[T, R] = + macro LabelledMacros.mkLabelledGeneric[T, R] } class nonGeneric extends StaticAnnotation @@ -931,7 +912,9 @@ class GenericMacros(val c: whitebox.Context) extends CaseClassMacros { private val generic = objectRef[Generic.type] - def materialize[T: WeakTypeTag, R: WeakTypeTag]: Tree = { + def materialize[T: WeakTypeTag, R]: Tree = mkGeneric[T] + + def mkGeneric[T: WeakTypeTag]: Tree = { val tpe = weakTypeOf[T] if (isReprType(tpe)) abort("No Generic instance available for HList or Coproduct") diff --git a/core/src/main/scala/shapeless/labelled.scala b/core/src/main/scala/shapeless/labelled.scala index 2f7baf4b2..809b9d034 100644 --- a/core/src/main/scala/shapeless/labelled.scala +++ b/core/src/main/scala/shapeless/labelled.scala @@ -85,7 +85,7 @@ trait FieldOf[V] { } @macrocompat.bundle -class LabelledMacros(val c: whitebox.Context) extends SingletonTypeUtils with CaseClassMacros { +class LabelledMacros(override val c: whitebox.Context) extends GenericMacros(c) with SingletonTypeUtils { import c.universe._ import internal.constantType @@ -118,6 +118,17 @@ class LabelledMacros(val c: whitebox.Context) extends SingletonTypeUtils with Ca private def parseLiteralTypeOrFail(tpe: String): Type = parseLiteralType(tpe).getOrElse(abort(s"Malformed literal type $tpe")) + def mkLabelledGeneric[T: WeakTypeTag, R]: Tree = { + val q"$_.instance[$_, $labels]($_)" = mkLabelling[T] + val generic @ q"$_.instance[$_, $repr]($_, $_)" = mkGeneric[T] + val keys = unpackHList(labels.tpe) + val isProduct = repr.tpe <:< hlistTpe + val values = if (isProduct) unpackHList(repr.tpe) else unpackCoproduct(repr.tpe) + val items = keys.zip(values).map((FieldType.apply _).tupled) + val labelled = if (isProduct) mkHListTpe(items) else mkCoproductTpe(items) + q"${reify(LabelledGeneric)}.unsafeInstance[${weakTypeOf[T]}, $labelled]($generic)" + } + def mkLabelling[T: WeakTypeTag]: Tree = { val tpe = weakTypeOf[T] val labels: List[Constant] = From 30378b4e481903a48ba0fc9569c118135a759a99 Mon Sep 17 00:00:00 2001 From: Georgi Krastev Date: Sat, 11 Apr 2020 10:10:51 +0200 Subject: [PATCH 08/17] Reuse CaseClassMacros in RecordMacros --- core/src/main/scala/shapeless/generic.scala | 2 +- core/src/main/scala/shapeless/records.scala | 43 +++++++-------------- 2 files changed, 16 insertions(+), 29 deletions(-) diff --git a/core/src/main/scala/shapeless/generic.scala b/core/src/main/scala/shapeless/generic.scala index 3c07d7bc2..84371bbde 100644 --- a/core/src/main/scala/shapeless/generic.scala +++ b/core/src/main/scala/shapeless/generic.scala @@ -279,7 +279,7 @@ trait CaseClassMacros extends ReprTypes with CaseClassMacrosVersionSpecifics { import c.universe._ - def abort(msg: String) = + def abort(msg: String): Nothing = c.abort(c.enclosingPosition, msg) def isReprType(tpe: Type): Boolean = diff --git a/core/src/main/scala/shapeless/records.scala b/core/src/main/scala/shapeless/records.scala index ed8176fe1..828e13f7f 100644 --- a/core/src/main/scala/shapeless/records.scala +++ b/core/src/main/scala/shapeless/records.scala @@ -111,41 +111,34 @@ trait FromRecordArgs extends Dynamic { } @macrocompat.bundle -class RecordMacros(val c: whitebox.Context) { +class RecordMacros(val c: whitebox.Context) extends CaseClassMacros { import c.universe._ import internal.constantType - import labelled.FieldType val hconsValueTree: Tree = reify(::).tree val hnilValueTree: Tree = reify(HNil: HNil).tree - val fieldTypeTpe: Type = typeOf[FieldType[_, _]].typeConstructor def mkRecordEmptyImpl(method: Tree)(rec: Tree*): Tree = { - if (rec.nonEmpty) - c.abort(c.enclosingPosition, "this method must be called with named arguments") - + if (rec.nonEmpty) abort("this method must be called with named arguments") hnilValueTree } def mkRecordNamedImpl(method: Tree)(rec: Tree*): Tree = { val q"${methodString: String}" = method - if (methodString != "apply") - c.abort(c.enclosingPosition, s"this method must be called as 'apply' not '$methodString'") - + if (methodString != "apply") abort(s"this method must be called as 'apply' not '$methodString'") mkRecordImpl(rec: _*) } - def forwardImpl(method: Tree)(): Tree = forwardNamedImpl(method)() + def forwardImpl(method: Tree)(): Tree = + forwardNamedImpl(method)() def forwardNamedImpl(method: Tree)(rec: Tree*): Tree = { val lhs = c.prefix.tree val lhsTpe = lhs.tpe - val q"${methodString: String}" = method val methodName = TermName(methodString + "Record") - if (lhsTpe.member(methodName) == NoSymbol) - c.abort(c.enclosingPosition, s"missing method '$methodName'") + abort(s"missing method '$methodName'") val recTree = mkRecordImpl(rec: _*) q"$lhs.$methodName($recTree)" @@ -154,45 +147,39 @@ class RecordMacros(val c: whitebox.Context) { def forwardFromRecordImpl[L <: HList](method: Tree)(rec: Expr[L]): Tree = { val lhs = c.prefix.tree val lhsTpe = lhs.tpe - val q"${methodString: String}" = method - if (!methodString.matches(".*Record$")) - c.abort(c.enclosingPosition, s"missing method '$methodString'") + abort(s"missing method '$methodString'") val methodName = TermName(methodString.replaceAll("Record$", "")) - if (!lhsTpe.member(methodName).isMethod) - c.abort(c.enclosingPosition, s"missing method '$methodName'") + abort(s"missing method '$methodName'") val params = mkParamsImpl(lhsTpe.member(methodName).asMethod, rec) q"$lhs.$methodName(...$params)" } - def mkFieldTpe(keyTpe: Type, valueTpe: Type): Type = - appliedType(fieldTypeTpe, List(keyTpe, valueTpe.widen)) - def mkRecordImpl(rec: Tree*): Tree = { - def mkElem(keyTpe: Type, value: Tree): Tree = - q"$value.asInstanceOf[${mkFieldTpe(keyTpe, value.tpe)}]" + def mkElem(key: Type, value: Tree): Tree = + q"$value.asInstanceOf[${FieldType(key, value.tpe.widen)}]" def promoteElem(elem: Tree): Tree = elem match { case q"$_(${Literal(k)}, $v)" => mkElem(constantType(k), v) - case _ => c.abort(c.enclosingPosition, s"$elem has the wrong shape for a record field") + case _ => abort(s"$elem has the wrong shape for a record field") } - rec.foldRight(hnilValueTree) { case (elem, acc) => + rec.foldRight(hnilValueTree) { (elem, acc) => q"$hconsValueTree(${promoteElem(elem)}, $acc)" } } def mkParamsImpl[L <: HList](method: MethodSymbol, rec: Expr[L]): List[List[Tree]] = { val selector = reify(ops.hlist.Selector) - def mkElem(keyTpe: Type, value: Tree): Tree = - q"$selector[${rec.actualType}, ${mkFieldTpe(keyTpe, value.tpe)}].apply($rec)" + def mkElem(key: Type, value: Tree): Tree = + q"$selector[${rec.actualType}, ${FieldType(key, value.tpe.widen)}].apply($rec)" method.paramLists.filterNot(_.forall(_.isImplicit)).map(_.map { p => - mkElem(constantType(Constant(p.name.decodedName.toString)), q"${p.typeSignature}") + mkElem(constantType(nameAsValue(p.name)), q"${p.typeSignature}") }) } } From 53fafc20517059c13dcee0e7163f7e4c6b76f3f6 Mon Sep 17 00:00:00 2001 From: Georgi Krastev Date: Sat, 11 Apr 2020 10:37:24 +0200 Subject: [PATCH 09/17] Optimize LabelledTypeClass --- core/src/main/scala/shapeless/typeclass.scala | 70 ++++++++----------- 1 file changed, 29 insertions(+), 41 deletions(-) diff --git a/core/src/main/scala/shapeless/typeclass.scala b/core/src/main/scala/shapeless/typeclass.scala index 2c5b6271e..e41654afa 100644 --- a/core/src/main/scala/shapeless/typeclass.scala +++ b/core/src/main/scala/shapeless/typeclass.scala @@ -16,7 +16,7 @@ package shapeless -import labelled.{ field, FieldType } +import labelled.FieldType /** * A type class abstracting over the `product` operation of type classes over @@ -86,39 +86,39 @@ trait LabelledProductTypeClassCompanion[C[_]] extends Serializable { val typeClass: LabelledProductTypeClass[C] - trait Wrap[KV] extends Serializable { + sealed abstract class Wrap[KV] extends Serializable { type V val unwrap: C[V] - def label(v: V): KV - def unlabel(rec: KV): V + def label(values: V): KV + def unlabel(record: KV): V } object Wrap { type Aux[KV, V0] = Wrap[KV] { type V = V0 } } - implicit def deriveHNil: Wrap.Aux[HNil, HNil] = new Wrap[HNil] { - type V = HNil - val unwrap = typeClass.emptyProduct - def label(v: HNil): HNil = HNil - def unlabel(rec: HNil): HNil = HNil + private[shapeless] final class Instance[KV, V0](val unwrap: C[V0]) extends Wrap[KV] { + type V = V0 + def label(values: V): KV = values.asInstanceOf[KV] + def unlabel(record: KV): V = record.asInstanceOf[V] } - implicit def deriveHCons[HK <: String, HV, TKV <: HList]( - implicit key: Witness.Aux[HK], ch: Lazy[C[HV]], ct: Wrap[TKV] { type V <: HList } - ): Wrap.Aux[FieldType[HK, HV] :: TKV, HV :: ct.V] = new Wrap[FieldType[HK, HV] :: TKV] { - type V = HV :: ct.V - val unwrap = typeClass.product(key.value, ch.value, ct.unwrap) - def label(v: V): FieldType[HK, HV] :: TKV = field[HK](v.head) :: ct.label(v.tail) - def unlabel(rec: FieldType[HK, HV] :: TKV): V = rec.head :: ct.unlabel(rec.tail) - } + implicit def deriveHNil: Wrap.Aux[HNil, HNil] = + new Instance(typeClass.emptyProduct) + + implicit def deriveHCons[HK <: String, HV, TKV <: HList, TV <: HList]( + implicit key: Witness.Aux[HK], ch: Lazy[C[HV]], ct: Wrap.Aux[TKV, TV] + ): Wrap.Aux[FieldType[HK, HV] :: TKV, HV :: TV] = + new Instance[FieldType[HK, HV] :: TKV, HV :: TV]( + typeClass.product(key.value, ch.value, ct.unwrap) + ) implicit def deriveInstance[T, LKV]( - implicit lgen: LabelledGeneric.Aux[T, LKV], lwclkv: Lazy[Wrap[LKV]] + implicit lgen: LabelledGeneric.Aux[T, LKV], wrap: Lazy[Wrap[LKV]] ): C[T] = { - import lwclkv.value._ - val to: T => V = (t: T) => unlabel(lgen.to(t)) - val from: V => T = (v: V) => lgen.from(label(v)) + import wrap.value._ + val to = (t: T) => unlabel(lgen.to(t)) + val from = (v: V) => lgen.from(label(v)) typeClass.project(unwrap, to, from) } } @@ -171,25 +171,13 @@ trait LabelledTypeClass[C[_]] extends LabelledProductTypeClass[C] { trait LabelledTypeClassCompanion[C[_]] extends LabelledProductTypeClassCompanion[C] { val typeClass: LabelledTypeClass[C] - implicit def deriveCNil: Wrap.Aux[CNil, CNil] = new Wrap[CNil] { - type V = CNil - val unwrap = typeClass.emptyCoproduct - def label(v: CNil): CNil = ??? - def unlabel(rec: CNil): CNil = ??? - } + implicit def deriveCNil: Wrap.Aux[CNil, CNil] = + new Instance(typeClass.emptyCoproduct) - implicit def deriveCCons[HK <: String, HV, TKV <: Coproduct]( - implicit key: Witness.Aux[HK], ch: Lazy[C[HV]], ct: Wrap[TKV] { type V <: Coproduct } - ): Wrap.Aux[FieldType[HK, HV] :+: TKV, HV :+: ct.V] = new Wrap[FieldType[HK, HV] :+: TKV] { - type V = HV :+: ct.V - val unwrap = typeClass.coproduct(key.value, ch.value, ct.unwrap) - def label(v: V): FieldType[HK, HV] :+: TKV = v match { - case Inl(hv) => Inl(field[HK](hv)) - case Inr(tv) => Inr(ct.label(tv)) - } - def unlabel(rec: FieldType[HK, HV] :+: TKV): V = rec match { - case Inl(hkv) => Inl(hkv) - case Inr(tkv) => Inr(ct.unlabel(tkv)) - } - } + implicit def deriveCCons[HK <: String, HV, TKV <: Coproduct, TV <: Coproduct]( + implicit key: Witness.Aux[HK], ch: Lazy[C[HV]], ct: Wrap.Aux[TKV, TV] + ): Wrap.Aux[FieldType[HK, HV] :+: TKV, HV :+: TV] = + new Instance[FieldType[HK, HV] :+: TKV, HV :+: TV]( + typeClass.coproduct(key.value, ch.value, ct.unwrap) + ) } From 0488fea2243a21e389b291b5dcf6e7d9cbe8748a Mon Sep 17 00:00:00 2001 From: Georgi Krastev Date: Sat, 11 Apr 2020 12:14:08 +0200 Subject: [PATCH 10/17] Factor out labelsOf a type --- core/src/main/scala/shapeless/labelled.scala | 37 ++++++++++---------- 1 file changed, 19 insertions(+), 18 deletions(-) diff --git a/core/src/main/scala/shapeless/labelled.scala b/core/src/main/scala/shapeless/labelled.scala index 809b9d034..5ad72db1d 100644 --- a/core/src/main/scala/shapeless/labelled.scala +++ b/core/src/main/scala/shapeless/labelled.scala @@ -118,24 +118,25 @@ class LabelledMacros(override val c: whitebox.Context) extends GenericMacros(c) private def parseLiteralTypeOrFail(tpe: String): Type = parseLiteralType(tpe).getOrElse(abort(s"Malformed literal type $tpe")) + private def labelsOf(tpe: Type): List[Constant] = + if (isProduct(tpe)) fieldsOf(tpe).map { case (f, _) => nameAsValue(f) } + else if (isCoproduct(tpe)) ctorsOf(tpe).map(c => nameAsValue(nameOf(c))) + else abort(s"$tpe is not case class like or the root of a sealed family of types") + def mkLabelledGeneric[T: WeakTypeTag, R]: Tree = { - val q"$_.instance[$_, $labels]($_)" = mkLabelling[T] - val generic @ q"$_.instance[$_, $repr]($_, $_)" = mkGeneric[T] - val keys = unpackHList(labels.tpe) + val tpe = weakTypeOf[T] + val keys = labelsOf(tpe).map(constantType) + val generic @ q"$_.instance[$_, ${repr: Tree}]($_, $_)" = mkGeneric[T] val isProduct = repr.tpe <:< hlistTpe val values = if (isProduct) unpackHList(repr.tpe) else unpackCoproduct(repr.tpe) val items = keys.zip(values).map((FieldType.apply _).tupled) val labelled = if (isProduct) mkHListTpe(items) else mkCoproductTpe(items) - q"${reify(LabelledGeneric)}.unsafeInstance[${weakTypeOf[T]}, $labelled]($generic)" + q"${reify(LabelledGeneric)}.unsafeInstance[$tpe, $labelled]($generic)" } def mkLabelling[T: WeakTypeTag]: Tree = { val tpe = weakTypeOf[T] - val labels: List[Constant] = - if (isProduct(tpe)) fieldsOf(tpe).map { case (f, _) => nameAsValue(f) } - else if (isCoproduct(tpe)) ctorsOf(tpe).map(c => nameAsValue(nameOf(c))) - else abort(s"$tpe is not case class like or the root of a sealed family of types") - + val labels = labelsOf(tpe) val labelsType = mkHListTpe(labels.map(constantType)) val labelsValue = mkHListValue(labels.map(Literal.apply)) q"${reify(Labelling)}.instance[$tpe, $labelsType]($labelsValue.asInstanceOf[$labelsType])" @@ -147,14 +148,14 @@ class LabelledMacros(override val c: whitebox.Context) extends GenericMacros(c) def unionType(tpeSelector: Tree): Tree = labelledType(tpeSelector, "union", cnilTpe, cconsTpe) - def labelledType(tpeSelector: Tree, variety: String, nilTpe: Type, consTpe: Type): Tree = { + def labelledType(tpeSelector: Tree, variety: String, nil: Type, cons: Type): Tree = { val q"${tpeString: String}" = tpeSelector - val labelledTpe = commaSeparated(tpeString).foldRight(nilTpe) { (element, acc) => + val labelledTpe = commaSeparated(tpeString).foldRight(nil) { (element, acc) => element.split("->") match { - case Array(key, value) => - val keyTpe = parseLiteralTypeOrFail(key.trim) - val valueTpe = parseTypeOrFail(value.trim) - appliedType(consTpe, appliedType(fieldTypeTpe, keyTpe, valueTpe), acc) + case Array(keyString, valueString) => + val key = parseLiteralTypeOrFail(keyString.trim) + val value = parseTypeOrFail(valueString.trim) + appliedType(cons, FieldType(key, value), acc) case _ => abort(s"Malformed $variety type $tpeString") } @@ -169,10 +170,10 @@ class LabelledMacros(override val c: whitebox.Context) extends GenericMacros(c) def coproductType(tpeSelector: Tree): Tree = nonLabelledType(tpeSelector, cnilTpe, cconsTpe) - def nonLabelledType(tpeSelector: Tree, nilTpe: Type, consTpe: Type): Tree = { + def nonLabelledType(tpeSelector: Tree, nil: Type, cons: Type): Tree = { val q"${tpeString: String}" = tpeSelector - val tpe = commaSeparated(tpeString).foldRight(nilTpe) { (element, acc) => - appliedType(consTpe, parseTypeOrFail(element), acc) + val tpe = commaSeparated(tpeString).foldRight(nil) { (element, acc) => + appliedType(cons, parseTypeOrFail(element), acc) } typeCarrier(tpe) From 793a893946d261732a59699364743c8664b22c00 Mon Sep 17 00:00:00 2001 From: Georgi Krastev Date: Sat, 11 Apr 2020 19:14:17 +0200 Subject: [PATCH 11/17] Remove special support for singleton symbols It was always a hack anyway. --- .../test/scala/shapeless/serialization.scala | 40 +-- .../src/main/scala/shapeless/singletons.scala | 297 +++++++----------- .../scala/shapeless/syntax/singletons.scala | 6 +- core/src/main/scala/shapeless/typeable.scala | 3 - core/src/test/scala/shapeless/coproduct.scala | 50 +-- core/src/test/scala/shapeless/hlist.scala | 24 +- .../scala/shapeless/labelledgeneric.scala | 14 +- core/src/test/scala/shapeless/records.scala | 93 +++--- .../src/test/scala/shapeless/singletons.scala | 194 ++++-------- core/src/test/scala/shapeless/typeable.scala | 12 +- core/src/test/scala/shapeless/unions.scala | 56 ++-- 11 files changed, 314 insertions(+), 475 deletions(-) diff --git a/core/jvm/src/test/scala/shapeless/serialization.scala b/core/jvm/src/test/scala/shapeless/serialization.scala index 792d2f67e..7ccc95d7e 100644 --- a/core/jvm/src/test/scala/shapeless/serialization.scala +++ b/core/jvm/src/test/scala/shapeless/serialization.scala @@ -170,15 +170,15 @@ object SerializationTestDefns { case class Box[T](t: T) - type K = HList.`'a, 'b, 'c`.T - type R = Record.`'a -> Int, 'b -> String, 'c -> Boolean`.T - type U = Union.`'a -> Int, 'b -> String, 'c -> Boolean`.T - type RM = Record.`'c -> Boolean, 'd -> Double`.T - type RM1 = Record.`'c -> Boolean, 'b -> String`.T - type RM2 = Record.`'b -> String, 'c -> Boolean`.T - type KA = Witness.`'a`.T - type KB = Witness.`'b`.T - type KC = Witness.`'c`.T + type K = HList.`"a", "b", "c"`.T + type R = Record.`"a" -> Int, "b" -> String, "c" -> Boolean`.T + type U = Union.`"a" -> Int, "b" -> String, "c" -> Boolean`.T + type RM = Record.`"c" -> Boolean, "d" -> Double`.T + type RM1 = Record.`"c" -> Boolean, "b" -> String`.T + type RM2 = Record.`"b" -> String, "c" -> Boolean`.T + type KA = Witness.`"a"`.T + type KB = Witness.`"b"`.T + type KC = Witness.`"c"`.T sealed trait Tree[T] case class Leaf[T](t: T) extends Tree[T] @@ -285,7 +285,7 @@ class SerializationTests { val cs = Coproduct[ISB]("foo") val cb = Coproduct[ISB](true) - val r = Symbol("foo") ->> 23 :: Symbol("bar") ->> "foo" :: Symbol("baz") ->> true :: HNil + val r = "foo" ->> 23 :: "bar" ->> "foo" :: "baz" ->> true :: HNil val prim = new Primary(42) val sec = new Secondary("qux") @@ -310,7 +310,7 @@ class SerializationTests { type ISB = Int :+: String :+: Boolean :+: CNil val cs = Coproduct[ISB]("foo") - val r = Symbol("foo") ->> 23 :: Symbol("bar") ->> "foo" :: Symbol("baz") ->> true :: HNil + val r = "foo" ->> 23 :: "bar" ->> "foo" :: "baz" ->> true :: HNil type U = Union.`"foo" -> Int, "bar" -> String, "baz" -> Boolean`.T val u = Union[U](bar = "quux") @@ -353,7 +353,7 @@ class SerializationTests { type LT = (Int, String) :: (Boolean, Double) :: (Char, Float) :: HNil type AL = (Int => Double) :: (String => Char) :: (Boolean => Float) :: HNil type I3 = Int :: Int :: Int :: HNil - val s = HList.`'a, "boo", 23, true` + val s = HList.`"a", "boo", 23, true` type S = s.T assertSerializable(IsHCons[L]) @@ -614,7 +614,7 @@ class SerializationTests { type L = Int :+: String :+: Boolean :+: CNil type LP = String :+: Boolean :+: Int :+: CNil type BS = Boolean :+: String :+: CNil - val s = Coproduct.`'a, "boo", 23, true` + val s = Coproduct.`"a", "boo", 23, true` type S = s.T assertSerializable(Inject[L, Int]) @@ -988,16 +988,16 @@ class SerializationTests { // special cases of referenceSingletonTypeable, // because symbols and objects preserve their // identity during serialization/deserialization: - assertSerializable(Typeable[Witness.`'foo`.T]) + assertSerializable(Typeable[Witness.`"foo"`.T]) assertSerializable(Typeable[Sing.type]) assertSerializable(Typeable[CaseObj.type]) // check that they indeed work // correctly after deserialization: - val symInst = roundtrip(Typeable[Witness.`'foo`.T]) - assertTrue(symInst.cast(Symbol("foo") : Any).isDefined) + val symInst = roundtrip(Typeable[Witness.`"foo"`.T]) + assertTrue(symInst.cast("foo": Any).isDefined) val objInst = roundtrip(Typeable[Sing.type]) - assertTrue(objInst.cast(Sing : Any).isDefined) + assertTrue(objInst.cast(Sing: Any).isDefined) val caseObjInst = roundtrip(Typeable[CaseObj.type]) assertTrue(caseObjInst.cast(CaseObj).isDefined) @@ -1112,8 +1112,8 @@ class SerializationTests { type OL = Option[Int] :: Option[String] :: Option[Boolean] :: HNil type I3 = Int :: Int :: Int :: HNil type IS = Int :: String :: HNil - type R = Record.`'a -> Int, 'b -> String, 'c -> Boolean`.T - type K = HList.`'a, 'b, 'c`.T + type R = Record.`"a" -> Int, "b" -> String, "c" -> Boolean`.T + type K = HList.`"a", "b", "c"`.T assertSerializable(UnaryTCConstraint[HNil, Option]) assertSerializable(UnaryTCConstraint[OL, Option]) @@ -1190,7 +1190,7 @@ class SerializationTests { val l8 = optic.hlistSelectLens[Int :: String :: Boolean :: HNil, String] val l9 = optic.coproductSelectPrism[Int :+: String :+: Boolean :+: CNil, String] val l10 = optic.hlistNthLens[Int :: String :: Boolean :: HNil, _1] - val l11 = optic.recordLens[Record.`'foo -> Int, 'bar -> String, 'baz -> Boolean`.T](Symbol("bar")) + val l11 = optic.recordLens[Record.`"foo" -> Int, "bar" -> String, "baz" -> Boolean`.T]("bar") val l12 = optic[Tree[Int]].l.r.l.t val l13 = optic[Node[Int]] >> "r" val l14 = optic[Node[Int]] >> _1 diff --git a/core/src/main/scala/shapeless/singletons.scala b/core/src/main/scala/shapeless/singletons.scala index 5896cb519..f58156460 100644 --- a/core/src/main/scala/shapeless/singletons.scala +++ b/core/src/main/scala/shapeless/singletons.scala @@ -21,9 +21,6 @@ import shapeless.syntax.SingletonOps import scala.language.dynamics import scala.language.experimental.macros import scala.reflect.macros.whitebox -import tag.@@ - -import scala.util.Try /** Provides the value corresponding to a singleton type. * @@ -160,98 +157,57 @@ object Widen { @macrocompat.bundle trait SingletonTypeUtils extends ReprTypes { - import c.universe.{ Try => _, _ } - import internal.decorators._ - - def singletonOpsTpe = typeOf[syntax.SingletonOps] - val SymTpe = typeOf[scala.Symbol] - - object LiteralSymbol { - def unapply(t: Tree): Option[String] = t match { - case Literal(Constant(s: scala.Symbol)) => Some(s.name) - case q""" scala.Symbol.apply(${Literal(Constant(s: String))}) """ => Some(s) - case _ => None - } - } - - object SingletonSymbolType { - val atatTpe = typeOf[@@[_,_]].typeConstructor - val TaggedSym = typeOf[tag.Tagged[_]].typeConstructor.typeSymbol - - def unrefine(t: Type): Type = - t.dealias match { - case RefinedType(List(t), scope) if scope.isEmpty => unrefine(t) - case t => t - } - - def apply(s: String): Type = appliedType(atatTpe, List(SymTpe, c.internal.constantType(Constant(s)))) - - def unapply(t: Type): Option[String] = - unrefine(t).dealias match { - case RefinedType(List(SymTpe, TypeRef(_, TaggedSym, List(ConstantType(Constant(s: String))))), _) => Some(s) - case _ => None - } - } + import c.universe._ + import internal._ + import decorators._ - def mkSingletonSymbol(s: String): Tree = { - val sTpe = SingletonSymbolType(s) - q"""_root_.scala.Symbol($s).asInstanceOf[$sTpe]""" - } + def singletonOpsTpe: Type = typeOf[syntax.SingletonOps] object SingletonType { - def unapply(t: Tree): Option[Type] = (t, t.tpe) match { - case (LiteralSymbol(s), _) => Some(SingletonSymbolType(s)) - case (Literal(k: Constant), _) => Some(c.internal.constantType(k)) - case (_, keyType @ SingleType(p, v)) if !v.isParameter && !isValueClass(v) => Some(keyType) - case (q""" $sops.narrow """, _) if sops.tpe <:< singletonOpsTpe => + def unapply(value: Tree): Option[Type] = (value, value.tpe) match { + case (Literal(const), _) => Some(constantType(const)) + case (_, keyType @ SingleType(_, v)) if !v.isParameter && !isValueClass(v) => Some(keyType) + case (q"${sops: Tree}.narrow", _) if sops.tpe <:< singletonOpsTpe => Some(sops.tpe.member(TypeName("T")).typeSignature) case _ => None } } - def narrowValue(t: Tree): (Type, Tree) = { - t match { - case LiteralSymbol(s) => (SingletonSymbolType(s), mkSingletonSymbol(s)) - case Literal(k: Constant) => - val tpe = c.internal.constantType(k) - (tpe, q"$t.asInstanceOf[$tpe]") - case _ => (t.tpe, t) - } + def narrowValue(value: Tree): (Type, Tree) = value match { + case Literal(const) => + val tpe = constantType(const) + (tpe, q"$value.asInstanceOf[$tpe]") + case _ => + (value.tpe, value) } - def parseSingletonSymbolType(typeStr: String): Option[Type] = - if (typeStr.startsWith("'") && !typeStr.endsWith("'")) - Some(SingletonSymbolType(typeStr.tail)) - else - None - - def parseLiteralType(typeStr: String): Option[Type] = - parseSingletonSymbolType(typeStr).orElse( - for { - parsed <- Try(c.parse(typeStr)).toOption - checked = c.typecheck(parsed, silent = true) - if checked.nonEmpty - tpe <- SingletonType.unapply(checked) - } yield tpe - ) - - def parseStandardType(typeStr: String): Option[Type] = - for { - parsed <- Try(c.parse(s"null.asInstanceOf[$typeStr]")).toOption - checked = c.typecheck(parsed, silent = true) - if checked.nonEmpty - } yield checked.tpe + def parseLiteralType(typeStr: String): Option[Type] = for { + parsed <- util.Try(c.parse(typeStr)).toOption + checked <- Option(c.typecheck(parsed, silent = true)) + if checked.nonEmpty + tpe <- SingletonType.unapply(checked) + } yield tpe + + def parseStandardType(typeStr: String): Option[Type] = for { + parsed <- util.Try(c.parse(s"null.asInstanceOf[$typeStr]")).toOption + checked <- Option(c.typecheck(parsed, silent = true)) + if checked.nonEmpty + } yield checked.tpe def parseType(typeStr: String): Option[Type] = - parseSingletonSymbolType(typeStr) orElse parseStandardType(typeStr) orElse parseLiteralType(typeStr) + parseStandardType(typeStr) orElse parseLiteralType(typeStr) - def typeCarrier(tpe: Type) = + def typeCarrier(tpe: Type): Literal = mkTypeCarrier(tq"{ type T = $tpe }") - def fieldTypeCarrier(tpe: Type) = - mkTypeCarrier(tq"{ type T = $tpe ; type ->>[V] = Field[V] ; type Field[V] = _root_.shapeless.labelled.FieldType[$tpe,V] }") + def fieldTypeCarrier(tpe: Type): Literal = + mkTypeCarrier(tq"""{ + type T = $tpe + type ->>[V] = Field[V] + type Field[V] = _root_.shapeless.labelled.FieldType[$tpe, V] + }""") - def mkTypeCarrier(tree: Tree) = { + def mkTypeCarrier(tree: Tree): Literal = { val carrier = c.typecheck(tree, mode = c.TYPEmode).tpe // We can't yield a useful value here, so return Unit instead which is at least guaranteed @@ -269,28 +225,25 @@ trait SingletonTypeUtils extends ReprTypes { class SingletonTypeMacros(val c: whitebox.Context) extends SingletonTypeUtils with NatMacroDefns { import c.universe._ import definitions._ + import internal._ - def mkWitness(sTpe: Type, s: Tree): Tree = { - val witness = objectRef[Witness.type] - q"$witness.mkWitness[$sTpe]($s.asInstanceOf[$sTpe])" - } + def mkWitness(sTpe: Type, s: Tree): Tree = + q"${reify(Witness)}.mkWitness[$sTpe]($s.asInstanceOf[$sTpe])" def mkWitnessWith(tcTpe: Type, sTpe: Type, s: Tree, i: Tree): Tree = { - val witnessWith = objectRef[WitnessWith.type] + val witnessWith = reify(WitnessWith) if (appliedType(tcTpe, AnyValTpe) <:< AnyRefTpe) q"$witnessWith.depInstance[$tcTpe, $sTpe]($s, $i)" else q"$witnessWith.instance[$tcTpe, $sTpe]($s, $i)" } def mkWitnessNat(tcTpe: Type, nTpe: Type, tc: Tree): Tree = { - val natWith = objectRef[NatWith.type] + val natWith = reify(NatWith) if (appliedType(tcTpe, AnyValTpe) <:< AnyRefTpe) q"$natWith.depInstance[$tcTpe, $nTpe]($tc)" else q"$natWith.instance[$tcTpe, $nTpe]($tc)" } - def mkOps(sTpe: Type, w: Tree): Tree = { - val ops = objectRef[SingletonOps.type] - q"$ops.instance[$sTpe]($w)" - } + def mkOps(sTpe: Type, w: Tree): Tree = + q"${reify(SingletonOps)}.instance[$sTpe]($w)" def mkAttributedQualifier(tpe: Type): Tree = { val global = c.universe.asInstanceOf[scala.tools.nsc.Global] @@ -298,137 +251,115 @@ class SingletonTypeMacros(val c: whitebox.Context) extends SingletonTypeUtils wi global.gen.mkAttributedQualifier(gTpe).asInstanceOf[Tree] } - def extractSingletonValue(tpe: Type): Tree = - SingletonSymbolType.unrefine(tpe) match { - case ConstantType(Constant(sym: scala.Symbol)) => mkSingletonSymbol(sym.name) - case ConstantType(const) => Literal(const) - case singleton: SingleType => mkAttributedQualifier(singleton) - case SingletonSymbolType(name) => mkSingletonSymbol(name) - case ThisType(sym) => This(sym) - case ref @ TypeRef(_, sym, _) if sym.isModuleClass => mkAttributedQualifier(ref) - case _ => c.abort(c.enclosingPosition, s"Type argument $tpe is not a singleton type") - } + @annotation.tailrec + final def unrefine(tpe: Type): Type = tpe.dealias match { + case RefinedType(List(parent), scope) if scope.isEmpty => unrefine(parent) + case other => other + } + + def extractSingletonValue(tpe: Type): Tree = unrefine(tpe) match { + case ConstantType(const) => Literal(const) + case singleton: SingleType => mkAttributedQualifier(singleton) + case ThisType(sym) => This(sym) + case ref @ TypeRef(_, sym, _) if sym.isModuleClass => mkAttributedQualifier(ref) + case _ => c.abort(c.enclosingPosition, s"Type argument $tpe is not a singleton type") + } def materializeImpl[T: WeakTypeTag]: Tree = { val tpe = weakTypeOf[T].dealias mkWitness(tpe, extractSingletonValue(tpe)) } - def extractResult(t: Tree)(mkResult: (Type, Tree) => Tree): Tree = - (t.tpe, t) match { - case (ConstantType(Constant(s: scala.Symbol)), _) => - mkResult(SingletonSymbolType(s.name), mkSingletonSymbol(s.name)) - - case (tpe @ ConstantType(c: Constant), _) => - mkResult(tpe, Literal(c)) + def extractResult(value: Tree)(mkResult: (Type, Tree) => Tree): Tree = + (value.tpe, value) match { + case (tpe @ ConstantType(const), _) => + mkResult(tpe, Literal(const)) - case (tpe @ SingleType(p, v), tree) => + case (tpe: SingleType, tree) => mkResult(tpe, tree) - case (SymTpe, LiteralSymbol(s)) => - mkResult(SingletonSymbolType(s), mkSingletonSymbol(s)) + case (_, tree: This) => + mkResult(thisType(tree.symbol), tree) - case (_, tree @ This(_)) => - mkResult(internal.thisType(tree.symbol), tree) - - case (tpe, tree) if (tree.symbol ne null) && tree.symbol.isTerm && tree.symbol.asTerm.isStable => + case (_, tree) if (tree.symbol ne null) && tree.symbol.isTerm && tree.symbol.asTerm.isStable => val sym = tree.symbol.asTerm - val pre = if(sym.owner.isClass) c.internal.thisType(sym.owner) else NoPrefix - val symTpe = c.internal.singleType(pre, sym) + val pre = if (sym.owner.isClass) thisType(sym.owner) else NoPrefix + val symTpe = singleType(pre, sym) mkResult(symTpe, q"$sym.asInstanceOf[$symTpe]") case _ => - c.abort(c.enclosingPosition, s"Expression $t does not evaluate to a constant or a stable reference value") + c.abort(c.enclosingPosition, s"Expression $value does not evaluate to a constant or a stable reference value") } def convertImpl(t: Tree): Tree = extractResult(t)(mkWitness) def inferInstance(tci: Type): Tree = { - val i = c.inferImplicitValue(tci) - if(i == EmptyTree) + val inferred = c.inferImplicitValue(tci) + if (inferred == EmptyTree) c.abort(c.enclosingPosition, s"Unable to resolve implicit value of type $tci") - i + inferred } - def convertInstanceImplNat[TC[_ <: Nat]](i: Tree) - (implicit tcTag: WeakTypeTag[TC[Nothing]]): Tree = - convertInstanceImplNatAux(i, tcTag.tpe) - - def convertInstanceImplNat1[B, T <: B, TC[_ <: B, _ <: Nat]](i: Tree) - (implicit tTag: WeakTypeTag[T], tcTag: WeakTypeTag[TC[Nothing, Nothing]]): Tree = { - val tTpe = tTag.tpe - val tc = tcTag.tpe.typeConstructor - val tcParam = tc.typeParams(1) - val tcTpe = c.internal.polyType(List(tcParam), appliedType(tc, List(tTpe, tcParam.asType.toType))) - convertInstanceImplNatAux(i, tcTpe) - } + def convertInstanceImplNat[TC[_ <: Nat]](i: Tree)( + implicit tcTag: WeakTypeTag[TC[Nothing]] + ): Tree = convertInstanceImplNatAux(i, tcTag.tpe) + + def convertInstanceImplNat1[B, T <: B, TC[_ <: B, _ <: Nat]](i: Tree)( + implicit tTag: WeakTypeTag[T], tcTag: WeakTypeTag[TC[Nothing, Nothing]] + ): Tree = { + val tTpe = tTag.tpe + val tc = tcTag.tpe.typeConstructor + val tcParam = tc.typeParams(1) + val tcTpe = polyType(List(tcParam), appliedType(tc, tTpe, tcParam.asType.toType)) + convertInstanceImplNatAux(i, tcTpe) + } def convertInstanceImplNatAux(i: Tree, tcTpe: Type): Tree = { - val nTpe = i match { - case NatLiteral(n) => mkNatTpe(n) - case _ => c.abort(c.enclosingPosition, s"Expression $i does not evaluate to a non-negative Int literal") - } - - val instTpe = appliedType(tcTpe, nTpe) - val iInst = inferInstance(instTpe) - mkWitnessNat(tcTpe, nTpe, iInst) + val nTpe = i match { + case NatLiteral(n) => mkNatTpe(n) + case _ => c.abort(c.enclosingPosition, s"Expression $i does not evaluate to a non-negative Int literal") + } + + val instTpe = appliedType(tcTpe, nTpe) + val iInst = inferInstance(instTpe) + mkWitnessNat(tcTpe, nTpe, iInst) } - def convertInstanceImpl1[TC[_]](t: Tree) - (implicit tcTag: WeakTypeTag[TC[_]]): Tree = - extractResult(t) { (sTpe, value) => - val tc = tcTag.tpe.typeConstructor - val tci = appliedType(tc, sTpe) - val i = inferInstance(tci) - mkWitnessWith(tc, sTpe, value, i) - } - - def convertInstanceImpl2[H, TC2[_ <: H, _], S <: H](t: Tree) - (implicit tc2Tag: WeakTypeTag[TC2[_, _]], sTag: WeakTypeTag[S]): Tree = - extractResult(t) { (sTpe, value) => - val tc2 = tc2Tag.tpe.typeConstructor - val tparam = tc2.typeParams.last.asType - val tc = c.internal.polyType(tparam :: Nil, appliedType(tc2, sTag.tpe, tparam.toType)) - val tci = appliedType(tc2, sTag.tpe, sTpe) - val i = inferInstance(tci) - mkWitnessWith(tc, sTpe, value, i) - } + def convertInstanceImpl1[TC[_]](t: Tree)( + implicit tcTag: WeakTypeTag[TC[_]] + ): Tree = extractResult(t) { (sTpe, value) => + val tc = tcTag.tpe.typeConstructor + val tci = appliedType(tc, sTpe) + val i = inferInstance(tci) + mkWitnessWith(tc, sTpe, value, i) + } + + def convertInstanceImpl2[H, TC2[_ <: H, _], S <: H](t: Tree)( + implicit tc2Tag: WeakTypeTag[TC2[_, _]], sTag: WeakTypeTag[S] + ): Tree = extractResult(t) { (sTpe, value) => + val tc2 = tc2Tag.tpe.typeConstructor + val tparam = tc2.typeParams.last.asType + val tc = polyType(tparam :: Nil, appliedType(tc2, sTag.tpe, tparam.toType)) + val tci = appliedType(tc2, sTag.tpe, sTpe) + val i = inferInstance(tci) + mkWitnessWith(tc, sTpe, value, i) + } def mkSingletonOps(t: Tree): Tree = extractResult(t) { (tpe, tree) => mkOps(tpe, mkWitness(tpe, tree)) } - def narrowSymbol[S <: String : WeakTypeTag](t: Tree): Tree = { - (weakTypeOf[S], t) match { - case (ConstantType(Constant(s1: String)), LiteralSymbol(s2)) if s1 == s2 => - mkSingletonSymbol(s1) - case _ => - c.abort(c.enclosingPosition, s"Expression $t is not an appropriate Symbol literal") - } - } - def witnessTypeImpl(tpeSelector: Tree): Tree = { val q"${tpeString: String}" = tpeSelector - val tpe = - parseLiteralType(tpeString) - .getOrElse(c.abort(c.enclosingPosition, s"Malformed literal $tpeString")) + val tpe = parseLiteralType(tpeString) + .getOrElse(c.abort(c.enclosingPosition, s"Malformed literal $tpeString")) fieldTypeCarrier(tpe) } def materializeWiden[T: WeakTypeTag, Out: WeakTypeTag]: Tree = { val tpe = weakTypeOf[T].dealias - - val widenTpe = tpe match { - case SingletonSymbolType(s) => symbolTpe - case _ => tpe.widen - } - - if (widenTpe =:= tpe) { - c.abort(c.enclosingPosition, s"Don't know how to widen $tpe") - } else { - val widen = objectRef[Widen.type] - val predef = objectRef[Predef.type] - q"$widen.instance[$tpe, $widenTpe]($predef.identity)" - } + val wideTpe = tpe.widen + if (wideTpe =:= tpe) c.abort(c.enclosingPosition, s"Don't know how to widen $tpe") + else q"${reify(Widen)}.instance[$tpe, $wideTpe](${reify(Predef)}.identity)" } } diff --git a/core/src/main/scala/shapeless/syntax/singletons.scala b/core/src/main/scala/shapeless/syntax/singletons.scala index ff923ef64..b586dc323 100644 --- a/core/src/main/scala/shapeless/syntax/singletons.scala +++ b/core/src/main/scala/shapeless/syntax/singletons.scala @@ -20,10 +20,8 @@ package syntax import scala.language.experimental.macros object singleton { - implicit def mkSingletonOps(t: Any): SingletonOps = macro SingletonTypeMacros.mkSingletonOps - - import tag._ - implicit def narrowSymbol[S <: String](t: Symbol): Symbol @@ S = macro SingletonTypeMacros.narrowSymbol[S] + implicit def mkSingletonOps(t: Any): SingletonOps = + macro SingletonTypeMacros.mkSingletonOps } trait SingletonOps { diff --git a/core/src/main/scala/shapeless/typeable.scala b/core/src/main/scala/shapeless/typeable.scala index e347507b5..5bca10992 100644 --- a/core/src/main/scala/shapeless/typeable.scala +++ b/core/src/main/scala/shapeless/typeable.scala @@ -405,9 +405,6 @@ class TypeableMacros(val c: blackbox.Context) extends SingletonTypeUtils { c.abort(c.enclosingPosition, s"No default Typeable for parametrized type $tpe") normalizedTypeable - case SingletonSymbolType(c) => - q"""_root_.shapeless.Typeable.valueSingletonTypeable[$tpe](${mkSingletonSymbol(c)}, "Symbol")""" - case RefinedType(parents, decls) => if (decls.nonEmpty) c.abort(c.enclosingPosition, "No Typeable for a refinement with non-empty decls") diff --git a/core/src/test/scala/shapeless/coproduct.scala b/core/src/test/scala/shapeless/coproduct.scala index 21030166d..73179e3eb 100644 --- a/core/src/test/scala/shapeless/coproduct.scala +++ b/core/src/test/scala/shapeless/coproduct.scala @@ -417,28 +417,28 @@ class CoproductTests { @Test def testWithKeys: Unit = { - type U = Union.`'i -> Int, 's -> String, 'b -> Boolean`.T + type U = Union.`"i" -> Int, "s" -> String, "b" -> Boolean`.T val cKeys = Keys[U].apply() val u1 = Coproduct[ISB](23).zipWithKeys(cKeys) - val v1 = u1.get(Symbol("i")) + val v1 = u1.get("i") typed[Option[Int]](v1) assertEquals(Some(23), v1) - assertEquals(None, u1.get(Symbol("s"))) + assertEquals(None, u1.get("s")) val u2 = Coproduct[ISB]("foo").zipWithKeys(cKeys) - val v2 = u2.get(Symbol("s")) + val v2 = u2.get("s") typed[Option[String]](v2) assertEquals(Some("foo"), v2) - assertEquals(None, u2.get(Symbol("b"))) + assertEquals(None, u2.get("b")) val u3 = Coproduct[ISB](true).zipWithKeys(cKeys) - val v3 = u3.get(Symbol("b")) + val v3 = u3.get("b") typed[Option[Boolean]](v3) assertEquals(Some(true), v3) - assertEquals(None, u3.get(Symbol("i"))) + assertEquals(None, u3.get("i")) - illTyped("""v3.get(Symbol("d"))""") + illTyped("""v3.get("d")""") // key/value lengths must match up illTyped("u1.zipWithKeys(uKeys.tail)") @@ -446,32 +446,32 @@ class CoproductTests { // Explicit type argument { - val u1 = Coproduct[ISB](23).zipWithKeys[HList.`'i, 's, 'b`.T] - val v1 = u1.get(Symbol("i")) + val u1 = Coproduct[ISB](23).zipWithKeys[HList.`"i", "s", "b"`.T] + val v1 = u1.get("i") typed[Option[Int]](v1) assertEquals(Some(23), v1) - assertEquals(None, u1.get(Symbol("s"))) + assertEquals(None, u1.get("s")) } { - val u2 = Coproduct[ISB]("foo").zipWithKeys[HList.`'i, 's, 'b`.T] - val v2 = u2.get(Symbol("s")) + val u2 = Coproduct[ISB]("foo").zipWithKeys[HList.`"i", "s", "b"`.T] + val v2 = u2.get("s") typed[Option[String]](v2) assertEquals(Some("foo"), v2) - assertEquals(None, u2.get(Symbol("b"))) + assertEquals(None, u2.get("b")) } { - val u3 = Coproduct[ISB](true).zipWithKeys[HList.`'i, 's, 'b`.T] - val v3 = u3.get(Symbol("b")) + val u3 = Coproduct[ISB](true).zipWithKeys[HList.`"i", "s", "b"`.T] + val v3 = u3.get("b") typed[Option[Boolean]](v3) assertEquals(Some(true), v3) - assertEquals(None, u3.get(Symbol("i"))) + assertEquals(None, u3.get("i")) - illTyped("""v3.get(Symbol("d"))""") + illTyped("""v3.get("d")""") } - illTyped(" Coproduct[ISB](true).zipWithKeys[HList.`'i, 's, 'b, 'd`.T] ") + illTyped("""Coproduct[ISB](true).zipWithKeys[HList.`"i", "s", "b", "d"`.T]""") } @@ -1887,14 +1887,14 @@ class CoproductTests { assertTypedEquals(HNil, Reify[CNil].apply) - val s1 = Coproduct.`'a` - assertTypedEquals(Symbol("a").narrow :: HNil, Reify[s1.T].apply) + val s1 = Coproduct.`"a"` + assertTypedEquals("a".narrow :: HNil, Reify[s1.T].apply) - val s2 = Coproduct.`'a, 1, "b", true` - assertEquals(Symbol("a").narrow :: 1.narrow :: "b".narrow :: true.narrow :: HNil, Reify[s2.T].apply) + val s2 = Coproduct.`"a", 1, "b", true` + assertEquals("a".narrow :: 1.narrow :: "b".narrow :: true.narrow :: HNil, Reify[s2.T].apply) - illTyped(""" Reify[String :+: Int :+: CNil] """) - illTyped(""" Reify[String :+: Coproduct.`'a, 1, "b", true`.T] """) + illTyped("Reify[String :+: Int :+: CNil]") + illTyped("""Reify[String :+: Coproduct.`"a", 1, "b", true`.T]""") } @Test diff --git a/core/src/test/scala/shapeless/hlist.scala b/core/src/test/scala/shapeless/hlist.scala index 165a7d45b..16a0a4e49 100644 --- a/core/src/test/scala/shapeless/hlist.scala +++ b/core/src/test/scala/shapeless/hlist.scala @@ -3122,8 +3122,8 @@ class HListTests { def testSingletonProductArgs: Unit = { object Obj - val l = SFoo(23, "foo", Symbol("bar"), Obj, true) - typed[Witness.`23`.T :: Witness.`"foo"`.T :: Witness.`'bar`.T :: Obj.type :: Witness.`true`.T :: HNil](l) + val l = SFoo(23, "foo", "bar", Obj, true) + typed[Witness.`23`.T :: Witness.`"foo"`.T :: Witness.`"bar"`.T :: Obj.type :: Witness.`true`.T :: HNil](l) // Annotations on the LHS here and subsequently, otherwise scalac will // widen the RHS to a non-singleton type. @@ -3133,8 +3133,8 @@ class HListTests { val v2: Witness.`"foo"`.T = l.tail.head assertEquals("foo", v2) - val v3: Witness.`'bar`.T = l.tail.tail.head - assertEquals(Symbol("bar"), v3) + val v3: Witness.`"bar"`.T = l.tail.tail.head + assertEquals("bar", v3) val v4: Obj.type = l.tail.tail.tail.head assertEquals(Obj, v4) @@ -3145,9 +3145,7 @@ class HListTests { val v6 = l.tail.tail.tail.tail.tail typed[HNil](v6) - illTyped(""" - r.tail.tail.tail.tail.tail.tail.head - """) + illTyped("r.tail.tail.tail.tail.tail.tail.head") // Verify that we infer HNil rather than HNil.type at the end NonSingletonHNilTC(SFoo(23).tail) @@ -3426,14 +3424,14 @@ class HListTests { assertTypedEquals(HNil, Reify[HNil].apply) - val s1 = HList.`'a` - assertTypedEquals(Symbol("a").narrow :: HNil, Reify[s1.T].apply) + val s1 = HList.`"a"` + assertTypedEquals("a".narrow :: HNil, Reify[s1.T].apply) - val s2 = HList.`'a, 1, "b", true` - assertTypedEquals(Symbol("a").narrow :: 1.narrow :: "b".narrow :: true.narrow :: HNil, Reify[s2.T].apply) + val s2 = HList.`"a", 1, "b", true` + assertTypedEquals("a".narrow :: 1.narrow :: "b".narrow :: true.narrow :: HNil, Reify[s2.T].apply) - illTyped(""" Reify[String :: Int :: HNil] """) - illTyped(""" Reify[String :: HList.`'a, 1, "b", true`.T] """) + illTyped("Reify[String :: Int :: HNil]") + illTyped("""Reify[String :: HList.`"a", 1, "b", true`.T]""") } @Test diff --git a/core/src/test/scala/shapeless/labelledgeneric.scala b/core/src/test/scala/shapeless/labelledgeneric.scala index 158276bf6..246734b62 100644 --- a/core/src/test/scala/shapeless/labelledgeneric.scala +++ b/core/src/test/scala/shapeless/labelledgeneric.scala @@ -45,16 +45,16 @@ object LabelledGenericTestsAux { ) val taplRecord = - (Symbol("author") ->> "Benjamin Pierce") :: - (Symbol("title") ->> "Types and Programming Languages") :: - (Symbol("id") ->> 262162091) :: - (Symbol("price") ->> 44.11) :: + ("author" ->> "Benjamin Pierce") :: + ("title" ->> "Types and Programming Languages") :: + ("id" ->> 262162091) :: + ("price" ->> 44.11) :: HNil val dpRecord = - (Symbol("title") ->> "Design Patterns") :: - (Symbol("id") ->> 201633612) :: - (Symbol("authors") ->> Seq("Erich Gamma", "Richard Helm", "Ralph Johnson", "John Vlissides")) :: + ("title" ->> "Design Patterns") :: + ("id" ->> 201633612) :: + ("authors" ->> Seq("Erich Gamma", "Richard Helm", "Ralph Johnson", "John Vlissides")) :: HNil type BookRec = Record.`"author" -> String, "title" -> String, "id" -> Int, "price" -> Double`.T diff --git a/core/src/test/scala/shapeless/records.scala b/core/src/test/scala/shapeless/records.scala index c9ab17ac0..c68371c2d 100644 --- a/core/src/test/scala/shapeless/records.scala +++ b/core/src/test/scala/shapeless/records.scala @@ -43,9 +43,9 @@ class RecordTests { case class Bar(a: Int, b: String) - type MapRec = Record.`'map -> Map[String, Int]`.T - type TupleRec = Record.`'tuple -> (String, Int)`.T - type ComplexRec = Record.`'map -> Map[String, Int], 'tuple -> (String, Int)`.T + type MapRec = Record.`"map" -> Map[String, Int]`.T + type TupleRec = Record.`"tuple" -> (String, Int)`.T + type ComplexRec = Record.`"map" -> Map[String, Int], "tuple" -> (String, Int)`.T @Test def testGet: Unit = { @@ -143,9 +143,9 @@ class RecordTests { @Test def testFromMap: Unit = { - type T1 = Record.`'stringVal -> String, 'intVal -> Int, 'boolVal -> Boolean`.T + type T1 = Record.`"stringVal" -> String, "intVal" -> Int, "boolVal" -> Boolean`.T - val in = Map(Symbol("intVal") -> 4, Symbol("stringVal") -> "Blarr", Symbol("boolVal") -> true) + val in = Map("intVal" -> 4, "stringVal" -> "Blarr", "boolVal" -> true) val recOption = in.toRecord[T1] @@ -156,11 +156,11 @@ class RecordTests { typed[T1](rec) - assert(rec(Symbol("stringVal")) == "Blarr", "stringVal mismatch") - assert(rec(Symbol("intVal")) == 4, "int val mismatch") - assert(rec(Symbol("boolVal")), "Boolean val match") + assert(rec("stringVal") == "Blarr", "stringVal mismatch") + assert(rec("intVal") == 4, "int val mismatch") + assert(rec("boolVal"), "Boolean val match") - val in2 = Map(Symbol("intVal") -> 4, Symbol("stringVal") -> "Blarr") + val in2 = Map("intVal" -> 4, "stringVal" -> "Blarr") val recEither2 = in2.toRecord[T1] @@ -304,12 +304,12 @@ class RecordTests { @Test def testMerge: Unit = { - val r1 = Symbol("a") ->> 23 :: Symbol("b") ->> "foo" :: Symbol("c") ->> true :: HNil - val r2 = Symbol("c") ->> false :: Symbol("a") ->> 13 :: HNil - val rExp = Symbol("a") ->> 13 :: Symbol("b") ->> "foo" :: Symbol("c") ->> false :: HNil + val r1 = "a" ->> 23 :: "b" ->> "foo" :: "c" ->> true :: HNil + val r2 = "c" ->> false :: "a" ->> 13 :: HNil + val rExp = "a" ->> 13 :: "b" ->> "foo" :: "c" ->> false :: HNil val rm = r1.merge(r2) - typed[Record.`'a -> Int, 'b -> String, 'c -> Boolean`.T](rm) + typed[Record.`"a" -> Int, "b" -> String, "c" -> Boolean`.T](rm) assertEquals(rExp, rm) } @@ -382,22 +382,22 @@ class RecordTests { } { - val r1 = Symbol("c") ->> true :: HNil - val r2 = Symbol("c") ->> false :: HNil - val rExp = Symbol("c") ->> true :: HNil + val r1 = "c" ->> true :: HNil + val r2 = "c" ->> false :: HNil + val rExp = "c" ->> true :: HNil val rm = r1.mergeWith(r2)(mergeField) - typed[Record.`'c -> Boolean`.T](rm) + typed[Record.`"c" -> Boolean`.T](rm) assertEquals(rExp, rm) } { - val r1 = Symbol("a") ->> 23 :: Symbol("b") ->> "foo" :: Symbol("c") ->> true :: HNil - val r2 = Symbol("c") ->> false :: Symbol("a") ->> "13" :: HNil - val rExp = Symbol("a") ->> 36.0 :: Symbol("b") ->> "foo" :: Symbol("c") ->> true :: HNil + val r1 = "a" ->> 23 :: "b" ->> "foo" :: "c" ->> true :: HNil + val r2 = "c" ->> false :: "a" ->> "13" :: HNil + val rExp = "a" ->> 36.0 :: "b" ->> "foo" :: "c" ->> true :: HNil val rm = r1.mergeWith(r2)(mergeField) - typed[Record.`'a -> Double, 'b -> String, 'c -> Boolean`.T](rm) + typed[Record.`"a" -> Double, "b" -> String, "c" -> Boolean`.T](rm) assertEquals(rExp, rm) } } @@ -611,17 +611,16 @@ class RecordTests { @Test def testRemoveAll: Unit = { + type R = Record.`"i" -> Int, "s" -> String, "c" -> Char, "j" -> Int`.T + type L = Record.`"c" -> Char, "j" -> Int`.T + type L2 = Record.`"s" -> String, "c" -> Char`.T - type R = Record.`'i -> Int, 's -> String, 'c -> Char, 'j -> Int`.T - type L = Record.`'c -> Char, 'j -> Int`.T - type L2 = Record.`'s -> String, 'c -> Char`.T - - type A1 = Record.`'i -> Int, 's -> String`.T + type A1 = Record.`"i" -> Int, "s" -> String`.T type A2 = Int :: String :: HNil - type A3 = Record.`'i -> Int, 'j -> Int`.T + type A3 = Record.`"i" -> Int, "j" -> Int`.T type A4 = Int :: Int :: HNil - val r = Symbol("i") ->> 10 :: Symbol("s") ->> "foo" :: Symbol("c") ->> 'x' :: Symbol("j") ->> 42 :: HNil + val r = "i" ->> 10 :: "s" ->> "foo" :: "c" ->> 'x' :: "j" ->> 42 :: HNil val removeAll1 = RemoveAll[R, A1] val removeAll2 = RemoveAll[R, A2] @@ -639,28 +638,28 @@ class RecordTests { val r4 = removeAll4.reinsert((removed4, remaining4)) typed[A1](removed1) - assertEquals(Symbol("i") ->> 10 :: Symbol("s") ->> "foo" :: HNil, removed1) + assertEquals("i" ->> 10 :: "s" ->> "foo" :: HNil, removed1) typed[A2](removed2) assertEquals(10 :: "foo" :: HNil, removed2) typed[A3](removed3) - assertEquals(Symbol("i") ->> 10 :: Symbol("j") ->> 42 :: HNil, removed3) + assertEquals("i" ->> 10 :: "j" ->> 42 :: HNil, removed3) typed[A4](removed4) assertEquals(10 :: 42 :: HNil, removed4) typed[L](remaining1) - assertEquals(Symbol("c") ->> 'x' :: Symbol("j") ->> 42 :: HNil, remaining1) + assertEquals("c" ->> 'x' :: "j" ->> 42 :: HNil, remaining1) typed[L](remaining2) - assertEquals(Symbol("c") ->> 'x' :: Symbol("j") ->> 42 :: HNil, remaining2) + assertEquals("c" ->> 'x' :: "j" ->> 42 :: HNil, remaining2) typed[L2](remaining3) - assertEquals(Symbol("s") ->> "foo" :: Symbol("c") ->> 'x' :: HNil, remaining3) + assertEquals("s" ->> "foo" :: "c" ->> 'x' :: HNil, remaining3) typed[L2](remaining4) - assertEquals(Symbol("s") ->> "foo" :: Symbol("c") ->> 'x' :: HNil, remaining4) + assertEquals("s" ->> "foo" :: "c" ->> 'x' :: HNil, remaining4) typed[R](r1) assertEquals(r, r1) @@ -852,23 +851,23 @@ class RecordTests { def testRecordTypeSelector: Unit = { typed[Record.` `.T](HNil) - typed[Record.`'i -> Int`.T](Symbol("i") ->> 23 :: HNil) + typed[Record.`"i" -> Int`.T]("i" ->> 23 :: HNil) - typed[Record.`'i -> Int, 's -> String`.T](Symbol("i") ->> 23 :: Symbol("s") ->> "foo" :: HNil) + typed[Record.`"i" -> Int, "s" -> String`.T]("i" ->> 23 :: "s" ->> "foo" :: HNil) - typed[Record.`'i -> Int, 's -> String, 'b -> Boolean`.T](Symbol("i") ->> 23 :: Symbol("s") ->> "foo" :: Symbol("b") ->> true :: HNil) + typed[Record.`"i" -> Int, "s" -> String, "b" -> Boolean`.T]("i" ->> 23 :: "s" ->> "foo" :: "b" ->> true :: HNil) // Literal types - typed[Record.`'i -> 2`.T](Symbol("i") ->> 2.narrow :: HNil) + typed[Record.`"i" -> 2`.T]("i" ->> 2.narrow :: HNil) - typed[Record.`'i -> 2, 's -> "a", 'b -> true`.T](Symbol("i") ->> 2.narrow :: Symbol("s") ->> "a".narrow :: Symbol("b") ->> true.narrow :: HNil) + typed[Record.`"i" -> 2, "s" -> "a", "b" -> true`.T]("i" ->> 2.narrow :: "s" ->> "a".narrow :: "b" ->> true.narrow :: HNil) - illTyped(""" typed[Record.`'i -> 2`.T](Symbol("i") ->> 3.narrow :: HNil) """) + illTyped("""typed[Record.`"i" -> 2`.T]("i" ->> 3.narrow :: HNil)""") // Mix of standard and literal types - typed[Record.`'i -> 2, 's -> String, 'b -> true`.T](Symbol("i") ->> 2.narrow :: Symbol("s") ->> "a" :: Symbol("b") ->> true.narrow :: HNil) + typed[Record.`"i" -> 2, "s" -> String, "b" -> true`.T]("i" ->> 2.narrow :: "s" ->> "a" :: "b" ->> true.narrow :: HNil) } @Test @@ -1104,14 +1103,14 @@ class RecordTests { def testSwapRecord: Unit = { import shapeless.ops.record.SwapRecord - val rt = Record.`'x -> Int, 'y -> String, 'z -> Boolean` + val rt = Record.`"x" -> Int, "y" -> String, "z" -> Boolean` type TestRecord = rt.T - val (x, y, z) = (Witness(Symbol("x")), Witness(Symbol("y")), Witness(Symbol("z"))) + val (x, y, z) = (Witness("x"), Witness("y"), Witness("z")) val fields: (FieldType[Int, x.T] :: FieldType[String, y.T] :: FieldType[Boolean, z.T] :: HNil) = SwapRecord[TestRecord].apply - assertEquals(fields.toList, List(Symbol("x"), Symbol("y"), Symbol("z"))) + assertEquals(fields.toList, List("x", "y", "z")) } @Test @@ -1137,12 +1136,12 @@ class RecordTests { import tag.@@ val tagged = tag[Int]("42") - val head1 = Symbol("k") ->> tagged - val head2 = field[Witness.`'k`.T](tagged) + val head1 = "k" ->> tagged + val head2 = field[Witness.`"k"`.T](tagged) val rec1 = head1 :: HNil val rec2 = head2 :: HNil - assertTypedEquals[String @@ Int](rec1(Symbol("k")), rec2(Symbol("k"))) + assertTypedEquals[String @@ Int](rec1("k"), rec2("k")) } @Test diff --git a/core/src/test/scala/shapeless/singletons.scala b/core/src/test/scala/shapeless/singletons.scala index 284ea8958..d462b0463 100644 --- a/core/src/test/scala/shapeless/singletons.scala +++ b/core/src/test/scala/shapeless/singletons.scala @@ -45,9 +45,9 @@ class SingletonTypesTests { val w3 = Witness(3) type _3 = w3.T - val wFoo = Witness(Symbol("foo")) + val wFoo = Witness("foo") type Foo = wFoo.T - val wBar = Witness(Symbol("bar")) + val wBar = Witness("bar") type Bar = wBar.T @Test @@ -84,17 +84,6 @@ class SingletonTypesTests { sameTyped(sFoo)(sBar) sameTyped(sFoo)("bar") """) - - val sFooSym = Symbol("foo").narrow - val sBarSym = Symbol("bar").narrow - - sameTyped(sFooSym)(sFooSym) - sameTyped(sFooSym)(Symbol("foo")) - - illTyped(""" - sameTyped(sFooSym)(sBarSym) - sameTyped(sFooSym)(Symbol("bar")) - """) } trait Show[T] { @@ -132,14 +121,12 @@ class SingletonTypesTests { val sThree = show(3.narrow) assertEquals("Three", sThree) - illTyped(""" - show(0.narrow) - """) + illTyped("show(0.narrow)") - val sFoo = show(Symbol("foo").narrow) + val sFoo = show("foo".narrow) assertEquals("'foo", sFoo) - val sBar = show(Symbol("bar").narrow) + val sBar = show("bar".narrow) assertEquals("'bar", sBar) } @@ -155,8 +142,8 @@ class SingletonTypesTests { implicit val showTwo = new LiteralShow[Witness.`2`.T] { def show = "Two" } implicit val showThree = new LiteralShow[Witness.`3`.T] { def show = "Three" } - implicit val showFoo = new LiteralShow[Witness.`'foo`.T] { def show = "'foo" } - implicit val showBar = new LiteralShow[Witness.`'bar`.T] { def show = "'bar" } + implicit val showFoo = new LiteralShow[Witness.`"foo"`.T] { def show = "'foo" } + implicit val showBar = new LiteralShow[Witness.`"bar"`.T] { def show = "'bar" } } def literalShow[T](t: T)(implicit s: LiteralShow[T]) = s.show @@ -178,14 +165,12 @@ class SingletonTypesTests { val sThree = literalShow(3.narrow) assertEquals("Three", sThree) - illTyped(""" - literalShow(0.narrow) - """) + illTyped("literalShow(0.narrow)") - val sFoo = literalShow(Symbol("foo").narrow) + val sFoo = literalShow("foo".narrow) assertEquals("'foo", sFoo) - val sBar = literalShow(Symbol("bar").narrow) + val sBar = literalShow("bar".narrow) assertEquals("'bar", sBar) } @@ -194,9 +179,9 @@ class SingletonTypesTests { } object LiteralsShow { - implicit val showTrueFalse = new LiteralsShow[HList.`true, false`.T] { def show = "true, false" } - implicit val showOneOrTwoOrThree = new LiteralsShow[Coproduct.`1, 2, 3`.T] { def show = "One | Two | Three" } - implicit val showFooBar = new LiteralsShow[HList.`'foo, 'bar`.T] { def show = "'foo, 'bar" } + implicit val showTrueFalse = new LiteralsShow[HList.`true, false`.T] { def show = "true, false" } + implicit val showOneOrTwoOrThree = new LiteralsShow[Coproduct.`1, 2, 3`.T] { def show = "One | Two | Three" } + implicit val showFooBar = new LiteralsShow[HList.`"foo", "bar"`.T] { def show = "'foo, 'bar" } } def literalsShow[T](t: T)(implicit s: LiteralsShow[T]) = s.show @@ -215,11 +200,9 @@ class SingletonTypesTests { val sThree = literalsShow(Inr(Inr(Inl(3.narrow)))) assertEquals("One | Two | Three", sThree) - illTyped(""" - literalsShow(true :: false :: HNil) - """) + illTyped("literalsShow(true :: false :: HNil)") - val sFooBar = literalsShow(Symbol("foo").narrow :: Symbol("bar").narrow :: HNil) + val sFooBar = literalsShow("foo".narrow :: "bar".narrow :: HNil) assertEquals("'foo, 'bar", sFooBar) } @@ -229,37 +212,19 @@ class SingletonTypesTests { val wFalse = Witness(false) sameTyped(wTrue)(wTrue) - - illTyped(""" - sameTyped(wTrue)(wFalse) - """) + illTyped("sameTyped(wTrue)(wFalse)") val w13 = Witness(13) val w23 = Witness(23) sameTyped(w13)(w13) - - illTyped(""" - sameTyped(w13)(w23) - """) + illTyped("sameTyped(w13)(w23)") val wFoo = Witness("foo") val wBar = Witness("bar") sameTyped(wFoo)(wFoo) - - illTyped(""" - sameTyped(wFoo)(wBar) - """) - - val wFooSym = Witness(Symbol("foo")) - val wBarSym = Witness(Symbol("bar")) - - sameTyped(wFooSym)(wFooSym) - - illTyped(""" - sameTyped(wFooSym)(wBarSym) - """) + illTyped("sameTyped(wFoo)(wBar)") } def convert(w: Witness): Witness.Aux[w.T] = w @@ -297,12 +262,8 @@ class SingletonTypesTests { sameTyped(cTrue)(Witness(true)) sameTyped(cFalse)(Witness(false)) - illTyped(""" - sameTyped(cTrue)(Witness(false)) - """) - illTyped(""" - sameTyped(cFalse)(Witness(true)) - """) + illTyped("sameTyped(cTrue)(Witness(false))") + illTyped("sameTyped(cFalse)(Witness(true))") val c13 = convert(13) val c23 = convert(23) @@ -310,12 +271,8 @@ class SingletonTypesTests { sameTyped(c13)(Witness(13)) sameTyped(c23)(Witness(23)) - illTyped(""" - sameTyped(c13)(Witness(23)) - """) - illTyped(""" - sameTyped(c23)(Witness(13)) - """) + illTyped("sameTyped(c13)(Witness(23))") + illTyped("sameTyped(c23)(Witness(13))") val cFoo = convert("foo") val cBar = convert("bar") @@ -323,25 +280,8 @@ class SingletonTypesTests { sameTyped(cFoo)(Witness("foo")) sameTyped(cBar)(Witness("bar")) - illTyped(""" - sameTyped(cFoo)(Witness("bar")) - """) - illTyped(""" - sameTyped(cBar)(Witness("foo")) - """) - - val cFooSym = convert(Symbol("foo")) - val cBarSym = convert(Symbol("bar")) - - sameTyped(cFooSym)(Witness(Symbol("foo"))) - sameTyped(cBarSym)(Witness(Symbol("bar"))) - - illTyped(""" - sameTyped(cFooSym)(Witness(Symbol("bar"))) - """) - illTyped(""" - sameTyped(cBarSym)(Witness(Symbol("foo"))) - """) + illTyped("""sameTyped(cFoo)(Witness("bar"))""") + illTyped("""sameTyped(cBar)(Witness("foo"))""") } def boundedConvert(w: Witness.Lt[Int]): Witness.Aux[w.T] = w @@ -350,21 +290,9 @@ class SingletonTypesTests { def testBoundedWitnessConversion: Unit = { val c13 = boundedConvert(13) sameTyped(c13)(Witness(13)) - illTyped(""" - sameTyped(c13)(Witness(23)) - """) - - illTyped(""" - boundedConvert(true) - """) - - illTyped(""" - boundedConvert("foo") - """) - - illTyped(""" - boundedConvert(Symbol("foo")) - """) + illTyped("sameTyped(c13)(Witness(23))") + illTyped("boundedConvert(true)") + illTyped("""boundedConvert("foo")""") } def showLiteral(t: Witness)(implicit s: Show[t.T]) = s.show @@ -386,15 +314,13 @@ class SingletonTypesTests { val sThree = showLiteral(3) assertEquals("Three", sThree) - val sFooSym = showLiteral(Symbol("foo")) + val sFooSym = showLiteral("foo") assertEquals("'foo", sFooSym) - val sBarSym = showLiteral(Symbol("bar")) + val sBarSym = showLiteral("bar") assertEquals("'bar", sBarSym) - illTyped(""" - showLiteral(0) - """) + illTyped("showLiteral(0)") } trait ShowWitness[T] { @@ -427,11 +353,11 @@ class SingletonTypesTests { val sThree = showWitness(3) assertEquals("3", sThree) - val sFooSym = showWitness(Symbol("foo")) - assertEquals("'foo", sFooSym) + val sFooSym = showWitness("foo") + assertEquals("foo", sFooSym) - val sBarSym = showWitness(Symbol("bar")) - assertEquals("'bar", sBarSym) + val sBarSym = showWitness("bar") + assertEquals("bar", sBarSym) } def showWitnessWith(w: WitnessWith[Show]) = w.instance.show @@ -453,10 +379,10 @@ class SingletonTypesTests { val sThree = showWitnessWith(3) assertEquals("Three", sThree) - val sFooSym = showWitnessWith(Symbol("foo")) + val sFooSym = showWitnessWith("foo") assertEquals("'foo", sFooSym) - val sBarSym = showWitnessWith(Symbol("bar")) + val sBarSym = showWitnessWith("bar") assertEquals("'bar", sBarSym) } @@ -479,17 +405,9 @@ class SingletonTypesTests { val relFalse = check(false)("foo") typed[String](relFalse) - illTyped(""" - check(true)("foo") - """) - - illTyped(""" - check(false)(23) - """) - - illTyped(""" - check(23)(23) - """) + illTyped("""check(true)("foo")""") + illTyped("check(false)(23)") + illTyped("check(23)(23)") } @Test @@ -498,39 +416,37 @@ class SingletonTypesTests { val y = new ValueTest(5) val wX = Witness(x) val wY = Witness(y) - illTyped(""" - implicitly[wX.T =:= wY.T] - """, "Cannot prove that wX.T =:= wY.T.") + illTyped("implicitly[wX.T =:= wY.T]", "Cannot prove that wX.T =:= wY.T.") } @Test def primitiveWiden: Unit = { { val w = Widen[Witness.`2`.T] - illTyped(" w(3) ", "type mismatch;.*") + illTyped("w(3)", "type mismatch;.*") val n = w(2) val n0: Int = n - illTyped(" val n1: Witness.`2`.T = n ", "type mismatch;.*") + illTyped("val n1: Witness.`2`.T = n", "type mismatch;.*") assertTypedEquals[Int](2, n) } { val w = Widen[Witness.`true`.T] - illTyped(" w(false) ", "type mismatch;.*") + illTyped("w(false)", "type mismatch;.*") val b = w(true) val b0: Boolean = b - illTyped(" val b1: Witness.`true`.T = b ", "type mismatch;.*") + illTyped("val b1: Witness.`true`.T = b", "type mismatch;.*") assertTypedEquals[Boolean](true, b) } { val w = Widen[Witness.`"ab"`.T] - illTyped(""" w("s") """, "type mismatch;.*") + illTyped("""w("s")""", "type mismatch;.*") val s = w("ab") val s0: String = s - illTyped(""" val s1: Witness.`"ab"`.T = s """, "type mismatch;.*") + illTyped("""val s1: Witness.`"ab"`.T = s""", "type mismatch;.*") assertTypedEquals[String]("ab", s) } @@ -542,23 +458,23 @@ class SingletonTypesTests { // Having it in scope makes the illTyped tests fail in an unexpected way. def narrowSymbol = ??? - val w = Widen[Witness.`'ab`.T] - illTyped(""" w(Symbol("s").narrow) """, "type mismatch;.*") - val s = w(Symbol("ab").narrow) - val s0: Symbol = s - illTyped(" val s1: Witness.`'ab`.T = s ", "type mismatch;.*") + val w = Widen[Witness.`"ab"`.T] + illTyped("""w("s".narrow)""", "type mismatch;.*") + val s = w("ab".narrow) + val s0: String = s + illTyped("""val s1: Witness.`"ab"`.T = s""", "type mismatch;.*") - assertTypedEquals[Symbol](Symbol("ab"), s) + assertTypedEquals[String]("ab", s) } @Test def aliasWiden: Unit = { type T = Witness.`2`.T val w = Widen[T] - illTyped(" w(3) ", "type mismatch;.*") + illTyped("w(3)", "type mismatch;.*") val n = w(2) val n0: Int = n - illTyped(" val n1: Witness.`2`.T = n ", "type mismatch;.*") + illTyped("val n1: Witness.`2`.T = n", "type mismatch;.*") assertTypedEquals[Int](2, n) } @@ -568,7 +484,7 @@ class SingletonTypesTests { @Test def singletonWiden: Unit = { - illTyped(" Widen[A.type] ", "could not find implicit value for parameter widen:.*") + illTyped("Widen[A.type]", "could not find implicit value for parameter widen:.*") } @Test diff --git a/core/src/test/scala/shapeless/typeable.scala b/core/src/test/scala/shapeless/typeable.scala index 0f37e9a76..4605939aa 100644 --- a/core/src/test/scala/shapeless/typeable.scala +++ b/core/src/test/scala/shapeless/typeable.scala @@ -497,7 +497,7 @@ class TypeableTests { val wFoo = Witness("foo") type Foo = wFoo.T - val wSym = Witness(Symbol("Foo")) + val wSym = Witness("Foo") type Sym = wSym.T object ObjA @@ -527,11 +527,11 @@ class TypeableTests { typed[Option[Foo]](c6) assertEquals(None, c6) - val c7 = (Symbol("Foo"): Any).cast[Sym] + val c7 = ("Foo": Any).cast[Sym] typed[Option[Sym]](c7) - assertEquals(Some(Symbol("Foo")), c7) + assertEquals(Some("Foo"), c7) - val c8 = (Symbol("Bar"): Any).cast[Sym] + val c8 = ("Bar": Any).cast[Sym] typed[Option[Sym]](c8) assertEquals(None, c8) @@ -685,7 +685,7 @@ class TypeableTests { object *** final case class <+>[A](left: A, right: A) val |+| = "Tie-fighter" - val witness = Witness(Symbol("witness")) + val witness = Witness("witness") // `Typeable.genTraversableTypeable` is not a macro. // Appart from that there is a difference in the encoded name between JVM and JS. @@ -694,7 +694,7 @@ class TypeableTests { assertEquals("***.type", Typeable[***.type].describe) assertEquals("<+>[String,String]", Typeable[<+>[String]].describe) assertEquals("|+|.type", Typeable[|+|.type].describe) - assertEquals("Symbol('witness)", Typeable[witness.T].describe) + assertEquals("String(witness)", Typeable[witness.T].describe) } @Test diff --git a/core/src/test/scala/shapeless/unions.scala b/core/src/test/scala/shapeless/unions.scala index 37b05ba77..f51a873cb 100644 --- a/core/src/test/scala/shapeless/unions.scala +++ b/core/src/test/scala/shapeless/unions.scala @@ -30,13 +30,13 @@ import ops.union.UnzipFields class UnionTests { - val wI = Witness(Symbol("i")) + val wI = Witness("i") type i = wI.T - val wS = Witness(Symbol("s")) + val wS = Witness("s") type s = wS.T - val sB = Witness(Symbol("b")) + val sB = Witness("b") type b = sB.T type U = Union.`"i" -> Int, "s" -> String, "b" -> Boolean`.T @@ -94,13 +94,13 @@ class UnionTests { @Test def testUnionTypeSelector: Unit = { type ii = FieldType[i, Int] :+: CNil - typed[ii](Coproduct[Union.`'i -> Int`.T](Symbol("i") ->> 23)) + typed[ii](Coproduct[Union.`"i" -> Int`.T]("i" ->> 23)) type iiss = FieldType[i, Int] :+: FieldType[s, String] :+: CNil - typed[iiss](Coproduct[Union.`'i -> Int, 's -> String`.T](Symbol("s") ->> "foo")) + typed[iiss](Coproduct[Union.`"i" -> Int, "s" -> String`.T]("s" ->> "foo")) type iissbb = FieldType[i, Int] :+: FieldType[s, String] :+: FieldType[b, Boolean] :+: CNil - typed[iissbb](Coproduct[Union.`'i -> Int, 's -> String, 'b -> Boolean`.T](Symbol("b") ->> true)) + typed[iissbb](Coproduct[Union.`"i" -> Int, "s" -> String, "b" -> Boolean`.T]("b" ->> true)) // Curiously, lines like // typed[Union.`'i -> Int, 's -> String`.T](Inl('i ->> 23)) @@ -115,29 +115,29 @@ class UnionTests { } { - type U = Union.`'i -> Int`.T + type U = Union.`"i" -> Int`.T - val u = Inl(Symbol("i") ->> 23) + val u = Inl("i" ->> 23) typed[U](u) } { - type U = Union.`'i -> Int, 's -> String`.T + type U = Union.`"i" -> Int, "s" -> String`.T - val u0 = Inl(Symbol("i") ->> 23) - val u1 = Inr(Inl(Symbol("s") ->> "foo")) + val u0 = Inl("i" ->> 23) + val u1 = Inr(Inl("s" ->> "foo")) typed[U](u0) typed[U](u1) } { - type U = Union.`'i -> Int, 's -> String, 'b -> Boolean`.T + type U = Union.`"i" -> Int, "s" -> String, "b" -> Boolean`.T - val u0 = Inl(Symbol("i") ->> 23) - val u1 = Inr(Inl(Symbol("s") ->> "foo")) - val u2 = Inr(Inr(Inl(Symbol("b") ->> true))) + val u0 = Inl("i" ->> 23) + val u1 = Inr(Inl("s" ->> "foo")) + val u2 = Inr(Inr(Inl("b" ->> true))) typed[U](u0) typed[U](u1) @@ -147,19 +147,19 @@ class UnionTests { // Literal types { - type U = Union.`'i -> 2`.T + type U = Union.`"i" -> 2`.T - val u = Inl(Symbol("i") ->> 2.narrow) + val u = Inl("i" ->> 2.narrow) typed[U](u) } { - type U = Union.`'i -> 2, 's -> "a", 'b -> true`.T + type U = Union.`"i" -> 2, "s" -> "a", "b" -> true`.T - val u0 = Inl(Symbol("i") ->> 2.narrow) - val u1 = Inr(Inl(Symbol("s") ->> "a".narrow)) - val u2 = Inr(Inr(Inl(Symbol("b") ->> true.narrow))) + val u0 = Inl("i" ->> 2.narrow) + val u1 = Inr(Inl("s" ->> "a".narrow)) + val u2 = Inr(Inr(Inl("b" ->> true.narrow))) typed[U](u0) typed[U](u1) @@ -167,21 +167,21 @@ class UnionTests { } { - type U = Union.`'i -> 2`.T + type U = Union.`"i" -> 2`.T - val u = Inl(Symbol("i") ->> 3.narrow) + val u = Inl("i" ->> 3.narrow) - illTyped(""" typed[U](u) """) + illTyped("typed[U](u)") } // Mix of standard and literal types { - type U = Union.`'i -> 2, 's -> String, 'b -> true`.T + type U = Union.`"i" -> 2, "s" -> String, "b" -> true`.T - val u0 = Inl(Symbol("i") ->> 2.narrow) - val u1 = Inr(Inl(Symbol("s") ->> "a")) - val u2 = Inr(Inr(Inl(Symbol("b") ->> true.narrow))) + val u0 = Inl("i" ->> 2.narrow) + val u1 = Inr(Inl("s" ->> "a")) + val u2 = Inr(Inr(Inl("b" ->> true.narrow))) typed[U](u0) typed[U](u1) From 846187b5b19e41f2267363c7861d8e9f9e0987bf Mon Sep 17 00:00:00 2001 From: Georgi Krastev Date: Sat, 11 Apr 2020 19:55:43 +0200 Subject: [PATCH 12/17] Remove deprecated methods which are kept for bincompat --- core/src/main/scala/shapeless/default.scala | 4 - core/src/main/scala/shapeless/hlists.scala | 4 - .../main/scala/shapeless/ops/coproduct.scala | 79 ------------------- .../src/main/scala/shapeless/ops/hlists.scala | 11 --- core/src/main/scala/shapeless/ops/nat.scala | 12 +-- core/src/main/scala/shapeless/poly.scala | 4 - core/src/main/scala/shapeless/sybclass.scala | 19 ----- .../main/scala/shapeless/syntax/hlists.scala | 14 ---- core/src/test/scala/shapeless/nat.scala | 2 +- 9 files changed, 4 insertions(+), 145 deletions(-) diff --git a/core/src/main/scala/shapeless/default.scala b/core/src/main/scala/shapeless/default.scala index fbffbc1f6..6c7ebd872 100644 --- a/core/src/main/scala/shapeless/default.scala +++ b/core/src/main/scala/shapeless/default.scala @@ -39,10 +39,6 @@ trait Default[T] extends DepFn0 with Serializable { object Default { def apply[T](implicit default: Default[T]): Aux[T, default.Out] = default - // only kept to preserve binary compatibility - def mkDefault[T, Out0 <: HList](defaults: Out0): Aux[T, Out0] = - mkDefaultByName(defaults) - def mkDefaultByName[T, Out0 <: HList](defaults: => Out0): Aux[T, Out0] = new Default[T] { type Out = Out0 diff --git a/core/src/main/scala/shapeless/hlists.scala b/core/src/main/scala/shapeless/hlists.scala index 0611e7e2e..4a5f02342 100644 --- a/core/src/main/scala/shapeless/hlists.scala +++ b/core/src/main/scala/shapeless/hlists.scala @@ -159,10 +159,6 @@ object HList extends Dynamic { loop(l, i, HNil) } - @deprecated("use unsafeUpdateAppend instead", "2.3.1") - def unsafeUpdate(l: HList, i: Int, e: Any): HList = - unsafeUpdateAppend(l, i, e) - def unsafeUpdateWith(l: HList, i: Int, f: Any => Any): HList = { @tailrec def loop(l: HList, i: Int, revPrefix: HList): HList = diff --git a/core/src/main/scala/shapeless/ops/coproduct.scala b/core/src/main/scala/shapeless/ops/coproduct.scala index 838a97b9b..270879c75 100644 --- a/core/src/main/scala/shapeless/ops/coproduct.scala +++ b/core/src/main/scala/shapeless/ops/coproduct.scala @@ -791,44 +791,6 @@ object coproduct { type Out = CNil def apply(c: CNil) = c } - - /** Binary compatibility stub */ - def implToRotateLeft[C <: Coproduct, N <: Nat, Size <: Nat, NModSize <: Succ[_]](implicit - length: Length.Aux[C, Size], - mod: nat.Mod.Aux[N, Size, NModSize], - impl: Impl[C, NModSize] - ): Aux[C, N, impl.Out] = - new RotateLeft[C, N] { - type Out = impl.Out - def apply(c: C): Out = impl(c) - } - - /** Binary compatibility stub */ - trait Impl[C <: Coproduct, N <: Nat] extends DepFn1[C] with Serializable { type Out <: Coproduct } - - /** Binary compatibility stub */ - object Impl { - type Aux[C <: Coproduct, N <: Nat, Out0 <: Coproduct] = Impl[C, N] { type Out = Out0 } - - def rotateCoproductOne[H, T <: Coproduct, TH <: Coproduct] - (implicit extendRight: ExtendRight.Aux[T, H, TH], inject: Inject[TH, H]): Aux[H :+: T, Nat._1, TH] = - new Impl[H :+: T, Nat._1] { - type Out = TH - - def apply(c: H :+: T): Out = c match { - case Inl(a) => inject(a) - case Inr(tail) => extendRight(tail) - } - } - - def rotateCoproductN[C <: Coproduct, N <: Nat, CN <: Coproduct, CSN <: Coproduct] - (implicit rotateN: Aux[C, N, CN], rotate1: Aux[CN, Nat._1, CSN]): Aux[C, Succ[N], CSN] = - new Impl[C, Succ[N]] { - type Out = CSN - - def apply(c: C): Out = rotate1(rotateN(c)) - } - } } trait LowPriorityRotateLeft { @@ -848,12 +810,6 @@ object coproduct { prepend(e.swap) } } - - /** Binary compatibility stub */ - def noopRotateLeftImpl[C <: Coproduct, N <: Nat]: RotateLeft.Aux[C, N, C] = new RotateLeft[C, N] { - type Out = C - def apply(c: C): Out = c - } } /** @@ -872,19 +828,6 @@ object coproduct { type Out = CNil def apply(c: CNil) = c } - - /** Binary compatibility stub */ - def hlistRotateRight[ - C <: Coproduct, N <: Nat, Size <: Nat, NModSize <: Succ[_], Size_Diff_NModSize <: Nat - ](implicit - length: Length.Aux[C, Size], - mod: nat.Mod.Aux[N, Size, NModSize], - diff: nat.Diff.Aux[Size, NModSize, Size_Diff_NModSize], - rotateLeft: RotateLeft.Impl[C, Size_Diff_NModSize] - ): Aux[C, N, rotateLeft.Out] = new RotateRight[C, N] { - type Out = rotateLeft.Out - def apply(c: C): Out = rotateLeft(c) - } } trait LowPriorityRotateRight { @@ -902,12 +845,6 @@ object coproduct { def apply(c: C): Out = rotateLeft(c) } - - /** Binary compatibility stub */ - def noopRotateRight[C <: Coproduct, N <: Nat]: Aux[C, N, C] = new RotateRight[C, N] { - type Out = C - def apply(c: C): Out = c - } } /** @@ -1100,22 +1037,6 @@ object coproduct { }) } } - - /** Binary compatibility stub */ - val reverseCNil: Aux[CNil, CNil] = reverse[CNil, CNil] - - /** Binary compatibility stub */ - def reverseCoproduct[H, T <: Coproduct, ReverseT <: Coproduct, RotateL_HReverseT <: Coproduct](implicit - reverse: Aux[T, ReverseT], - rotateLeft: RotateLeft.Aux[H :+: ReverseT, Nat._1, RotateL_HReverseT], - inject: Inject[RotateL_HReverseT, H] - ): Aux[H :+: T, RotateL_HReverseT] = new Reverse[H :+: T] { - type Out = RotateL_HReverseT - def apply(c: H :+: T): Out = c match { - case Inl(h) => inject(h) - case Inr(t) => rotateLeft(Inr[H, ReverseT](reverse(t))) - } - } } /** diff --git a/core/src/main/scala/shapeless/ops/hlists.scala b/core/src/main/scala/shapeless/ops/hlists.scala index 8e033e789..d2a795198 100644 --- a/core/src/main/scala/shapeless/ops/hlists.scala +++ b/core/src/main/scala/shapeless/ops/hlists.scala @@ -2057,11 +2057,6 @@ object hlist { } trait LowPriorityPrepend extends LowestPriorityPrepend { - /** - * Binary compatibility stub - * This one is for https://github.com/milessabin/shapeless/issues/406 - */ - override type Aux[P <: HList, S <: HList, Out0 <: HList] = Prepend[P, S] { type Out = Out0 } implicit def hnilPrepend0[P <: HList, S >: HNil.type <: HNil]: Aux[P, S, P] = new Prepend[P, S] { @@ -2657,12 +2652,6 @@ object hlist { prepend(after, before) } } - - /** Binary compatibility stub */ - def noopRotateLeft[L <: HList, N <: Nat]: Aux[L, N, L] = new RotateLeft[L, N] { - type Out = L - def apply(l: L): Out = l - } } /** diff --git a/core/src/main/scala/shapeless/ops/nat.scala b/core/src/main/scala/shapeless/ops/nat.scala index bd603f1f1..9a164950f 100644 --- a/core/src/main/scala/shapeless/ops/nat.scala +++ b/core/src/main/scala/shapeless/ops/nat.scala @@ -591,24 +591,18 @@ object nat { * * @author Miles Sabin */ - trait ToInt[N <: Nat] extends Serializable { - def apply() : Int + sealed abstract class ToInt[N <: Nat] extends Serializable { + def apply(): Int } object ToInt { def apply[N <: Nat](implicit toInt: ToInt[N]): ToInt[N] = toInt - class Inst[N <: Nat] (i: Int) extends ToInt[N]{ + final class Inst[N <: Nat](i: Int) extends ToInt[N] { def apply(): Int = i } implicit val toInt0: ToInt[_0] = new Inst[_0](0) - - //this method is used for backwards compatibility - def toIntSucc[N <: Nat](toIntN : ToInt[N]) = new ToInt[Succ[N]] { - def apply() = toIntN() + 1 - } - implicit def toIntSuccM[N <: Nat]: ToInt[N] = macro ToIntMacros.applyImpl[N] } diff --git a/core/src/main/scala/shapeless/poly.scala b/core/src/main/scala/shapeless/poly.scala index 5ed2491b8..0b7efc24e 100644 --- a/core/src/main/scala/shapeless/poly.scala +++ b/core/src/main/scala/shapeless/poly.scala @@ -218,10 +218,6 @@ object PolyDefns extends Cases { implicit def inst2[G[_], T](f : Id ~> G) : T => G[T] = f(_) implicit def inst3[F[_], T](f : F ~> Id) : F[T] => T = f(_) implicit def inst4[T](f : Id ~> Id) : T => T = f[T](_) // Explicit type argument needed here to prevent recursion? - // Retained as non-implicit for binary compatibility - def inst5[F[_], G, T](f : F ~> Const[G]#λ) : F[T] => G = f(_) - def inst6[G, T](f : Id ~> Const[G]#λ) : T => G = f(_) - def inst7[F, G](f : Const[F]#λ ~> Const[G]#λ) : F => G = f(_) } /** Natural transformation with a constant type constructor on the right hand side. */ diff --git a/core/src/main/scala/shapeless/sybclass.scala b/core/src/main/scala/shapeless/sybclass.scala index 0490051e1..6dd601094 100644 --- a/core/src/main/scala/shapeless/sybclass.scala +++ b/core/src/main/scala/shapeless/sybclass.scala @@ -55,15 +55,6 @@ object Data extends Data1 { def gmapQ[F, T, R](f: F)(t: T)(implicit data: Lazy[Data[F, T, R]]) = data.value.gmapQ(t) - /** - * Data type class instance for `List`s. - */ - @deprecated("Superseded by genTraversableData", "2.3.1") - def listData[P, T, R](implicit qt: Lazy[Case1.Aux[P, T, R]]): Data[P, List[T], R] = - new Data[P, List[T], R] { - def gmapQ(t: List[T]) = t.map(qt.value(_)) - } - implicit def genTraversableData[P, C[X] <: Iterable[X], T, R] (implicit qt: Lazy[Case1.Aux[P, T, R]]): Data[P, C[T], R] = new Data[P, C[T], R] { @@ -143,16 +134,6 @@ object DataT extends DataT1 { def gmapT[F, T](f: F)(t: T)(implicit data: Lazy[DataT[F, T]]) = data.value.gmapT(t) - /** - * DataT type class instance for `List`s. - */ - @deprecated("Superseded by genTraversableDataT", "2.3.1") - def listDataT[F <: Poly, T, U](implicit ft: Lazy[Case1.Aux[F, T, U]]): Aux[F, List[T], List[U]] = - new DataT[F, List[T]] { - type Out = List[U] - def gmapT(t: List[T]) = t.map(ft.value) - } - implicit def genTraversableDataT[F <: Poly, CC[X] <: Iterable[X], T, U] (implicit ft: Lazy[Case1.Aux[F, T, U]], cbf: Factory[U, CC[U]]): Aux[F, CC[T], CC[U]] = new DataT[F, CC[T]] { diff --git a/core/src/main/scala/shapeless/syntax/hlists.scala b/core/src/main/scala/shapeless/syntax/hlists.scala index 1c025aad2..d3056ef04 100644 --- a/core/src/main/scala/shapeless/syntax/hlists.scala +++ b/core/src/main/scala/shapeless/syntax/hlists.scala @@ -478,26 +478,12 @@ final class HListOps[L <: HList](l : L) extends Serializable { */ def zip(implicit zipper : Zip[L]) : zipper.Out = zipper(l) - /** - * Zips this `HList` of `HList`s returning an `HList` of tuples. Available only if there is evidence that this - * `HList` has `HList` elements. - */ - @deprecated("Use zip instead", "2.0.0") - def zipped(implicit zipper : Zip[L]) : zipper.Out = zipper(l) - /** * Unzips this `HList` of tuples returning a tuple of `HList`s. Available only if there is evidence that this * `HList` has tuple elements. */ def unzip(implicit unzipper : Unzip[L]) : unzipper.Out = unzipper(l) - /** - * Unzips this `HList` of tuples returning a tuple of `HList`s. Available only if there is evidence that this - * `HList` has tuple elements. - */ - @deprecated("Use unzip instead", "2.0.0") - def unzipped(implicit unzipper : Unzip[L]) : unzipper.Out = unzipper(l) - /** * Zips this `HList` with its argument `HList` of `HList`s, returning an `HList` of `HList`s with each element of * this `HList` prepended to the corresponding `HList` element of the argument `HList`. diff --git a/core/src/test/scala/shapeless/nat.scala b/core/src/test/scala/shapeless/nat.scala index 9ed732adf..ea6718c14 100644 --- a/core/src/test/scala/shapeless/nat.scala +++ b/core/src/test/scala/shapeless/nat.scala @@ -188,7 +188,7 @@ class NatTests { implicitly[LCM.Aux[_2, _3, _6]] implicitly[LCM.Aux[_4, _6, _12]] - assertEquals(1, ToInt.toIntSucc(new ToInt.Inst[_0](0))()) + assertEquals(1, toInt[Succ[_0]]) // Type level assertEquals(0, toInt[_0]) From a3986968a9dd9179c06b9464374149709168c848 Mon Sep 17 00:00:00 2001 From: Georgi Krastev Date: Sun, 12 Apr 2020 01:34:39 +0200 Subject: [PATCH 13/17] Remove macrocompat.bundle --- core/src/main/scala/shapeless/annotation.scala | 1 - core/src/main/scala/shapeless/cached.scala | 1 - core/src/main/scala/shapeless/default.scala | 1 - core/src/main/scala/shapeless/generic.scala | 3 --- core/src/main/scala/shapeless/generic1.scala | 5 ----- core/src/main/scala/shapeless/hlists.scala | 1 - core/src/main/scala/shapeless/labelled.scala | 1 - core/src/main/scala/shapeless/lazy.scala | 2 -- core/src/main/scala/shapeless/lowpriority.scala | 2 -- core/src/main/scala/shapeless/nat.scala | 2 -- core/src/main/scala/shapeless/ops/nat.scala | 1 - core/src/main/scala/shapeless/ops/records.scala | 5 ----- core/src/main/scala/shapeless/orphans.scala | 1 - core/src/main/scala/shapeless/package.scala | 1 - core/src/main/scala/shapeless/poly.scala | 1 - core/src/main/scala/shapeless/records.scala | 1 - core/src/main/scala/shapeless/singletons.scala | 2 -- core/src/main/scala/shapeless/test/compiletime.scala | 1 - core/src/main/scala/shapeless/test/package.scala | 1 - core/src/main/scala/shapeless/test/typechecking.scala | 1 - core/src/main/scala/shapeless/test/typetrace.scala | 1 - core/src/main/scala/shapeless/typeable.scala | 1 - core/src/main/scala/shapeless/typeoperators.scala | 2 -- core/src/main/scala/shapeless/unions.scala | 1 - core/src/main/scala_2.13+/shapeless/versionspecifics.scala | 4 ---- core/src/main/scala_2.13-/shapeless/versionspecifics.scala | 4 ---- 26 files changed, 47 deletions(-) diff --git a/core/src/main/scala/shapeless/annotation.scala b/core/src/main/scala/shapeless/annotation.scala index 91ac77fb3..7dbdd4347 100644 --- a/core/src/main/scala/shapeless/annotation.scala +++ b/core/src/main/scala/shapeless/annotation.scala @@ -172,7 +172,6 @@ object TypeAnnotations { implicit def materialize[A, T, Out <: HList]: Aux[A, T, Out] = macro AnnotationMacros.materializeTypeAnnotations[A, T, Out] } -@macrocompat.bundle class AnnotationMacros(val c: whitebox.Context) extends CaseClassMacros { import c.universe._ diff --git a/core/src/main/scala/shapeless/cached.scala b/core/src/main/scala/shapeless/cached.scala index 35d601ad5..20d9e9f14 100644 --- a/core/src/main/scala/shapeless/cached.scala +++ b/core/src/main/scala/shapeless/cached.scala @@ -66,7 +66,6 @@ class CachedMacrosState { var cache = List.empty[(Any, Any)] } -@macrocompat.bundle class CachedMacros(override val c: whitebox.Context) extends LazyMacros(c) with OpenImplicitMacros { import c.universe._ private val state = MacroState.getOrElseUpdate[CachedMacrosState](c.universe, new CachedMacrosState) diff --git a/core/src/main/scala/shapeless/default.scala b/core/src/main/scala/shapeless/default.scala index 6c7ebd872..0d06b3c4b 100644 --- a/core/src/main/scala/shapeless/default.scala +++ b/core/src/main/scala/shapeless/default.scala @@ -205,7 +205,6 @@ object Default { } } -@macrocompat.bundle class DefaultMacros(val c: whitebox.Context) extends CaseClassMacros { import c.universe._ diff --git a/core/src/main/scala/shapeless/generic.scala b/core/src/main/scala/shapeless/generic.scala index 84371bbde..24a60cd53 100644 --- a/core/src/main/scala/shapeless/generic.scala +++ b/core/src/main/scala/shapeless/generic.scala @@ -253,7 +253,6 @@ object HasCoproductGeneric { implicit def apply[T]: HasCoproductGeneric[T] = macro GenericMacros.mkHasCoproductGeneric[T] } -@macrocompat.bundle trait ReprTypes { val c: blackbox.Context import c.universe.{Symbol => _, _} @@ -273,7 +272,6 @@ trait ReprTypes { def objectRef[O: TypeTag]: Tree = Ident(typeOf[O].termSymbol) } -@macrocompat.bundle trait CaseClassMacros extends ReprTypes with CaseClassMacrosVersionSpecifics { val c: blackbox.Context @@ -906,7 +904,6 @@ trait CaseClassMacros extends ReprTypes with CaseClassMacrosVersionSpecifics { } } -@macrocompat.bundle class GenericMacros(val c: whitebox.Context) extends CaseClassMacros { import c.universe._ diff --git a/core/src/main/scala/shapeless/generic1.scala b/core/src/main/scala/shapeless/generic1.scala index 560735ce2..7445f7dc4 100644 --- a/core/src/main/scala/shapeless/generic1.scala +++ b/core/src/main/scala/shapeless/generic1.scala @@ -195,7 +195,6 @@ trait Split10 { implicit def apply[L[_], FO[_[_]], FI[_[_]]]: Split1[L, FO, FI] = macro Split1Macros.mkSplit1Impl[L, FO, FI] } -@macrocompat.bundle class Generic1Macros(val c: whitebox.Context) extends CaseClassMacros { import c.ImplicitCandidate import c.universe._ @@ -257,7 +256,6 @@ class Generic1Macros(val c: whitebox.Context) extends CaseClassMacros { } } -@macrocompat.bundle class IsHCons1Macros(val c: whitebox.Context) extends IsCons1Macros { import c.universe._ @@ -274,7 +272,6 @@ class IsHCons1Macros(val c: whitebox.Context) extends IsCons1Macros { } } -@macrocompat.bundle class IsCCons1Macros(val c: whitebox.Context) extends IsCons1Macros { import c.universe._ import definitions._ @@ -305,7 +302,6 @@ class IsCCons1Macros(val c: whitebox.Context) extends IsCons1Macros { } } -@macrocompat.bundle trait IsCons1Macros extends CaseClassMacros { val c: whitebox.Context import c.ImplicitCandidate @@ -347,7 +343,6 @@ trait IsCons1Macros extends CaseClassMacros { } } -@macrocompat.bundle class Split1Macros(val c: whitebox.Context) extends CaseClassMacros { import c.ImplicitCandidate import c.internal._ diff --git a/core/src/main/scala/shapeless/hlists.scala b/core/src/main/scala/shapeless/hlists.scala index 4a5f02342..3460e39c9 100644 --- a/core/src/main/scala/shapeless/hlists.scala +++ b/core/src/main/scala/shapeless/hlists.scala @@ -277,7 +277,6 @@ trait SingletonProductArgs extends Dynamic { def applyDynamic(method: String)(args: Any*): Any = macro ProductMacros.forwardSingletonImpl } -@macrocompat.bundle class ProductMacros(val c: whitebox.Context) extends SingletonTypeUtils with NatMacroDefns { import c.universe._ diff --git a/core/src/main/scala/shapeless/labelled.scala b/core/src/main/scala/shapeless/labelled.scala index 5ad72db1d..8909918ee 100644 --- a/core/src/main/scala/shapeless/labelled.scala +++ b/core/src/main/scala/shapeless/labelled.scala @@ -84,7 +84,6 @@ trait FieldOf[V] { def ->>(v: V): FieldType[this.type, V] = field[this.type](v) } -@macrocompat.bundle class LabelledMacros(override val c: whitebox.Context) extends GenericMacros(c) with SingletonTypeUtils { import c.universe._ import internal.constantType diff --git a/core/src/main/scala/shapeless/lazy.scala b/core/src/main/scala/shapeless/lazy.scala index 755cb87d4..b86528d36 100644 --- a/core/src/main/scala/shapeless/lazy.scala +++ b/core/src/main/scala/shapeless/lazy.scala @@ -168,7 +168,6 @@ object Strict { implicit def mkStrict[I]: Strict[I] = macro LazyMacros.mkStrictImpl[I] } -@macrocompat.bundle trait OpenImplicitMacros { val c: whitebox.Context @@ -193,7 +192,6 @@ trait OpenImplicitMacros { } } -@macrocompat.bundle class LazyMacros(val c: whitebox.Context) extends CaseClassMacros with OpenImplicitMacros with LowPriorityTypes { import c.universe._ import c.internal._ diff --git a/core/src/main/scala/shapeless/lowpriority.scala b/core/src/main/scala/shapeless/lowpriority.scala index f2c93fe60..89343d739 100644 --- a/core/src/main/scala/shapeless/lowpriority.scala +++ b/core/src/main/scala/shapeless/lowpriority.scala @@ -61,7 +61,6 @@ object LowPriority { } -@macrocompat.bundle class LowPriorityMacros(val c: whitebox.Context) extends OpenImplicitMacros with LowPriorityTypes { import c.universe._ @@ -105,7 +104,6 @@ class LowPriorityMacros(val c: whitebox.Context) extends OpenImplicitMacros with } -@macrocompat.bundle trait LowPriorityTypes { val c: whitebox.Context diff --git a/core/src/main/scala/shapeless/nat.scala b/core/src/main/scala/shapeless/nat.scala index b487e7854..2f4cebeea 100644 --- a/core/src/main/scala/shapeless/nat.scala +++ b/core/src/main/scala/shapeless/nat.scala @@ -70,7 +70,6 @@ object Nat extends Nats { implicit def natOps[N <: Nat](n : N) : NatOps[N] = new NatOps(n) } -@macrocompat.bundle class NatMacros(val c: whitebox.Context) extends NatMacroDefns { import c.universe._ @@ -82,7 +81,6 @@ class NatMacros(val c: whitebox.Context) extends NatMacroDefns { } } -@macrocompat.bundle trait NatMacroDefns { val c: whitebox.Context import c.universe._ diff --git a/core/src/main/scala/shapeless/ops/nat.scala b/core/src/main/scala/shapeless/ops/nat.scala index 9a164950f..8b624fd8c 100644 --- a/core/src/main/scala/shapeless/ops/nat.scala +++ b/core/src/main/scala/shapeless/ops/nat.scala @@ -606,7 +606,6 @@ object nat { implicit def toIntSuccM[N <: Nat]: ToInt[N] = macro ToIntMacros.applyImpl[N] } - @macrocompat.bundle class ToIntMacros(val c: whitebox.Context) extends CaseClassMacros { import c.universe._ diff --git a/core/src/main/scala/shapeless/ops/records.scala b/core/src/main/scala/shapeless/ops/records.scala index bc2f65af4..a903a0e6e 100644 --- a/core/src/main/scala/shapeless/ops/records.scala +++ b/core/src/main/scala/shapeless/ops/records.scala @@ -50,7 +50,6 @@ package record { def apply(record: HList): Any = HList.unsafeGet(record, i) } - @macrocompat.bundle class SelectorMacros(val c: whitebox.Context) extends CaseClassMacros { import c.universe._ @@ -122,7 +121,6 @@ package record { def apply(l: HList, e: Any): HList = HList.unsafeUpdateAppend(l, i, e) } - @macrocompat.bundle class UpdaterMacros(val c: whitebox.Context) extends CaseClassMacros { import c.universe._ @@ -366,7 +364,6 @@ package record { def apply(record: HList, f: Any => Any): HList = HList.unsafeUpdateWith(record, i, f) } - @macrocompat.bundle class ModifierMacros(val c: whitebox.Context) extends CaseClassMacros { import c.universe._ @@ -412,7 +409,6 @@ package record { def apply(record: HList): (Any, HList) = HList.unsafeRemove(record, i) } - @macrocompat.bundle class RemoverMacros(val c: whitebox.Context) extends CaseClassMacros { import c.universe._ @@ -558,7 +554,6 @@ package record { macro LacksKeyMacros.materialize[R, K] } - @macrocompat.bundle class LacksKeyMacros(val c: whitebox.Context) extends CaseClassMacros { import c.universe._ diff --git a/core/src/main/scala/shapeless/orphans.scala b/core/src/main/scala/shapeless/orphans.scala index 13409011b..196cbf0e3 100644 --- a/core/src/main/scala/shapeless/orphans.scala +++ b/core/src/main/scala/shapeless/orphans.scala @@ -36,7 +36,6 @@ trait OrphanDeriver[F[_], D] { implicit def materialize[T]: F[T] = macro OrphanMacros.materializeImpl[F, D, T] } -@macrocompat.bundle class OrphanMacros(val c: whitebox.Context) extends CaseClassMacros { import c.universe._ diff --git a/core/src/main/scala/shapeless/package.scala b/core/src/main/scala/shapeless/package.scala index e364f43f9..87401985e 100644 --- a/core/src/main/scala/shapeless/package.scala +++ b/core/src/main/scala/shapeless/package.scala @@ -112,7 +112,6 @@ package object shapeless extends ScalaVersionSpecifics { } package shapeless { - @macrocompat.bundle class CachedImplicitMacros(val c: whitebox.Context) { import c.universe._ diff --git a/core/src/main/scala/shapeless/poly.scala b/core/src/main/scala/shapeless/poly.scala index 0b7efc24e..5ece0159d 100644 --- a/core/src/main/scala/shapeless/poly.scala +++ b/core/src/main/scala/shapeless/poly.scala @@ -317,7 +317,6 @@ trait Poly0 extends Poly { } } -@macrocompat.bundle class PolyMacros(val c: whitebox.Context) { import c.universe._ diff --git a/core/src/main/scala/shapeless/records.scala b/core/src/main/scala/shapeless/records.scala index 828e13f7f..7cc9118e9 100644 --- a/core/src/main/scala/shapeless/records.scala +++ b/core/src/main/scala/shapeless/records.scala @@ -110,7 +110,6 @@ trait FromRecordArgs extends Dynamic { def applyDynamic[L <: HList](method: String)(rec: L): Any = macro RecordMacros.forwardFromRecordImpl[L] } -@macrocompat.bundle class RecordMacros(val c: whitebox.Context) extends CaseClassMacros { import c.universe._ import internal.constantType diff --git a/core/src/main/scala/shapeless/singletons.scala b/core/src/main/scala/shapeless/singletons.scala index 5896cb519..9ab94fb79 100644 --- a/core/src/main/scala/shapeless/singletons.scala +++ b/core/src/main/scala/shapeless/singletons.scala @@ -158,7 +158,6 @@ object Widen { implicit def materialize[T, Out]: Aux[T, Out] = macro SingletonTypeMacros.materializeWiden[T, Out] } -@macrocompat.bundle trait SingletonTypeUtils extends ReprTypes { import c.universe.{ Try => _, _ } import internal.decorators._ @@ -265,7 +264,6 @@ trait SingletonTypeUtils extends ReprTypes { } } -@macrocompat.bundle class SingletonTypeMacros(val c: whitebox.Context) extends SingletonTypeUtils with NatMacroDefns { import c.universe._ import definitions._ diff --git a/core/src/main/scala/shapeless/test/compiletime.scala b/core/src/main/scala/shapeless/test/compiletime.scala index 827ffce6d..7a6646102 100644 --- a/core/src/main/scala/shapeless/test/compiletime.scala +++ b/core/src/main/scala/shapeless/test/compiletime.scala @@ -38,7 +38,6 @@ object compileTime { def apply(code: String): FiniteDuration = macro CompileTimeMacros.applyImpl } -@macrocompat.bundle class CompileTimeMacros(val c: blackbox.Context) { import c.universe._ diff --git a/core/src/main/scala/shapeless/test/package.scala b/core/src/main/scala/shapeless/test/package.scala index 2b7c889ca..a678a9464 100644 --- a/core/src/main/scala/shapeless/test/package.scala +++ b/core/src/main/scala/shapeless/test/package.scala @@ -29,7 +29,6 @@ package object test { def showType[T](t: => T): String = macro TestMacros.showType[T] } -@macrocompat.bundle class TestMacros(val c: blackbox.Context) { import c.universe._ diff --git a/core/src/main/scala/shapeless/test/typechecking.scala b/core/src/main/scala/shapeless/test/typechecking.scala index 55b9e07b5..fbdc97ee5 100644 --- a/core/src/main/scala/shapeless/test/typechecking.scala +++ b/core/src/main/scala/shapeless/test/typechecking.scala @@ -33,7 +33,6 @@ object illTyped { def apply(code: String, expected: String): Unit = macro IllTypedMacros.applyImpl } -@macrocompat.bundle class IllTypedMacros(val c: blackbox.Context) { import c.universe._ diff --git a/core/src/main/scala/shapeless/test/typetrace.scala b/core/src/main/scala/shapeless/test/typetrace.scala index fe7798be2..7635458c7 100644 --- a/core/src/main/scala/shapeless/test/typetrace.scala +++ b/core/src/main/scala/shapeless/test/typetrace.scala @@ -27,7 +27,6 @@ object TypeTrace { implicit def apply[T]: TypeTrace[T] = macro TypeTraceMacros.applyImpl[T] } -@macrocompat.bundle class TypeTraceMacros(val c: blackbox.Context) { import c.universe._ diff --git a/core/src/main/scala/shapeless/typeable.scala b/core/src/main/scala/shapeless/typeable.scala index e347507b5..7783d47f1 100644 --- a/core/src/main/scala/shapeless/typeable.scala +++ b/core/src/main/scala/shapeless/typeable.scala @@ -381,7 +381,6 @@ object TypeCase { } } -@macrocompat.bundle class TypeableMacros(val c: blackbox.Context) extends SingletonTypeUtils { import c.universe._ import definitions.NothingClass diff --git a/core/src/main/scala/shapeless/typeoperators.scala b/core/src/main/scala/shapeless/typeoperators.scala index 576903e03..fc25a83b5 100644 --- a/core/src/main/scala/shapeless/typeoperators.scala +++ b/core/src/main/scala/shapeless/typeoperators.scala @@ -112,7 +112,6 @@ object the extends Dynamic { def selectDynamic(tpeSelector: String): Any = macro TheMacros.implicitlyImpl } -@macrocompat.bundle class TheMacros(val c: whitebox.Context) { import c.universe.{ Try => _, _ } import internal._, decorators._ @@ -155,7 +154,6 @@ object TypeOf extends Dynamic { def selectDynamic(code: String): Any = macro Macros.selectDynamic - @macrocompat.bundle private[TypeOf] final class Macros(val c: whitebox.Context) { import c.universe.{Try => _, _} import internal._, decorators._ diff --git a/core/src/main/scala/shapeless/unions.scala b/core/src/main/scala/shapeless/unions.scala index 3cf2c3be7..ba9ddc7d0 100644 --- a/core/src/main/scala/shapeless/unions.scala +++ b/core/src/main/scala/shapeless/unions.scala @@ -56,7 +56,6 @@ object union { } } -@macrocompat.bundle class UnionMacros(val c: whitebox.Context) { import c.universe._ import internal.constantType diff --git a/core/src/main/scala_2.13+/shapeless/versionspecifics.scala b/core/src/main/scala_2.13+/shapeless/versionspecifics.scala index f44396527..c0f3ab5e3 100644 --- a/core/src/main/scala_2.13+/shapeless/versionspecifics.scala +++ b/core/src/main/scala_2.13+/shapeless/versionspecifics.scala @@ -31,10 +31,6 @@ trait ScalaVersionSpecifics { s"Implicit value of type $tpe not found" } } - - private[shapeless] object macrocompat { - class bundle extends annotation.Annotation - } } trait CaseClassMacrosVersionSpecifics { self: CaseClassMacros => diff --git a/core/src/main/scala_2.13-/shapeless/versionspecifics.scala b/core/src/main/scala_2.13-/shapeless/versionspecifics.scala index 883151bcc..031bb844c 100644 --- a/core/src/main/scala_2.13-/shapeless/versionspecifics.scala +++ b/core/src/main/scala_2.13-/shapeless/versionspecifics.scala @@ -41,10 +41,6 @@ trait ScalaVersionSpecifics extends LP0 { } } - private[shapeless] object macrocompat { - class bundle extends annotation.Annotation - } - private[shapeless] implicit class GenTraversableLikeOps[T, Repr](gtl: GenTraversableLike[T, Repr]) { def iterator: Iterator[T] = gtl.toIterator } From 69ed5f5d4eea8456f67deb31b34a4c773e5ba0f4 Mon Sep 17 00:00:00 2001 From: Miles Sabin Date: Mon, 13 Apr 2020 10:44:24 +0100 Subject: [PATCH 14/17] Comment out a few stray Symbol literals in tests. --- core/src/test/scala/shapeless/generic.scala | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/core/src/test/scala/shapeless/generic.scala b/core/src/test/scala/shapeless/generic.scala index f89dda5d6..371606394 100644 --- a/core/src/test/scala/shapeless/generic.scala +++ b/core/src/test/scala/shapeless/generic.scala @@ -596,8 +596,8 @@ class GenericTests { illTyped(" IsTuple[Single] ") illTyped(" IsTuple[Person] ") illTyped(" IsTuple[Fruit] ") - illTyped(" IsTuple[Record.`'i -> Int, 's -> String`.T] ") - illTyped(" IsTuple[Union.`'i -> Int, 's -> String`.T] ") + illTyped(""" IsTuple[Record.`"i" -> Int, "s" -> String`.T] """) + illTyped(""" IsTuple[Union.`"i" -> Int, "s" -> String`.T] """) illTyped(" IsTuple[Int] ") illTyped(" IsTuple[String] ") illTyped(" IsTuple[Array[Int]] ") @@ -621,8 +621,8 @@ class GenericTests { illTyped(" HasProductGeneric[CNil] ") illTyped(" HasProductGeneric[Int :+: String :+: CNil] ") illTyped(" HasProductGeneric[Fruit] ") - illTyped(" HasProductGeneric[Record.`'i -> Int, 's -> String`.T] ") - illTyped(" HasProductGeneric[Union.`'i -> Int, 's -> String`.T] ") + illTyped(""" HasProductGeneric[Record.`"i" -> Int, "s" -> String`.T] """) + illTyped(""" HasProductGeneric[Union.`"i" -> Int, "s" -> String`.T] """) illTyped(" HasProductGeneric[Int] ") illTyped(" HasProductGeneric[String] ") illTyped(" HasProductGeneric[Array[Int]] ") @@ -644,8 +644,8 @@ class GenericTests { illTyped(" HasCoproductGeneric[A.type] ") illTyped(" HasCoproductGeneric[Single] ") illTyped(" HasCoproductGeneric[Person] ") - illTyped(" HasCoproductGeneric[Record.`'i -> Int, 's -> String`.T] ") - illTyped(" HasCoproductGeneric[Union.`'i -> Int, 's -> String`.T] ") + illTyped(""" HasCoproductGeneric[Record.`"i" -> Int, "s" -> String`.T] """) + illTyped(""" HasCoproductGeneric[Union.`"i" -> Int, "s" -> String`.T] """) illTyped(" HasCoproductGeneric[Int] ") illTyped(" HasCoproductGeneric[String] ") illTyped(" HasCoproductGeneric[Array[Int]] ") @@ -663,8 +663,8 @@ class GenericTests { illTyped(" Generic[Int :: String :: HNil] ") illTyped(" Generic[CNil] ") illTyped(" Generic[Int :+: String :+: CNil] ") - illTyped(" Generic[Record.`'i -> Int, 's -> String`.T] ") - illTyped(" Generic[Union.`'i -> Int, 's -> String`.T] ") + illTyped(""" Generic[Record.`"i" -> Int, "s" -> String`.T] """) + illTyped(""" Generic[Union.`"i" -> Int, "s" -> String`.T] """) } sealed trait Color From fccdab7df1c28a8d2a0f071f9ba60c2b1942bf56 Mon Sep 17 00:00:00 2001 From: Scala Steward Date: Wed, 15 Apr 2020 12:16:47 +0200 Subject: [PATCH 15/17] Update sbt to 1.3.10 --- project/build.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/project/build.properties b/project/build.properties index 06703e34d..797e7ccfd 100644 --- a/project/build.properties +++ b/project/build.properties @@ -1 +1 @@ -sbt.version=1.3.9 +sbt.version=1.3.10 From 3a5a0220540dc00c63cdbe427d08c3fb7ad16122 Mon Sep 17 00:00:00 2001 From: Scala Steward Date: Tue, 21 Apr 2020 21:13:13 +0200 Subject: [PATCH 16/17] Update sbt-ci-release to 1.5.3 --- project/plugins.sbt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/project/plugins.sbt b/project/plugins.sbt index bb3c056ae..5a6f8066d 100644 --- a/project/plugins.sbt +++ b/project/plugins.sbt @@ -6,7 +6,7 @@ val scalaJsVersion = Option(System.getenv("SCALA_JS_VERSION")).getOrElse("1.0.1" addSbtPlugin("com.typesafe" % "sbt-mima-plugin" % "0.7.0") addSbtPlugin("com.typesafe.sbt" % "sbt-osgi" % "0.9.5") addSbtPlugin("com.eed3si9n" % "sbt-buildinfo" % "0.9.0") -addSbtPlugin("com.geirsson" % "sbt-ci-release" % "1.5.2") +addSbtPlugin("com.geirsson" % "sbt-ci-release" % "1.5.3") addSbtPlugin("com.thoughtworks.sbt-api-mappings" % "sbt-api-mappings" % "3.0.0") addSbtPlugin("org.scoverage" % "sbt-scoverage" % "1.6.1") addSbtPlugin("org.scala-js" % "sbt-scalajs" % scalaJsVersion) From bfbbb4ec27b4bec96959c79fb78f5ada910ca754 Mon Sep 17 00:00:00 2001 From: Georgi Krastev Date: Fri, 24 Apr 2020 12:25:37 +0200 Subject: [PATCH 17/17] Update to Scala 2.13.2 and docs update --- .travis.yml | 2 +- README.md | 10 +++++----- build.sbt | 2 +- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/.travis.yml b/.travis.yml index 048ae00b4..b0e343250 100644 --- a/.travis.yml +++ b/.travis.yml @@ -8,7 +8,7 @@ jdk: scala: - 2.11.12 - 2.12.11 - - 2.13.1 + - 2.13.2 env: - {} diff --git a/README.md b/README.md index 178bc4e9c..53682c1d2 100644 --- a/README.md +++ b/README.md @@ -122,10 +122,10 @@ resolvers ++= Seq( Builds are available for Scala 2.11.x, 2.12.x and 2.13.x. The main line of development for -shapeless 2.3.3 is Scala 2.13.1. +shapeless 2.3.3 is Scala 2.13.2. ```scala -scalaVersion := "2.13.1" +scalaVersion := "2.13.2" libraryDependencies ++= Seq( "com.chuusai" %% "shapeless" % "2.3.3" @@ -134,7 +134,7 @@ libraryDependencies ++= Seq( For using snapshots of Shapeless you should add, ```scala -scalaVersion := "2.13.1" +scalaVersion := "2.13.2" libraryDependencies ++= Seq( "com.chuusai" %% "shapeless" % "2.4.0-SNAPSHOT" @@ -164,8 +164,8 @@ releases][olderusage] on the shapeless wiki. ## Building shapeless -shapeless is built with SBT 1.2.8 or later, and its master branch is built with Scala 2.13.1 by default but also -cross-builds for 2.11.12 and 2.12.8. +shapeless is built with SBT 1.3.10 or later, and its master branch is built with Scala 2.13.2 by default but also +cross-builds for 2.11.12 and 2.12.11. [namehashing]: https://github.com/sbt/sbt/issues/1640 diff --git a/build.sbt b/build.sbt index 031996cae..19814e20e 100644 --- a/build.sbt +++ b/build.sbt @@ -6,7 +6,7 @@ import sbtcrossproject.CrossProject val Scala211 = "2.11.12" val Scala212 = "2.12.11" -val Scala213 = "2.13.1" +val Scala213 = "2.13.2" val isScalaNative = System.getenv("SCALA_NATIVE") != null val hasScalaJsVersion = System.getenv("SCALA_JS_VERSION") != null