@@ -85,10 +85,49 @@ object Inliner {
85
85
* @return An `Inlined` node that refers to the original call and the inlined bindings
86
86
* and body that replace it.
87
87
*/
88
- def inlineCall (tree : Tree , pt : Type )(implicit ctx : Context ): Tree = tree match {
89
- case Block (stats, expr) =>
90
- cpy.Block (tree)(stats, inlineCall(expr, pt))
91
- case _ if (enclosingInlineds.length < ctx.settings.XmaxInlines .value) =>
88
+ def inlineCall (tree : Tree , pt : Type )(implicit ctx : Context ): Tree = {
89
+
90
+ /** Set the position of all trees logically contained in the expansion of
91
+ * inlined call `call` to the position of `call`. This transform is necessary
92
+ * when lifting bindings from the expansion to the outside of the call.
93
+ */
94
+ def liftFromInlined (call : Tree ) = new TreeMap {
95
+ override def transform (t : Tree )(implicit ctx : Context ) = {
96
+ t match {
97
+ case Inlined (t, Nil , expr) if t.isEmpty => expr
98
+ case _ => super .transform(t.withPos(call.pos))
99
+ }
100
+ }
101
+ }
102
+
103
+ val bindings = new mutable.ListBuffer [Tree ]
104
+
105
+ /** Lift bindings in function or argument of inline call to
106
+ * the `bindings` buffer. This is done as an optimization to keep
107
+ * inline call expansions smaller.
108
+ */
109
+ def liftBindings (tree : Tree , liftPos : Tree => Tree ): Tree = tree match {
110
+ case Block (stats, expr) =>
111
+ bindings ++= stats.map(liftPos)
112
+ liftBindings(expr, liftPos)
113
+ case Inlined (call, stats, expr) =>
114
+ bindings ++= stats.map(liftPos)
115
+ val lifter = liftFromInlined(call)
116
+ cpy.Inlined (tree)(call, Nil , liftBindings(expr, liftFromInlined(call).transform(_)))
117
+ case Apply (fn, args) =>
118
+ cpy.Apply (tree)(liftBindings(fn, liftPos), args.map(liftBindings(_, liftPos)))
119
+ case TypeApply (fn, args) =>
120
+ cpy.TypeApply (tree)(liftBindings(fn, liftPos), args)
121
+ case Select (qual, name) =>
122
+ cpy.Select (tree)(liftBindings(qual, liftPos), name)
123
+ case _ =>
124
+ tree
125
+ }
126
+
127
+ val tree1 = liftBindings(tree, identity)
128
+ if (bindings.nonEmpty)
129
+ cpy.Block (tree)(bindings.toList, inlineCall(tree1, pt))
130
+ else if (enclosingInlineds.length < ctx.settings.XmaxInlines .value) {
92
131
val body = bodyToInline(tree.symbol) // can typecheck the tree and thereby produce errors
93
132
if (ctx.reporter.hasErrors) tree
94
133
else {
@@ -97,7 +136,8 @@ object Inliner {
97
136
else ctx.fresh.setProperty(InlineBindings , newMutableSymbolMap[Tree ])
98
137
new Inliner (tree, body)(inlinerCtx).inlined(pt)
99
138
}
100
- case _ =>
139
+ }
140
+ else
101
141
errorTree(
102
142
tree,
103
143
i """ |Maximal number of successive inlines ( ${ctx.settings.XmaxInlines .value}) exceeded,
0 commit comments