Skip to content

Commit 032a192

Browse files
committed
Implement GenIso.unit
1 parent 4f36ec0 commit 032a192

File tree

4 files changed

+41
-1
lines changed

4 files changed

+41
-1
lines changed

compiler/src/dotty/tools/dotc/tastyreflect/TypeOrBoundsOpsImpl.scala

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,8 @@ trait TypeOrBoundsOpsImpl extends scala.tasty.reflect.TypeOrBoundsOps with CoreI
2525

2626
def typeSymbol(implicit ctx: Context): Symbol = tpe.typeSymbol
2727

28+
def isSingleton(implicit ctx: Context): Boolean = tpe.isSingleton
29+
2830
def memberType(member: Symbol)(implicit ctx: Context): Type =
2931
member.info.asSeenFrom(tpe, member.owner)
3032
}

library/src/scala/tasty/reflect/TypeOrBoundsOps.scala

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@ trait TypeOrBoundsOps extends Core {
5555
def widen(implicit ctx: Context): Type
5656
def classSymbol(implicit ctx: Context): Option[ClassSymbol]
5757
def typeSymbol(implicit ctx: Context): Symbol
58+
def isSingleton(implicit ctx: Context): Boolean
5859
def memberType(member: Symbol)(implicit ctx: Context): Type
5960
}
6061

tests/run-with-compiler/i5941/macro_1.scala

Lines changed: 36 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,41 @@ object Iso {
128128
apply(from)(to)
129129
}
130130
}
131+
132+
def implUnit[S: Type](implicit refl: Reflection): Expr[Iso[S, Unit]] = {
133+
import refl._
134+
import util._
135+
import quoted.Toolbox.Default._
136+
137+
val tpS = typeOf[S]
138+
139+
if (tpS.isSingleton) {
140+
val ident = Term.Ident(tpS.asInstanceOf[TermRef]).seal[S]
141+
'{
142+
Iso[S, Unit](Function.const(~ident))(Function.const(()))
143+
}
144+
}
145+
else if (tpS.classSymbol.flatMap(cls => if (cls.flags.is(Flags.Case)) Some(true) else None).nonEmpty) {
146+
val cls = tpS.classSymbol.get
147+
148+
if (cls.caseFields.size != 0)
149+
throw new QuoteError("Use GenIso.fields for case classes more than one parameter")
150+
151+
val companion = tpS match {
152+
case Type.SymRef(sym, prefix) => Type.TermRef(prefix, sym.name)
153+
case Type.TypeRef(name, prefix) => Type.TermRef(prefix, name)
154+
}
155+
156+
val obj = Term.Select.overloaded(Term.Ident(companion), "apply", Nil, Nil).seal[S]
157+
158+
'{
159+
Iso[S, Unit](Function.const(~obj))(Function.const(()))
160+
}
161+
}
162+
else {
163+
throw new QuoteError("Only support generation for case classes or singleton types")
164+
}
165+
}
131166
}
132167

133168
object GenIso {
@@ -141,7 +176,7 @@ object GenIso {
141176
inline def apply[S, A]: Iso[S, A] = ~Iso.impl[S, A]
142177

143178
inline def fields[S, A]: Iso[S, A] = ???
144-
inline def unit[S]: Iso[S, Unit] = ???
179+
inline def unit[S]: Iso[S, Unit] = ~Iso.implUnit[S]
145180
}
146181

147182
trait Prism[S, A] {

tests/run-with-compiler/i5941/usage_2.scala

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,5 +30,7 @@ object Test {
3030
// assert(jStr(JStr("world")) == JStr("world"))
3131

3232
assert(GenIso[JStr, String].to(JStr("Hello")) == "Hello")
33+
assert(GenIso.unit[JNull.type].to(JNull) == (()))
34+
assert(GenIso.unit[JNull.type].from(()) == JNull)
3335
}
3436
}

0 commit comments

Comments
 (0)