aboutsummaryrefslogtreecommitdiff
path: root/src/dotty/tools/dotc/typer/Inliner.scala
diff options
context:
space:
mode:
authorMartin Odersky <odersky@gmail.com>2016-09-02 13:51:20 +0200
committerMartin Odersky <odersky@gmail.com>2016-10-02 16:11:21 +0200
commitb8a117634b636d6255e6233ae1996f6c7b90dcae (patch)
treec77fdd6c434366b956eae9dd17a6075317234aaf /src/dotty/tools/dotc/typer/Inliner.scala
parent729815bec8035f2d6132fde0eb928e877dd21a64 (diff)
downloaddotty-b8a117634b636d6255e6233ae1996f6c7b90dcae.tar.gz
dotty-b8a117634b636d6255e6233ae1996f6c7b90dcae.tar.bz2
dotty-b8a117634b636d6255e6233ae1996f6c7b90dcae.zip
Avoid simple aliases in bindings
Avoid bindings such as type T = T' val x: x'.type = x' Required some refactorings in Inliner.
Diffstat (limited to 'src/dotty/tools/dotc/typer/Inliner.scala')
-rw-r--r--src/dotty/tools/dotc/typer/Inliner.scala119
1 files changed, 66 insertions, 53 deletions
diff --git a/src/dotty/tools/dotc/typer/Inliner.scala b/src/dotty/tools/dotc/typer/Inliner.scala
index 8d9b5bf30..c6177eb8d 100644
--- a/src/dotty/tools/dotc/typer/Inliner.scala
+++ b/src/dotty/tools/dotc/typer/Inliner.scala
@@ -114,8 +114,6 @@ object Inliner {
class Inliner(call: tpd.Tree, rhs: tpd.Tree)(implicit ctx: Context) {
import tpd._
- private val meth = call.symbol
-
private def decomposeCall(tree: Tree): (Tree, List[Tree], List[List[Tree]]) = tree match {
case Apply(fn, args) =>
val (meth, targs, argss) = decomposeCall(fn)
@@ -128,64 +126,73 @@ class Inliner(call: tpd.Tree, rhs: tpd.Tree)(implicit ctx: Context) {
}
private val (methPart, targs, argss) = decomposeCall(call)
+ private val meth = methPart.symbol
private lazy val prefix = methPart match {
case Select(qual, _) => qual
case _ => tpd.This(ctx.owner.enclosingClass.asClass)
}
- private val replacement = new mutable.HashMap[Type, NamedType]
+ private val thisProxy = new mutable.HashMap[Type, NamedType]
+ private val paramProxy = new mutable.HashMap[Type, Type]
+ private val paramBinding = new mutable.HashMap[Name, Type]
+ val bindingsBuf = new mutable.ListBuffer[MemberDef]
- private val paramBindings = paramBindingsOf(meth.info, targs, argss)
+ computeParamBindings(meth.info, targs, argss)
- private def paramBindingsOf(tp: Type, targs: List[Tree], argss: List[List[Tree]]): List[MemberDef] = tp match {
+ private def newSym(name: Name, flags: FlagSet, info: Type): Symbol =
+ ctx.newSymbol(ctx.owner, name, flags, info, coord = call.pos)
+
+ private def computeParamBindings(tp: Type, targs: List[Tree], argss: List[List[Tree]]): Unit = tp match {
case tp: PolyType =>
- val bindings =
- (tp.paramNames, targs).zipped.map { (name, arg) =>
- val tparam = newSym(name, EmptyFlags, TypeAlias(arg.tpe.stripTypeVar)).asType
- TypeDef(tparam)
+ (tp.paramNames, targs).zipped.foreach { (name, arg) =>
+ paramBinding(name) = arg.tpe.stripTypeVar match {
+ case argtpe: TypeRef => argtpe
+ case argtpe =>
+ val binding = newSym(name, EmptyFlags, TypeAlias(argtpe)).asType
+ bindingsBuf += TypeDef(binding)
+ binding.typeRef
}
- bindings ::: paramBindingsOf(tp.resultType, Nil, argss)
+ }
+ computeParamBindings(tp.resultType, Nil, argss)
case tp: MethodType =>
- val bindings =
- (tp.paramNames, tp.paramTypes, argss.head).zipped.map { (name, paramtp, arg) =>
- def isByName = paramtp.dealias.isInstanceOf[ExprType]
- val (paramFlags, paramType) =
- if (isByName) (Method, ExprType(arg.tpe)) else (EmptyFlags, arg.tpe)
- val vparam = newSym(name, paramFlags, paramType).asTerm
- if (isByName) DefDef(vparam, arg) else ValDef(vparam, arg)
+ (tp.paramNames, tp.paramTypes, argss.head).zipped.foreach { (name, paramtp, arg) =>
+ def isByName = paramtp.dealias.isInstanceOf[ExprType]
+ paramBinding(name) = arg.tpe.stripTypeVar match {
+ case argtpe: SingletonType if isByName || isIdempotentExpr(arg) => argtpe
+ case argtpe =>
+ val (bindingFlags, bindingType) =
+ if (isByName) (Method, ExprType(argtpe.widen)) else (EmptyFlags, argtpe.widen)
+ val binding = newSym(name, bindingFlags, bindingType).asTerm
+ bindingsBuf +=
+ (if (isByName) DefDef(binding, arg) else ValDef(binding, arg))
+ binding.termRef
}
- bindings ::: paramBindingsOf(tp.resultType, targs, argss.tail)
+ }
+ computeParamBindings(tp.resultType, targs, argss.tail)
case _ =>
assert(targs.isEmpty)
assert(argss.isEmpty)
- Nil
}
- private def newSym(name: Name, flags: FlagSet, info: Type): Symbol =
- ctx.newSymbol(ctx.owner, name, flags, info, coord = call.pos)
-
- private def registerType(tpe: Type): Unit =
- if (!replacement.contains(tpe)) tpe match {
- case tpe: ThisType =>
- if (!ctx.owner.isContainedIn(tpe.cls) && !tpe.cls.is(Package))
- if (tpe.cls.isStaticOwner)
- replacement(tpe) = tpe.cls.sourceModule.termRef
- else {
- def outerDistance(cls: Symbol): Int = {
- assert(cls.exists, i"not encl: ${meth.owner.enclosingClass} ${tpe.cls}")
- if (tpe.cls eq cls) 0
- else outerDistance(cls.owner.enclosingClass) + 1
- }
- val n = outerDistance(meth.owner)
- replacement(tpe) = newSym(nme.SELF ++ n.toString, EmptyFlags, tpe.widen).termRef
+ private def registerType(tpe: Type): Unit = tpe match {
+ case tpe: ThisType if !thisProxy.contains(tpe) =>
+ if (!ctx.owner.isContainedIn(tpe.cls) && !tpe.cls.is(Package))
+ if (tpe.cls.isStaticOwner)
+ thisProxy(tpe) = tpe.cls.sourceModule.termRef
+ else {
+ def outerDistance(cls: Symbol): Int = {
+ assert(cls.exists, i"not encl: ${meth.owner.enclosingClass} ${tpe.cls}")
+ if (tpe.cls eq cls) 0
+ else outerDistance(cls.owner.enclosingClass) + 1
}
- case tpe: NamedType if tpe.symbol.is(Param) && tpe.symbol.owner == meth =>
- val Some(binding) = paramBindings.find(_.name == tpe.name)
- replacement(tpe) =
- if (tpe.name.isTypeName) binding.symbol.typeRef else binding.symbol.termRef
- case _ =>
- }
+ val n = outerDistance(meth.owner)
+ thisProxy(tpe) = newSym(nme.SELF ++ n.toString, EmptyFlags, tpe.widen).termRef
+ }
+ case tpe: NamedType if tpe.symbol.is(Param) && tpe.symbol.owner == meth && !paramProxy.contains(tpe) =>
+ paramProxy(tpe) = paramBinding(tpe.name)
+ case _ =>
+ }
private def registerLeaf(tree: Tree): Unit = tree match {
case _: This | _: Ident => registerType(tree.tpe)
@@ -198,42 +205,48 @@ class Inliner(call: tpd.Tree, rhs: tpd.Tree)(implicit ctx: Context) {
rhs.foreachSubTree(registerLeaf)
val accessedSelfSyms =
- (for ((tp: ThisType, ref) <- replacement) yield ref.symbol.asTerm).toSeq.sortBy(outerLevel)
+ (for ((tp: ThisType, ref) <- thisProxy) yield ref.symbol.asTerm).toSeq.sortBy(outerLevel)
- val outerBindings = new mutable.ListBuffer[MemberDef]
+ var lastSelf: Symbol = NoSymbol
for (selfSym <- accessedSelfSyms) {
val rhs =
- if (outerBindings.isEmpty) prefix
+ if (!lastSelf.exists) prefix
else {
- val lastSelf = outerBindings.last.symbol
val outerDelta = outerLevel(selfSym) - outerLevel(lastSelf)
def outerSelect(ref: Tree, dummy: Int): Tree = ???
//ref.select(ExplicitOuter.outerAccessorTBD(ref.tpe.widen.classSymbol.asClass))
(ref(lastSelf) /: (0 until outerDelta))(outerSelect)
}
- outerBindings += ValDef(selfSym, rhs.ensureConforms(selfSym.info))
+ bindingsBuf += ValDef(selfSym, rhs.ensureConforms(selfSym.info))
+ lastSelf = selfSym
}
- outerBindings ++= paramBindings
val typeMap = new TypeMap {
def apply(t: Type) = t match {
- case _: SingletonType => replacement.getOrElse(t, t)
- case _ => mapOver(t)
+ case t: ThisType => thisProxy.getOrElse(t, t)
+ case t: SingletonType => paramProxy.getOrElse(t, t)
+ case t => mapOver(t)
}
}
def treeMap(tree: Tree) = tree match {
- case _: This | _: Ident =>
- replacement.get(tree.tpe) match {
+ case _: This =>
+ thisProxy.get(tree.tpe) match {
case Some(t) => ref(t)
case None => tree
}
+ case _: Ident =>
+ paramProxy.get(tree.tpe) match {
+ case Some(t: TypeRef) => ref(t)
+ case Some(t: SingletonType) => singleton(t)
+ case None => tree
+ }
case _ => tree
}
val inliner = new TreeTypeMap(typeMap, treeMap, meth :: Nil, ctx.owner :: Nil)
val Block(bindings: List[MemberDef], expansion) =
- inliner(Block(outerBindings.toList, rhs)).withPos(call.pos)
+ inliner(Block(bindingsBuf.toList, rhs)).withPos(call.pos)
val result = tpd.Inlined(call, bindings, expansion)
inlining.println(i"inlining $call\n --> \n$result")