@@ -37,6 +37,8 @@ import quoted.QuoteUtils
37
37
object Inliner {
38
38
import tpd ._
39
39
40
+ private type DefBuffer = mutable.ListBuffer [ValOrDefDef ]
41
+
40
42
/** `sym` is an inline method with a known body to inline.
41
43
*/
42
44
def hasBodyToInline (sym : SymDenotation )(using Context ): Boolean =
@@ -413,7 +415,7 @@ class Inliner(call: tpd.Tree, rhsToInline: tpd.Tree)(using Context) {
413
415
414
416
private val methPart = funPart(call)
415
417
private val callTypeArgs = typeArgss(call).flatten
416
- private val rawCallValueArgss = termArgss(call)
418
+ private val callValueArgss = termArgss(call)
417
419
private val inlinedMethod = methPart.symbol
418
420
private val inlineCallPrefix =
419
421
qualifier(methPart).orElse(This (inlinedMethod.enclosingClass.asClass))
@@ -465,14 +467,14 @@ class Inliner(call: tpd.Tree, rhsToInline: tpd.Tree)(using Context) {
465
467
/** A binding for the parameter of an inline method. This is a `val` def for
466
468
* by-value parameters and a `def` def for by-name parameters. `val` defs inherit
467
469
* inline annotations from their parameters. The generated `def` is appended
468
- * to `bindingsBuf `.
470
+ * to `buf `.
469
471
* @param name the name of the parameter
470
472
* @param formal the type of the parameter
471
473
* @param arg the argument corresponding to the parameter
472
- * @param bindingsBuf the buffer to which the definition should be appended
474
+ * @param buf the buffer to which the definition should be appended
473
475
*/
474
476
private def paramBindingDef (name : Name , formal : Type , arg0 : Tree ,
475
- bindingsBuf : mutable. ListBuffer [ ValOrDefDef ] )(using Context ): ValOrDefDef = {
477
+ buf : DefBuffer )(using Context ): ValOrDefDef = {
476
478
val isByName = formal.dealias.isInstanceOf [ExprType ]
477
479
val arg = arg0 match {
478
480
case Typed (arg1, tpt) if tpt.tpe.isRepeatedParam && arg1.tpe.derivesFrom(defn.ArrayClass ) =>
@@ -501,23 +503,25 @@ class Inliner(call: tpd.Tree, rhsToInline: tpd.Tree)(using Context) {
501
503
else ValDef (boundSym, newArg)
502
504
}.withSpan(boundSym.span)
503
505
inlining.println(i " parameter binding: $binding, $argIsBottom" )
504
- bindingsBuf += binding
506
+ buf += binding
505
507
binding
506
508
}
507
509
508
- /** Populate `paramBinding` and `bindingsBuf ` by matching parameters with
510
+ /** Populate `paramBinding` and `buf ` by matching parameters with
509
511
* corresponding arguments. `bindingbuf` will be further extended later by
510
512
* proxies to this-references. Issue an error if some arguments are missing.
511
513
*/
512
514
private def computeParamBindings (
513
- tp : Type , targs : List [Tree ], argss : List [List [Tree ]], formalss : List [List [Type ]]): Boolean =
515
+ tp : Type , targs : List [Tree ],
516
+ argss : List [List [Tree ]], formalss : List [List [Type ]],
517
+ buf : DefBuffer ): Boolean =
514
518
tp match
515
519
case tp : PolyType =>
516
520
tp.paramNames.lazyZip(targs).foreach { (name, arg) =>
517
521
paramSpan(name) = arg.span
518
522
paramBinding(name) = arg.tpe.stripTypeVar
519
523
}
520
- computeParamBindings(tp.resultType, targs.drop(tp.paramNames.length), argss, formalss)
524
+ computeParamBindings(tp.resultType, targs.drop(tp.paramNames.length), argss, formalss, buf )
521
525
case tp : MethodType =>
522
526
if argss.isEmpty then
523
527
report.error(i " missing arguments for inline method $inlinedMethod" , call.srcPos)
@@ -529,9 +533,9 @@ class Inliner(call: tpd.Tree, rhsToInline: tpd.Tree)(using Context) {
529
533
case _ : SingletonType if isIdempotentPath(arg) =>
530
534
arg.tpe
531
535
case _ =>
532
- paramBindingDef(name, formal, arg, bindingsBuf ).symbol.termRef
536
+ paramBindingDef(name, formal, arg, buf ).symbol.termRef
533
537
}
534
- computeParamBindings(tp.resultType, targs, argss.tail, formalss.tail)
538
+ computeParamBindings(tp.resultType, targs, argss.tail, formalss.tail, buf )
535
539
case _ =>
536
540
assert(targs.isEmpty)
537
541
assert(argss.isEmpty)
@@ -810,7 +814,7 @@ class Inliner(call: tpd.Tree, rhsToInline: tpd.Tree)(using Context) {
810
814
def inlined (sourcePos : SrcPos ): Tree = {
811
815
812
816
// Special handling of `requireConst` and `codeOf`
813
- rawCallValueArgss match
817
+ callValueArgss match
814
818
case (arg :: Nil ) :: Nil =>
815
819
if inlinedMethod == defn.Compiletime_requireConst then
816
820
arg match
@@ -860,24 +864,35 @@ class Inliner(call: tpd.Tree, rhsToInline: tpd.Tree)(using Context) {
860
864
case TypeApply (fn, _) => paramTypess(fn, acc)
861
865
case _ => acc
862
866
863
- val callValueArgss = rawCallValueArgss.nestedMapConserve(mapOpaquesInValueArg)
867
+ val paramBindings =
868
+ val mappedCallValueArgss = callValueArgss.nestedMapConserve(mapOpaquesInValueArg)
869
+ if mappedCallValueArgss ne callValueArgss then
870
+ inlining.println(i " mapped value args = ${mappedCallValueArgss.flatten}%, % " )
864
871
865
- if callValueArgss ne rawCallValueArgss then
866
- inlining.println(i " mapped value args = ${callValueArgss.flatten}%, % " )
872
+ val paramBindingsBuf = new DefBuffer
873
+ // Compute bindings for all parameters, appending them to bindingsBuf
874
+ if ! computeParamBindings(
875
+ inlinedMethod.info, callTypeArgs,
876
+ mappedCallValueArgss, paramTypess(call, Nil ),
877
+ paramBindingsBuf)
878
+ then
879
+ return call
867
880
868
- // Compute bindings for all parameters, appending them to bindingsBuf
869
- if ! computeParamBindings(inlinedMethod.info, callTypeArgs, callValueArgss, paramTypess(call, Nil )) then
870
- return call
881
+ paramBindingsBuf.toList
882
+ end paramBindings
871
883
872
884
// make sure prefix is executed if it is impure
873
- if ( ! isIdempotentExpr(inlineCallPrefix)) registerType(inlinedMethod.owner.thisType)
885
+ if ! isIdempotentExpr(inlineCallPrefix) then registerType(inlinedMethod.owner.thisType)
874
886
875
887
// Register types of all leaves of inlined body so that the `paramProxy` and `thisProxy` maps are defined.
876
888
rhsToInline.foreachSubTree(registerLeaf)
877
889
878
890
// Compute bindings for all this-proxies, appending them to bindingsBuf
879
891
computeThisBindings()
880
892
893
+ // Parameter bindings come after this bindings, reflecting order of evaluation
894
+ bindingsBuf ++= paramBindings
895
+
881
896
val inlineTyper = new InlineTyper (ctx.reporter.errorCount)
882
897
883
898
val inlineCtx = inlineContext(call).fresh.setTyper(inlineTyper).setNewScope
@@ -1190,7 +1205,7 @@ class Inliner(call: tpd.Tree, rhsToInline: tpd.Tree)(using Context) {
1190
1205
private object InlineableArg {
1191
1206
lazy val paramProxies = paramProxy.values.toSet
1192
1207
def unapply (tree : Trees .Ident [? ])(using Context ): Option [Tree ] = {
1193
- def search (buf : mutable. ListBuffer [ ValOrDefDef ] ) = buf.find(_.name == tree.name)
1208
+ def search (buf : DefBuffer ) = buf.find(_.name == tree.name)
1194
1209
if (paramProxies.contains(tree.typeOpt))
1195
1210
search(bindingsBuf) match {
1196
1211
case Some (bind : ValOrDefDef ) if bind.symbol.is(Inline ) =>
@@ -1229,7 +1244,7 @@ class Inliner(call: tpd.Tree, rhsToInline: tpd.Tree)(using Context) {
1229
1244
cpy.Inlined (cl)(call, bindings, recur(expr))
1230
1245
case _ => ddef.tpe.widen match
1231
1246
case mt : MethodType if ddef.paramss.head.length == args.length =>
1232
- val bindingsBuf = new mutable. ListBuffer [ ValOrDefDef ]
1247
+ val bindingsBuf = new DefBuffer
1233
1248
val argSyms = mt.paramNames.lazyZip(mt.paramInfos).lazyZip(args).map { (name, paramtp, arg) =>
1234
1249
arg.tpe.dealias match {
1235
1250
case ref @ TermRef (NoPrefix , _) => ref.symbol
0 commit comments