Skip to content

Commit b2a6be1

Browse files
committed
Complete the support for unapply
1 parent 5b651b7 commit b2a6be1

File tree

3 files changed

+37
-7
lines changed

3 files changed

+37
-7
lines changed

compiler/src/dotty/tools/dotc/transform/init/Objects.scala

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1203,16 +1203,16 @@ object Objects:
12031203
// TODO: handle unapplySeq
12041204
Bottom
12051205

1206-
case UnApply(fun, _, pats) =>
1206+
case UnApply(fun, implicits, pats) =>
12071207
val fun1 = funPart(fun)
12081208
val funRef = fun1.tpe.asInstanceOf[TermRef]
12091209
if fun.symbol.name == nme.unapplySeq then
12101210
// TODO: handle unapplySeq
12111211
()
12121212
else
12131213
val receiver = evalType(funRef.prefix, thisV, klass)
1214-
// TODO: apply implicits
1215-
val unapplyRes = call(receiver, funRef.symbol, TraceValue(scrutinee, summon[Trace]) :: Nil, funRef.prefix, superType = NoType, needResolve = true)
1214+
val implicitValues = evalArgs(implicits.map(Arg.apply), thisV, klass)
1215+
val unapplyRes = call(receiver, funRef.symbol, TraceValue(scrutinee, summon[Trace]) :: implicitValues, funRef.prefix, superType = NoType, needResolve = true)
12161216
// distribute unapply to patterns
12171217
val unapplyResTp = funRef.widen.finalResultType
12181218
if isProductMatch(unapplyResTp, pats.length) then
@@ -1227,14 +1227,16 @@ object Objects:
12271227
()
12281228
else
12291229
// Get match
1230-
val getMember = unapplyResTp.member(nme.get).suchThat(_.info.isParameterless)
1231-
// TODO: call isEmpty as well
1232-
val getRes = call(unapplyRes, getMember.symbol, Nil, unapplyResTp, superType = NoType, needResolve = true)
1230+
val isEmptyDenot = unapplyResTp.member(nme.isEmpty).suchThat(_.info.isParameterless)
1231+
call(unapplyRes, isEmptyDenot.symbol, Nil, unapplyResTp, superType = NoType, needResolve = true)
1232+
1233+
val getDenot = unapplyResTp.member(nme.get).suchThat(_.info.isParameterless)
1234+
val getRes = call(unapplyRes, getDenot.symbol, Nil, unapplyResTp, superType = NoType, needResolve = true)
12331235
if pats.length == 1 then
12341236
// single match
12351237
evalPattern(getRes, pats.head)
12361238
else
1237-
val getResTp = getMember.info.widen.finalResultType
1239+
val getResTp = getDenot.info.finalResultType
12381240
val selectors = productSelectors(getResTp).take(pats.length)
12391241
selectors.zip(pats).map { (sel, pat) =>
12401242
val selectRes = call(unapplyRes, sel, Nil, unapplyResTp, superType = NoType, needResolve = true)
@@ -1245,6 +1247,9 @@ object Objects:
12451247
end if
12461248
scrutinee
12471249

1250+
case Ident(nme.WILDCARD) =>
1251+
scrutinee
1252+
12481253
case Typed(pat, _) =>
12491254
evalPattern(scrutinee, pat)
12501255

compiler/src/dotty/tools/dotc/transform/init/Util.scala

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,9 @@ object Util:
2626
opaque type Arg = Tree | ByNameArg
2727
case class ByNameArg(tree: Tree)
2828

29+
object Arg:
30+
def apply(tree: Tree): Arg = tree
31+
2932
extension (arg: Arg)
3033
def isByName = arg.isInstanceOf[ByNameArg]
3134
def tree: Tree = arg match

tests/init/neg/patmat.scala

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,3 +12,25 @@ object B:
1212
if A.a.isEmpty then println(xs.size)
1313
case Nil =>
1414
println(0)
15+
16+
case class Box[T](value: T)
17+
case class Holder[T](value: T)
18+
object C:
19+
(Box(5): Box[Int] | Holder[Int]) match
20+
case Box(x) => x
21+
case Holder(x) => x
22+
23+
(Box(5): Box[Int] | Holder[Int]) match
24+
case box: Box[Int] => box.value
25+
case holder: Holder[Int] => holder.value
26+
27+
val a: Int = Inner.b
28+
29+
object Inner: // error
30+
val b: Int = 10
31+
32+
val foo: () => Int = () => C.a
33+
34+
(Box(foo): Box[() => Int] | Holder[Int]) match
35+
case Box(f) => f()
36+
case Holder(x) => x

0 commit comments

Comments
 (0)