diff options
author | Martin Odersky <odersky@gmail.com> | 2016-09-06 13:20:39 +0200 |
---|---|---|
committer | Martin Odersky <odersky@gmail.com> | 2016-10-02 16:11:21 +0200 |
commit | 19ab7ab10fabe7113f45063ffd2b6cc6abcc3329 (patch) | |
tree | 3672315832460f5d636074fc2c387d243597cff5 | |
parent | bd0660ef100ee1a41bd56267d9e95c9e6dd74d5e (diff) | |
download | dotty-19ab7ab10fabe7113f45063ffd2b6cc6abcc3329.tar.gz dotty-19ab7ab10fabe7113f45063ffd2b6cc6abcc3329.tar.bz2 dotty-19ab7ab10fabe7113f45063ffd2b6cc6abcc3329.zip |
Make inline annotation @scala.inline.
Drop @dotty.annotation.inline. This will inline all
@inline marked methods in Scala for which a body is known
(i.e. that are either compiled in the same run or have Tasty
trees available).
Option -Yno-inline suppresses inlining. This is needed for
the moment because some @inline methods access private members
or members that are otherwise inaccessible at the call-site.
Also fixes some problems in Inliner
- make sure type arguments to inline calls re fully defined
- don't forget recursive calls in typeMap
- don't forget positions in treeMap
- drop dead code dealing with outer.
-rw-r--r-- | src/dotty/annotation/inline.scala | 8 | ||||
-rw-r--r-- | src/dotty/tools/dotc/config/ScalaSettings.scala | 1 | ||||
-rw-r--r-- | src/dotty/tools/dotc/core/Decorators.scala | 2 | ||||
-rw-r--r-- | src/dotty/tools/dotc/core/Definitions.scala | 2 | ||||
-rw-r--r-- | src/dotty/tools/dotc/reporting/Reporter.scala | 6 | ||||
-rw-r--r-- | src/dotty/tools/dotc/typer/Inliner.scala | 42 | ||||
-rw-r--r-- | src/dotty/tools/dotc/typer/Typer.scala | 2 | ||||
-rw-r--r-- | src/dotty/tools/dotc/util/Stats.scala | 4 | ||||
-rw-r--r-- | test/dotc/tests.scala | 4 | ||||
-rw-r--r-- | tests/neg/inlineAccess.scala | 15 | ||||
-rw-r--r-- | tests/neg/inlineAccess/C_1.scala | 2 | ||||
-rw-r--r-- | tests/neg/power.scala | 2 | ||||
-rw-r--r-- | tests/run/inline/inlines_1.scala | 10 | ||||
-rw-r--r-- | tests/run/inlinePower/power_1.scala | 2 | ||||
-rw-r--r-- | tests/run/inlinedAssign.scala | 6 |
15 files changed, 41 insertions, 67 deletions
diff --git a/src/dotty/annotation/inline.scala b/src/dotty/annotation/inline.scala deleted file mode 100644 index ff4ca08b6..000000000 --- a/src/dotty/annotation/inline.scala +++ /dev/null @@ -1,8 +0,0 @@ -package dotty.annotation - -import scala.annotation.Annotation - -/** Unlike scala.inline, this one forces inlining in the Typer - * Should be replaced by keyword when we switch over completely to dotty - */ -class inline extends Annotation
\ No newline at end of file diff --git a/src/dotty/tools/dotc/config/ScalaSettings.scala b/src/dotty/tools/dotc/config/ScalaSettings.scala index d05ae0803..42e761c2e 100644 --- a/src/dotty/tools/dotc/config/ScalaSettings.scala +++ b/src/dotty/tools/dotc/config/ScalaSettings.scala @@ -186,6 +186,7 @@ class ScalaSettings extends Settings.SettingGroup { val Yexplainlowlevel = BooleanSetting("-Yexplain-lowlevel", "When explaining type errors, show types at a lower level.") val YnoDoubleBindings = BooleanSetting("-Yno-double-bindings", "Assert no namedtype is bound twice (should be enabled only if program is error-free).") val YshowVarBounds = BooleanSetting("-Yshow-var-bounds", "Print type variables with their bounds") + val YnoInline = BooleanSetting("-Yno-inline", "Suppress inlining.") val optimise = BooleanSetting("-optimise", "Generates faster bytecode by applying optimisations to the program") withAbbreviation "-optimize" diff --git a/src/dotty/tools/dotc/core/Decorators.scala b/src/dotty/tools/dotc/core/Decorators.scala index 64f50173c..691e0aeba 100644 --- a/src/dotty/tools/dotc/core/Decorators.scala +++ b/src/dotty/tools/dotc/core/Decorators.scala @@ -42,7 +42,7 @@ object Decorators { */ implicit class ListDecorator[T](val xs: List[T]) extends AnyVal { - @inline final def mapconserve[U](f: T => U): List[U] = { + final def mapconserve[U](f: T => U): List[U] = { @tailrec def loop(mapped: ListBuffer[U], unchanged: List[U], pending: List[T]): List[U] = if (pending.isEmpty) { diff --git a/src/dotty/tools/dotc/core/Definitions.scala b/src/dotty/tools/dotc/core/Definitions.scala index c9a3ef4de..8bf340337 100644 --- a/src/dotty/tools/dotc/core/Definitions.scala +++ b/src/dotty/tools/dotc/core/Definitions.scala @@ -466,7 +466,7 @@ class Definitions { def DeprecatedAnnot(implicit ctx: Context) = DeprecatedAnnotType.symbol.asClass lazy val ImplicitNotFoundAnnotType = ctx.requiredClassRef("scala.annotation.implicitNotFound") def ImplicitNotFoundAnnot(implicit ctx: Context) = ImplicitNotFoundAnnotType.symbol.asClass - lazy val InlineAnnotType = ctx.requiredClassRef("dotty.annotation.inline") + lazy val InlineAnnotType = ctx.requiredClassRef("scala.inline") def InlineAnnot(implicit ctx: Context) = InlineAnnotType.symbol.asClass lazy val InvariantBetweenAnnotType = ctx.requiredClassRef("dotty.annotation.internal.InvariantBetween") def InvariantBetweenAnnot(implicit ctx: Context) = InvariantBetweenAnnotType.symbol.asClass diff --git a/src/dotty/tools/dotc/reporting/Reporter.scala b/src/dotty/tools/dotc/reporting/Reporter.scala index 68ed972e1..f3777473d 100644 --- a/src/dotty/tools/dotc/reporting/Reporter.scala +++ b/src/dotty/tools/dotc/reporting/Reporter.scala @@ -140,16 +140,16 @@ trait Reporting { this: Context => def debugwarn(msg: => String, pos: SourcePosition = NoSourcePosition): Unit = if (this.settings.debug.value) warning(msg, pos) - @dotty.annotation.inline + @inline def debugTraceIndented[TD](question: => String, printer: Printers.Printer = Printers.default, show: Boolean = false)(op: => TD): TD = conditionalTraceIndented(this.settings.debugTrace.value, question, printer, show)(op) - @dotty.annotation.inline + @inline def conditionalTraceIndented[TC](cond: Boolean, question: => String, printer: Printers.Printer = Printers.default, show: Boolean = false)(op: => TC): TC = if (cond) traceIndented[TC](question, printer, show)(op) else op - @dotty.annotation.inline + @inline def traceIndented[T](question: => String, printer: Printers.Printer = Printers.default, show: Boolean = false)(op: => T): T = if (printer eq config.Printers.noPrinter) op else doTraceIndented[T](question, printer, show)(op) diff --git a/src/dotty/tools/dotc/typer/Inliner.scala b/src/dotty/tools/dotc/typer/Inliner.scala index 4af9ecaec..b59c33008 100644 --- a/src/dotty/tools/dotc/typer/Inliner.scala +++ b/src/dotty/tools/dotc/typer/Inliner.scala @@ -17,6 +17,7 @@ import Names.Name import SymDenotations.SymDenotation import Annotations.Annotation import transform.ExplicitOuter +import Inferencing.fullyDefinedType import config.Printers.inlining import ErrorReporting.errorTree import util.{Property, SourceFile, NoSource} @@ -36,13 +37,13 @@ object Inliner { def attachBody(inlineAnnot: Annotation, tree: => Tree)(implicit ctx: Context): Unit = inlineAnnot.tree.putAttachment(InlinedBody, new InlinedBody(tree)) - def inlinedBody(sym: SymDenotation)(implicit ctx: Context): Tree = + def inlinedBody(sym: SymDenotation)(implicit ctx: Context): Option[Tree] = sym.getAnnotation(defn.InlineAnnot).get.tree - .attachment(InlinedBody).body + .getAttachment(InlinedBody).map(_.body) def inlineCall(tree: Tree, pt: Type)(implicit ctx: Context): Tree = if (enclosingInlineds.length < ctx.settings.xmaxInlines.value) - new Inliner(tree, inlinedBody(tree.symbol)).inlined(pt) + new Inliner(tree, inlinedBody(tree.symbol).get).inlined(pt) else errorTree(tree, i"""Maximal number of successive inlines (${ctx.settings.xmaxInlines.value}) exceeded, | Maybe this is caused by a recursive inline method? @@ -86,6 +87,8 @@ class Inliner(call: tpd.Tree, rhs: tpd.Tree)(implicit ctx: Context) { private val (methPart, targs, argss) = decomposeCall(call) private val meth = methPart.symbol + for (targ <- targs) fullyDefinedType(targ.tpe, "inlined type argument", targ.pos) + private val prefix = methPart match { case Select(qual, _) => qual case _ => tpd.This(ctx.owner.enclosingClass.asClass) @@ -156,19 +159,9 @@ class Inliner(call: tpd.Tree, rhs: tpd.Tree)(implicit ctx: Context) { private object InlineTyper extends ReTyper { override def typedSelect(tree: untpd.Select, pt: Type)(implicit ctx: Context): Tree = { - val acc = tree.symbol - super.typedSelect(tree, pt) match { - case res @ Select(qual, name) => - if (name.endsWith(nme.OUTER)) { - val outerAcc = tree.symbol - res.withType(qual.tpe.widen.normalizedPrefix) - } - else { - ensureAccessible(res.tpe, qual.isInstanceOf[Super], tree.pos) - res - } - case res => res - } + val res = super.typedSelect(tree, pt) + ensureAccessible(res.tpe, tree.qualifier.isInstanceOf[untpd.Super], tree.pos) + res } override def typedIf(tree: untpd.If, pt: Type)(implicit ctx: Context) = { val cond1 = typed(tree.cond, defn.BooleanType) @@ -207,26 +200,27 @@ class Inliner(call: tpd.Tree, rhs: tpd.Tree)(implicit ctx: Context) { val typeMap = new TypeMap { def apply(t: Type) = t match { case t: ThisType => thisProxy.getOrElse(t, t) - case t: TypeRef => paramProxy.getOrElse(t, t) - case t: SingletonType => paramProxy.getOrElse(t, t) + case t: TypeRef => paramProxy.getOrElse(t, mapOver(t)) + case t: SingletonType => paramProxy.getOrElse(t, mapOver(t)) case t => mapOver(t) } } - def treeMap(tree: Tree) = tree match { + def treeMap(tree: Tree) = { + tree match { case _: This => thisProxy.get(tree.tpe) match { - case Some(t) => ref(t) + case Some(t) => ref(t).withPos(tree.pos) case None => tree } case _: Ident => paramProxy.get(tree.tpe) match { - case Some(t: SingletonType) if tree.isTerm => singleton(t) - case Some(t) if tree.isType => TypeTree(t) + case Some(t: SingletonType) if tree.isTerm => singleton(t).withPos(tree.pos) + case Some(t) if tree.isType => TypeTree(t).withPos(tree.pos) case None => tree } case _ => tree - } + }} val inliner = new TreeTypeMap(typeMap, treeMap, meth :: Nil, ctx.owner :: Nil) val bindings = bindingsBuf.toList.map(_.withPos(call.pos)) @@ -235,7 +229,7 @@ class Inliner(call: tpd.Tree, rhs: tpd.Tree)(implicit ctx: Context) { val expansion1 = InlineTyper.typed(expansion, pt)(inlineContext(call)) val result = tpd.Inlined(call, bindings, expansion1) - inlining.println(i"inlining $call\n --> \n$result") + inlining.println(i"inlined $call\n --> \n$result") result } } diff --git a/src/dotty/tools/dotc/typer/Typer.scala b/src/dotty/tools/dotc/typer/Typer.scala index 22a5095ec..29c36805f 100644 --- a/src/dotty/tools/dotc/typer/Typer.scala +++ b/src/dotty/tools/dotc/typer/Typer.scala @@ -1794,7 +1794,9 @@ class Typer extends Namer with TypeAssigner with Applications with Implicits wit } else if (tree.tpe <:< pt) if (tree.symbol.isInlineMethod && + Inliner.inlinedBody(tree.symbol).isDefined && !ctx.owner.ownersIterator.exists(_.isInlineMethod) && + !ctx.settings.YnoInline.value && !ctx.isAfterTyper) adapt(Inliner.inlineCall(tree, pt), pt) else if (ctx.typeComparer.GADTused && pt.isValueType) diff --git a/src/dotty/tools/dotc/util/Stats.scala b/src/dotty/tools/dotc/util/Stats.scala index f5e711348..e06695dfb 100644 --- a/src/dotty/tools/dotc/util/Stats.scala +++ b/src/dotty/tools/dotc/util/Stats.scala @@ -20,7 +20,7 @@ import collection.mutable override def default(key: String): Int = 0 } - @dotty.annotation.inline + @inline def record(fn: String, n: Int = 1) = if (enabled) doRecord(fn, n) @@ -30,7 +30,7 @@ import collection.mutable hits(name) += n } - @dotty.annotation.inline + @inline def track[T](fn: String)(op: => T) = if (enabled) doTrack(fn)(op) else op diff --git a/test/dotc/tests.scala b/test/dotc/tests.scala index 9f95a30c1..a12e77918 100644 --- a/test/dotc/tests.scala +++ b/test/dotc/tests.scala @@ -156,7 +156,7 @@ class tests extends CompilerTest { .filter(_.nonEmpty) .toList - @Test def compileStdLib = compileList("compileStdLib", stdlibFiles, "-migration" :: scala2mode) + @Test def compileStdLib = compileList("compileStdLib", stdlibFiles, "-migration" :: "-Yno-inline" :: scala2mode) @Test def compileMixed = compileLine( """tests/pos/B.scala |./scala-scala/src/library/scala/collection/immutable/Seq.scala @@ -274,7 +274,7 @@ class tests extends CompilerTest { "ClassOf.scala", "CollectEntryPoints.scala", "Constructors.scala", "CrossCastAnd.scala", "CtxLazy.scala", "ElimByName.scala", "ElimErasedValueType.scala", "ElimRepeated.scala", "ElimStaticThis.scala", "Erasure.scala", "ExpandPrivate.scala", "ExpandSAMs.scala", - "ExplicitOuter.scala", "ExplicitSelf.scala", "ExtensionMethods.scala", "FirstTransform.scala", + "ExplicitOuter.scala", "ExtensionMethods.scala", "FirstTransform.scala", "Flatten.scala", "FullParameterization.scala", "FunctionalInterfaces.scala", "GetClass.scala", "Getters.scala", "InterceptedMethods.scala", "LambdaLift.scala", "LiftTry.scala", "LinkScala2ImplClasses.scala", "MacroTransform.scala", "Memoize.scala", "Mixin.scala", "MixinOps.scala", "NonLocalReturns.scala", diff --git a/tests/neg/inlineAccess.scala b/tests/neg/inlineAccess.scala deleted file mode 100644 index cfb1cc06f..000000000 --- a/tests/neg/inlineAccess.scala +++ /dev/null @@ -1,15 +0,0 @@ -package p { -class C { - protected def f(): Unit = () - - @dotty.annotation.inline - def inl() = f() // error (when inlined): not accessible -} -} - -object Test { - def main(args: Array[String]) = { - val c = new p.C() - c.inl() - } -} diff --git a/tests/neg/inlineAccess/C_1.scala b/tests/neg/inlineAccess/C_1.scala index fc24f7666..6db1ea787 100644 --- a/tests/neg/inlineAccess/C_1.scala +++ b/tests/neg/inlineAccess/C_1.scala @@ -2,7 +2,7 @@ package p { class C { protected def f(): Unit = () - @dotty.annotation.inline + @inline def inl() = f() // error (when inlined): not accessible } } diff --git a/tests/neg/power.scala b/tests/neg/power.scala index 7439d8699..6230b4e51 100644 --- a/tests/neg/power.scala +++ b/tests/neg/power.scala @@ -1,6 +1,6 @@ object Test { - @dotty.annotation.inline + @inline def power(x: Double, n: Int): Double = if (n == 0) 1.0 else if (n == 1) x diff --git a/tests/run/inline/inlines_1.scala b/tests/run/inline/inlines_1.scala index 36f5ac402..8189e6805 100644 --- a/tests/run/inline/inlines_1.scala +++ b/tests/run/inline/inlines_1.scala @@ -5,7 +5,7 @@ object inlines { final val monitored = false - @dotty.annotation.inline + @inline def f(x: Int): Int = x * x val hits = new mutable.HashMap[String, Int] { @@ -21,7 +21,7 @@ object inlines { @volatile private var stack: List[String] = Nil - @dotty.annotation.inline + @inline def track[T](fn: String)(op: => T) = if (monitored) { stack = fn :: stack @@ -34,9 +34,9 @@ object inlines { def f = "Outer.f" class Inner { val msg = " Inner" - @dotty.annotation.inline def m = msg - @dotty.annotation.inline def g = f - @dotty.annotation.inline def h = f ++ m + @inline def m = msg + @inline def g = f + @inline def h = f ++ m } val inner = new Inner } diff --git a/tests/run/inlinePower/power_1.scala b/tests/run/inlinePower/power_1.scala index 1faa10516..23da6009a 100644 --- a/tests/run/inlinePower/power_1.scala +++ b/tests/run/inlinePower/power_1.scala @@ -2,7 +2,7 @@ package p object pow { - @dotty.annotation.inline + @inline def power(x: Double, n: Int): Double = if (n == 0) 1.0 else if (n == 1) x diff --git a/tests/run/inlinedAssign.scala b/tests/run/inlinedAssign.scala index 735158209..b9a5d287d 100644 --- a/tests/run/inlinedAssign.scala +++ b/tests/run/inlinedAssign.scala @@ -1,6 +1,6 @@ object Test { - @dotty.annotation.inline + @inline def swap[T](x: T, x_= : T => Unit, y: T, y_= : T => Unit) = { val t = x x_=(y) @@ -10,8 +10,8 @@ object Test { def main(args: Array[String]) = { var x = 1 var y = 2 - @dotty.annotation.inline def setX(z: Int) = x = z - @dotty.annotation.inline def setY(z: Int) = y = z + @inline def setX(z: Int) = x = z + @inline def setY(z: Int) = y = z swap[Int](x, setX, y, setY) assert(x == 2 && y == 1) } |