diff options
-rw-r--r-- | src/dotty/tools/dotc/core/Flags.scala | 2 | ||||
-rw-r--r-- | src/dotty/tools/dotc/typer/Inliner.scala | 39 | ||||
-rw-r--r-- | src/dotty/tools/dotc/typer/Typer.scala | 5 | ||||
-rw-r--r-- | tests/run/inlinedAssign.scala | 6 |
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 } } |