@@ -158,35 +158,46 @@ class InlineReducer(inliner: Inliner)(using Context):
158158 *
159159 * where `def` is used for call-by-name parameters. However, we shortcut any NoPrefix
160160 * refs among the ei's directly without creating an intermediate binding.
161+ *
162+ * This variant of beta-reduction preserves the integrity of `Inlined` tree nodes.
161163 */
162164 def betaReduce (tree : Tree )(using Context ): Tree = tree match {
163- case Apply (Select (cl @ closureDef(ddef), nme.apply), args) if defn.isFunctionType(cl.tpe) =>
164- // closureDef also returns a result for closures wrapped in Inlined nodes.
165- // These need to be preserved.
166- def recur (cl : Tree ): Tree = cl match
167- case Inlined (call, bindings, expr) =>
168- cpy.Inlined (cl)(call, bindings, recur(expr))
169- case _ => ddef.tpe.widen match
170- case mt : MethodType if ddef.paramss.head.length == args.length =>
171- val bindingsBuf = new DefBuffer
172- val argSyms = mt.paramNames.lazyZip(mt.paramInfos).lazyZip(args).map { (name, paramtp, arg) =>
173- arg.tpe.dealias match {
174- case ref @ TermRef (NoPrefix , _) => ref.symbol
175- case _ =>
176- paramBindingDef(name, paramtp, arg, bindingsBuf)(
177- using ctx.withSource(cl.source)
178- ).symbol
165+ case Apply (Select (cl, nme.apply), args) if defn.isFunctionType(cl.tpe) =>
166+ val bindingsBuf = new DefBuffer
167+ def recur (cl : Tree ): Option [Tree ] = cl match
168+ case Block ((ddef : DefDef ) :: Nil , closure : Closure ) if ddef.symbol == closure.meth.symbol =>
169+ ddef.tpe.widen match
170+ case mt : MethodType if ddef.paramss.head.length == args.length =>
171+ val argSyms = mt.paramNames.lazyZip(mt.paramInfos).lazyZip(args).map { (name, paramtp, arg) =>
172+ arg.tpe.dealias match {
173+ case ref @ TermRef (NoPrefix , _) => ref.symbol
174+ case _ =>
175+ paramBindingDef(name, paramtp, arg, bindingsBuf)(
176+ using ctx.withSource(cl.source)
177+ ).symbol
178+ }
179179 }
180- }
181- val expander = new TreeTypeMap (
182- oldOwners = ddef.symbol :: Nil ,
183- newOwners = ctx.owner :: Nil ,
184- substFrom = ddef.paramss.head.map(_.symbol),
185- substTo = argSyms)
186- Block (bindingsBuf.toList, expander.transform(ddef.rhs)).withSpan(tree.span)
187- case _ => tree
188- recur(cl)
189- case _ => tree
180+ val expander = new TreeTypeMap (
181+ oldOwners = ddef.symbol :: Nil ,
182+ newOwners = ctx.owner :: Nil ,
183+ substFrom = ddef.paramss.head.map(_.symbol),
184+ substTo = argSyms)
185+ Some (expander.transform(ddef.rhs))
186+ case _ => None
187+ case Block (stats, expr) if stats.forall(isPureBinding) =>
188+ recur(expr).map(cpy.Block (cl)(stats, _))
189+ case Inlined (call, bindings, expr) if bindings.forall(isPureBinding) =>
190+ recur(expr).map(cpy.Inlined (cl)(call, bindings, _))
191+ case Typed (expr, tpt) =>
192+ recur(expr)
193+ case _ => None
194+ recur(cl) match
195+ case Some (reduced) =>
196+ Block (bindingsBuf.toList, reduced).withSpan(tree.span)
197+ case None =>
198+ tree
199+ case _ =>
200+ tree
190201 }
191202
192203 /** The result type of reducing a match. It consists optionally of a list of bindings
@@ -281,7 +292,7 @@ class InlineReducer(inliner: Inliner)(using Context):
281292 // Test case is pos-macros/i15971
282293 val tptBinds = getBinds(Set .empty[TypeSymbol ], tpt)
283294 val binds : Set [TypeSymbol ] = pat match {
284- case UnApply (TypeApply (_, tpts), _, _) =>
295+ case UnApply (TypeApply (_, tpts), _, _) =>
285296 getBinds(Set .empty[TypeSymbol ], tpts) ++ tptBinds
286297 case _ => tptBinds
287298 }
0 commit comments