Skip to content

Commit 503f439

Browse files
committed
Implement sealed trait handling using if-then-else
1 parent 64ffea6 commit 503f439

File tree

1 file changed

+21
-2
lines changed

1 file changed

+21
-2
lines changed

quicklens/src/main/scala-3/com/softwaremill/quicklens/QuicklensMacros.scala

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -101,14 +101,33 @@ object QuicklensMacros {
101101
case _ => Apply(Select(obj, copy), args)
102102
}
103103
else if (objSymbol.flags.is(Flags.Sealed) && objSymbol.flags.is(Flags.Trait)) || objSymbol.flags.is(Flags.Enum) then
104-
// if the source is a sealed trait / enum, generating a pattern match with a .copy for each child (implementing case class)
104+
// if the source is a sealed trait / enum, generating a if-then-else with a .copy for each child (implementing case class)
105105
val cases = obj.tpe.typeSymbol.children.map { child =>
106106
val subtype = TypeIdent(child)
107107
val bind = Symbol.newBind(owner, "c", Flags.EmptyFlags, subtype.tpe)
108108
CaseDef(Bind(bind, Typed(Ref(bind), subtype)), None, caseClassCopy(owner, mod, Ref(bind), field, tail))
109109
}
110-
Match(obj, cases)
111110

111+
/*
112+
if (obj.isInstanceOf[Child1]) caseClassCopy(obj.asInstanceOf[Child1]) else
113+
if (obj.isInstanceOf[Child2]) caseClassCopy(obj.asInstanceOf[Child2]) else
114+
...
115+
else throw new IllegalStateException()
116+
*/
117+
val ifThens = obj.tpe.typeSymbol.children.map { child =>
118+
val ifCond = TypeApply(Select.unique(obj, "isInstanceOf"), List(TypeIdent(child)))
119+
120+
val ifThen = ValDef.let(owner, TypeApply(Select.unique(obj, "asInstanceOf"), List(TypeIdent(child)))) { castToChildVal =>
121+
caseClassCopy(owner, mod, castToChildVal, field, tail)
122+
}
123+
124+
ifCond -> ifThen
125+
}
126+
127+
val elseThrow = '{throw new IllegalStateException()}.asTerm
128+
ifThens.foldRight(elseThrow) { case ((ifCond, ifThen), ifElse) =>
129+
If(ifCond, ifThen, ifElse)
130+
}
112131
else
113132
report.throwError(s"Unsupported source object: must be a case class or sealed trait, but got: $objSymbol")
114133

0 commit comments

Comments
 (0)