Skip to content

Commit e258b86

Browse files
committed
Fix problems related to implicit function types.
1. Propagate expected type when typing an implicit closure. This is necessary to recursively apply eta expansion in the case of nested implicit functions. 2. Generalize match pattern in shortcutImplicits. This is necessary to avoid a crash.
1 parent d541452 commit e258b86

File tree

3 files changed

+11
-11
lines changed

3 files changed

+11
-11
lines changed

compiler/src/dotty/tools/dotc/core/NameKinds.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -283,7 +283,7 @@ object NameKinds {
283283
val ProtectedAccessorName = new PrefixNameKind(PROTECTEDACCESSOR, "protected$")
284284
val ProtectedSetterName = new PrefixNameKind(PROTECTEDSETTER, "protected$set") // dubious encoding, kept for Scala2 compatibility
285285
val AvoidClashName = new SuffixNameKind(AVOIDCLASH, "$_avoid_name_clash_$")
286-
val DirectName = new SuffixNameKind(DIRECT, "$direct")
286+
val DirectMethodName = new SuffixNameKind(DIRECT, "$direct") { override def definesNewName = true }
287287
val FieldName = new SuffixNameKind(FIELD, "$$local")
288288
val ExtMethName = new SuffixNameKind(EXTMETH, "$extension")
289289
val ModuleVarName = new SuffixNameKind(OBJECTVAR, "$module")

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

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ import core.Decorators._
1111
import core.StdNames.nme
1212
import core.Names._
1313
import core.NameOps._
14-
import core.NameKinds.DirectName
14+
import core.NameKinds.DirectMethodName
1515
import ast.Trees._
1616
import ast.tpd
1717
import collection.mutable
@@ -77,6 +77,7 @@ class ShortcutImplicits extends MiniPhase with IdentityDenotTransformer { thisTr
7777
private def shouldBeSpecialized(sym: Symbol)(implicit ctx: Context) =
7878
sym.is(Method, butNot = Accessor) &&
7979
defn.isImplicitFunctionType(sym.info.finalResultType) &&
80+
!sym.isAnonymousFunction &&
8081
(specializeMonoTargets || !sym.isEffectivelyFinal || sym.allOverriddenSymbols.nonEmpty)
8182

8283
/** @pre The type's final result type is an implicit function type `implicit Ts => R`.
@@ -92,7 +93,7 @@ class ShortcutImplicits extends MiniPhase with IdentityDenotTransformer { thisTr
9293
/** A new `m$direct` method to accompany the given method `m` */
9394
private def newDirectMethod(sym: Symbol)(implicit ctx: Context): Symbol = {
9495
val direct = sym.copy(
95-
name = DirectName(sym.name.asTermName).asInstanceOf[sym.ThisName],
96+
name = DirectMethodName(sym.name.asTermName).asInstanceOf[sym.ThisName],
9697
flags = sym.flags | Synthetic,
9798
info = directInfo(sym.info))
9899
if (direct.allOverriddenSymbols.isEmpty) direct.resetFlag(Override)
@@ -104,14 +105,13 @@ class ShortcutImplicits extends MiniPhase with IdentityDenotTransformer { thisTr
104105
*/
105106
private def directMethod(sym: Symbol)(implicit ctx: Context): Symbol =
106107
if (sym.owner.isClass) {
107-
val direct = sym.owner.info.member(DirectName(sym.name.asTermName))
108+
val direct = sym.owner.info.member(DirectMethodName(sym.name.asTermName))
108109
.suchThat(_.info matches directInfo(sym.info)).symbol
109110
if (direct.maybeOwner == sym.owner) direct
110111
else newDirectMethod(sym).enteredAfter(thisTransform)
111112
}
112113
else directMeth.getOrElseUpdate(sym, newDirectMethod(sym))
113114

114-
115115
/** Transform `qual.apply` occurrences according to rewrite rule (2) above */
116116
override def transformSelect(tree: Select)(implicit ctx: Context, info: TransformerInfo) =
117117
if (tree.name == nme.apply &&
@@ -122,7 +122,7 @@ class ShortcutImplicits extends MiniPhase with IdentityDenotTransformer { thisTr
122122
case TypeApply(fn, args) => cpy.TypeApply(tree)(directQual(fn), args)
123123
case Block(stats, expr) => cpy.Block(tree)(stats, directQual(expr))
124124
case tree: RefTree =>
125-
cpy.Ref(tree)(DirectName(tree.name.asTermName))
125+
cpy.Ref(tree)(DirectMethodName(tree.name.asTermName))
126126
.withType(directMethod(tree.symbol).termRef)
127127
}
128128
directQual(tree.qualifier)
@@ -136,7 +136,7 @@ class ShortcutImplicits extends MiniPhase with IdentityDenotTransformer { thisTr
136136

137137
def splitClosure(tree: Tree): (List[Type] => List[List[Tree]] => Tree, Tree) = tree match {
138138
case Block(Nil, expr) => splitClosure(expr)
139-
case Block((meth @ DefDef(nme.ANON_FUN, Nil, clparams :: Nil, _, _)) :: Nil, cl: Closure) =>
139+
case Block((meth @ DefDef(nme.ANON_FUN, Nil, clparams :: Nil, _, _)) :: rest, cl: Closure) =>
140140
val tparamSyms = mdef.tparams.map(_.symbol)
141141
val vparamSymss = mdef.vparamss.map(_.map(_.symbol))
142142
val clparamSyms = clparams.map(_.symbol)
@@ -149,16 +149,16 @@ class ShortcutImplicits extends MiniPhase with IdentityDenotTransformer { thisTr
149149
val forwarder = ref(direct)
150150
.appliedToTypeTrees(tparamSyms.map(ref(_)))
151151
.appliedToArgss(vparamSymss.map(_.map(ref(_))) :+ clparamSyms.map(ref(_)))
152-
val fwdClosure = cpy.Block(tree)(cpy.DefDef(meth)(rhs = forwarder) :: Nil, cl)
152+
val fwdClosure = cpy.Block(tree)(cpy.DefDef(meth)(rhs = forwarder) :: rest, cl)
153153
(remappedCore, fwdClosure)
154154
case EmptyTree =>
155155
(_ => _ => EmptyTree, EmptyTree)
156156
}
157157

158158
val (remappedCore, fwdClosure) = splitClosure(mdef.rhs)
159159
val originalDef = cpy.DefDef(mdef)(rhs = fwdClosure)
160-
val directDef = polyDefDef(direct.asTerm, remappedCore)
161-
Thicket(originalDef, directDef)
160+
val directDef = transformDefDef(polyDefDef(direct.asTerm, remappedCore))
161+
flatTree(List(originalDef, directDef))
162162
}
163163
else mdef
164164
}

compiler/src/dotty/tools/dotc/typer/Typer.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1582,7 +1582,7 @@ class Typer extends Namer with TypeAssigner with Applications with Implicits wit
15821582
val paramTypes = formals.map(fullyDefinedType(_, "implicit function parameter", tree.pos))
15831583
val ifun = desugar.makeImplicitFunction(paramTypes, tree)
15841584
typr.println(i"make implicit function $tree / $pt ---> $ifun")
1585-
typedUnadapted(ifun)
1585+
typed(ifun, pt)
15861586
}
15871587

15881588
def typed(tree: untpd.Tree, pt: Type = WildcardType)(implicit ctx: Context): Tree = /*>|>*/ ctx.traceIndented (i"typing $tree", typr, show = true) /*<|<*/ {

0 commit comments

Comments
 (0)