Skip to content

Commit 4da33ae

Browse files
committed
Only generate isDefined and applyOrElse for partial function literals
This is done by extending `scala.runtime.AbstractPartialFunction`.
1 parent 045e602 commit 4da33ae

File tree

3 files changed

+15
-6
lines changed

3 files changed

+15
-6
lines changed

compiler/src/dotty/tools/dotc/ast/tpd.scala

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -282,11 +282,11 @@ object tpd extends Trees.Instance[Type] with TypedTreeInfo {
282282
val parents1 =
283283
if (parents.head.classSymbol.is(Trait)) parents.head.parents.head :: parents
284284
else parents
285-
val cls = ctx.newNormalizedClassSymbol(owner, tpnme.ANON_CLASS, Synthetic, parents1,
285+
val cls = ctx.newNormalizedClassSymbol(owner, tpnme.ANON_CLASS, Synthetic | Final, parents1,
286286
coord = fns.map(_.pos).reduceLeft(_ union _))
287287
val constr = ctx.newConstructor(cls, Synthetic, Nil, Nil).entered
288288
def forwarder(fn: TermSymbol, name: TermName) = {
289-
var flags = Synthetic | Method
289+
var flags = Synthetic | Method | Final
290290
def isOverriden(denot: SingleDenotation) = fn.info.overrides(denot.info, matchLoosely = true)
291291
val isOverride = parents.exists(_.member(name).hasAltWith(isOverriden))
292292
if (isOverride) flags = flags | Override

compiler/src/dotty/tools/dotc/transform/ExpandSAMs.scala

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,7 @@ class ExpandSAMs extends MiniPhase {
9090
val tru = Literal(Constant(true))
9191
applyRhs match {
9292
case tree @ Match(_, cases) =>
93-
def translateCase(cdef: CaseDef)=
93+
def translateCase(cdef: CaseDef) =
9494
cpy.CaseDef(cdef)(body = tru).changeOwner(applyFn, isDefinedAtFn)
9595
val paramRef = paramRefss.head.head
9696
val defaultValue = Literal(Constant(false))
@@ -109,15 +109,19 @@ class ExpandSAMs extends MiniPhase {
109109
val defaultValue = defaultRef.select(nme.apply).appliedTo(paramRef)
110110
translateMatch(tree, paramRef, cases.map(translateCase), defaultValue)
111111
case _ =>
112-
ref(applyFn).appliedTo(paramRef)
112+
applyRhs
113+
.changeOwner(applyFn, applyOrElseFn)
114+
.subst(param.symbol :: Nil, paramRef.symbol :: Nil)
113115
}
114116
}
115117

116118
val isDefinedAtDef = transformFollowingDeep(DefDef(isDefinedAtFn, isDefinedAtRhs(_)))
117119
val applyOrElseDef = transformFollowingDeep(DefDef(applyOrElseFn, applyOrElseRhs(_)))
118120

119-
val anonCls = AnonClass(tpt.tpe :: Nil, List(applyFn, isDefinedAtFn, applyOrElseFn), List(nme.apply, nme.isDefinedAt, nme.applyOrElse))
120-
cpy.Block(tree)(List(applyDef, isDefinedAtDef, applyOrElseDef), anonCls)
121+
val tpArgs = tpt.tpe.baseType(defn.PartialFunctionClass).argInfos
122+
val parent = defn.AbstractPartialFunctionType.appliedTo(tpArgs)
123+
val anonCls = AnonClass(parent :: Nil, List(isDefinedAtFn, applyOrElseFn), List(nme.isDefinedAt, nme.applyOrElse))
124+
cpy.Block(tree)(List(isDefinedAtDef, applyOrElseDef), anonCls)
121125
}
122126

123127
private def checkRefinements(tpe: Type, pos: Position)(implicit ctx: Context): Type = tpe.dealias match {

tests/pos/i4177.scala

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,5 +11,10 @@ class Test {
1111
val e: PartialFunction[String, String] = { case x @ "abc" => x }
1212
val f: PartialFunction[String, String] = x => x match { case "abc" => x }
1313
val g: PartialFunction[String, String] = x => x match { case "abc" if x.isEmpty => x }
14+
15+
type P = PartialFunction[String,String]
16+
val h: P = { case x => x.toString }
17+
18+
val i: PartialFunction[Int, Int] = { x => x match { case x => x } }
1419
}
1520
}

0 commit comments

Comments
 (0)