aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/dotty/tools/dotc/core/Flags.scala2
-rw-r--r--src/dotty/tools/dotc/typer/Inliner.scala39
-rw-r--r--src/dotty/tools/dotc/typer/Typer.scala5
-rw-r--r--tests/run/inlinedAssign.scala6
4 files changed, 30 insertions, 22 deletions
diff --git a/src/dotty/tools/dotc/core/Flags.scala b/src/dotty/tools/dotc/core/Flags.scala
index 1a1182c7b..b7befa6e2 100644
--- a/src/dotty/tools/dotc/core/Flags.scala
+++ b/src/dotty/tools/dotc/core/Flags.scala
@@ -431,7 +431,7 @@ object Flags {
/** Flags representing source modifiers */
final val SourceModifierFlags =
- commonFlags(Private, Protected, Abstract, Final,
+ commonFlags(Private, Protected, Abstract, Final, Inline,
Sealed, Case, Implicit, Override, AbsOverride, Lazy, JavaStatic)
/** Flags representing modifiers that can appear in trees */
diff --git a/src/dotty/tools/dotc/typer/Inliner.scala b/src/dotty/tools/dotc/typer/Inliner.scala
index a78d1c029..e9c054ff2 100644
--- a/src/dotty/tools/dotc/typer/Inliner.scala
+++ b/src/dotty/tools/dotc/typer/Inliner.scala
@@ -377,11 +377,13 @@ class Inliner(call: tpd.Tree, rhs: tpd.Tree)(implicit ctx: Context) {
case tp: MethodType =>
(tp.paramNames, tp.paramTypes, argss.head).zipped.foreach { (name, paramtp, arg) =>
def isByName = paramtp.dealias.isInstanceOf[ExprType]
- paramBinding(name) = arg.tpe.stripTypeVar match {
+ paramBinding(name) = arg.tpe.stripAnnots.stripTypeVar match {
case argtpe: SingletonType if isByName || isIdempotentExpr(arg) => argtpe
case argtpe =>
+ val inlineFlag = if (paramtp.hasAnnotation(defn.InlineParamAnnot)) Inline else EmptyFlags
val (bindingFlags, bindingType) =
- if (isByName) (Method, ExprType(argtpe.widen)) else (EmptyFlags, argtpe.widen)
+ if (isByName) (inlineFlag | Method, ExprType(argtpe.widen))
+ else (inlineFlag, argtpe.widen)
val boundSym = newSym(name, bindingFlags, bindingType).asTerm
val binding =
if (isByName) DefDef(boundSym, arg.changeOwner(ctx.owner, boundSym))
@@ -500,22 +502,22 @@ class Inliner(call: tpd.Tree, rhs: tpd.Tree)(implicit ctx: Context) {
val inliner = new TreeTypeMap(typeMap, treeMap, meth :: Nil, ctx.owner :: Nil)
val expansion = inliner(rhs.withPos(call.pos))
+ ctx.traceIndented(i"inlining $call\n, BINDINGS =\n${bindingsBuf.toList}%\n%\nEXPANSION =\n$expansion", inlining, show = true) {
- // The final expansion runs a typing pass over the inlined tree. See InlineTyper for details.
- val expansion1 = InlineTyper.typed(expansion, pt)(inlineContext(call))
+ // The final expansion runs a typing pass over the inlined tree. See InlineTyper for details.
+ val expansion1 = InlineTyper.typed(expansion, pt)(inlineContext(call))
- /** Does given definition bind a closure that will be inlined? */
- def bindsDeadClosure(defn: ValOrDefDef) = Ident(defn.symbol.termRef) match {
- case InlineableClosure(_) => !InlineTyper.retainedClosures.contains(defn.symbol)
- case _ => false
- }
+ /** Does given definition bind a closure that will be inlined? */
+ def bindsDeadClosure(defn: ValOrDefDef) = Ident(defn.symbol.termRef) match {
+ case InlineableClosure(_) => !InlineTyper.retainedClosures.contains(defn.symbol)
+ case _ => false
+ }
- /** All bindings in `bindingsBuf` except bindings of inlineable closures */
- val bindings = bindingsBuf.toList.filterNot(bindsDeadClosure).map(_.withPos(call.pos))
+ /** All bindings in `bindingsBuf` except bindings of inlineable closures */
+ val bindings = bindingsBuf.toList.filterNot(bindsDeadClosure).map(_.withPos(call.pos))
- val result = tpd.Inlined(call, bindings, expansion1)
- inlining.println(i"inlined $call\n --> \n$result")
- result
+ tpd.Inlined(call, bindings, expansion1)
+ }
}
/** An extractor for references to closure arguments that refer to `@inline` methods */
@@ -523,8 +525,12 @@ class Inliner(call: tpd.Tree, rhs: tpd.Tree)(implicit ctx: Context) {
lazy val paramProxies = paramProxy.values.toSet
def unapply(tree: Ident)(implicit ctx: Context): Option[Tree] =
if (paramProxies.contains(tree.tpe)) {
- bindingsBuf.find(_.name == tree.name).map(_.rhs) match {
- case Some(closure(_, meth, _)) if meth.symbol.isInlineMethod => Some(meth)
+ bindingsBuf.find(_.name == tree.name) match {
+ case Some(ddef: ValDef) if ddef.symbol.is(Inline) =>
+ ddef.rhs match {
+ case closure(_, meth, _) => Some(meth)
+ case _ => None
+ }
case _ => None
}
} else None
@@ -571,6 +577,7 @@ class Inliner(call: tpd.Tree, rhs: tpd.Tree)(implicit ctx: Context) {
override def typedApply(tree: untpd.Apply, pt: Type)(implicit ctx: Context) = tree.asInstanceOf[tpd.Tree] match {
case Apply(Select(InlineableClosure(fn), nme.apply), args) =>
+ inlining.println(i"reducing $tree with closure $fn")
typed(fn.appliedToArgs(args), pt)
case _ =>
super.typedApply(tree, pt)
diff --git a/src/dotty/tools/dotc/typer/Typer.scala b/src/dotty/tools/dotc/typer/Typer.scala
index 18b609f8d..4c7d1c50d 100644
--- a/src/dotty/tools/dotc/typer/Typer.scala
+++ b/src/dotty/tools/dotc/typer/Typer.scala
@@ -745,10 +745,7 @@ class Typer extends Namer with TypeAssigner with Applications with Implicits wit
case WildcardType(_) => untpd.TypeTree()
case _ => untpd.TypeTree(protoResult)
}
- val inlineable = fnBody match {
- case Apply(untpd.TypedSplice(fn), _) => Inliner.hasBodyToInline(fn.symbol)
- case _ => false
- }
+ val inlineable = pt.hasAnnotation(defn.InlineParamAnnot)
desugar.makeClosure(inferredParams, fnBody, resultTpt, inlineable)
}
typed(desugared, pt)
diff --git a/tests/run/inlinedAssign.scala b/tests/run/inlinedAssign.scala
index 5b73a6f0c..f241780ed 100644
--- a/tests/run/inlinedAssign.scala
+++ b/tests/run/inlinedAssign.scala
@@ -1,6 +1,6 @@
object Test {
- inline def swap[T](x: T, x_= : T => Unit, y: T, y_= : T => Unit) = {
+ inline def swap[T](x: T, inline x_= : T => Unit, y: T, inline y_= : T => Unit) = {
val t = x
x_=(y)
y_=(t)
@@ -16,6 +16,10 @@ object Test {
swap(x, setX, y, setY)
assert(x == 2 && y == 1)
+ swap(x, x = _, y, y = _)
+ assert(x == 1 && y == 2)
+
+
val z = f(setX) // tests case where inline arg is not applied
}
}