@@ -101,7 +101,24 @@ class InstrumentCoverage extends MacroTransform with IdentityDenotTransformer:
101101
102102 // (fun)[args]
103103 case TypeApply (fun, args) =>
104- cpy.TypeApply (tree)(transform(fun), args)
104+ val tfun = transform(fun)
105+ tfun match
106+ case InstrumentCoverage .InstrumentedBlock (invokeCall, expr) =>
107+ // expr[T] shouldn't be transformed to
108+ // {invoked(...), expr}[T]
109+ //
110+ // but to
111+ // {invoked(...), expr[T]}
112+ //
113+ // This is especially important for trees like (expr[T])(args),
114+ // for which the wrong transformation crashes the compiler.
115+ // See tests/coverage/pos/PolymorphicExtensions.scala
116+ Block (
117+ invokeCall :: Nil ,
118+ cpy.TypeApply (tree)(expr, args)
119+ )
120+ case _ =>
121+ cpy.TypeApply (tree)(tfun, args)
105122
106123 // a.b
107124 case Select (qual, name) =>
@@ -242,12 +259,12 @@ class InstrumentCoverage extends MacroTransform with IdentityDenotTransformer:
242259 val statementId = recordStatement(parent, pos, false )
243260 insertInvokeCall(body, pos, statementId)
244261
245- /** Returns the tree, prepended by a call to Invoker.invoker */
262+ /** Returns the tree, prepended by a call to Invoker.invoked */
246263 private def insertInvokeCall (tree : Tree , pos : SourcePosition , statementId : Int )(using Context ): Tree =
247264 val callSpan = syntheticSpan(pos)
248265 Block (invokeCall(statementId, callSpan) :: Nil , tree).withSpan(callSpan.union(tree.span))
249266
250- /** Generates Invoked .invoked(id, DIR) */
267+ /** Generates Invoker .invoked(id, DIR) */
251268 private def invokeCall (id : Int , span : Span )(using Context ): Tree =
252269 val outputPath = ctx.settings.coverageOutputDir.value
253270 ref(defn.InvokedMethodRef ).withSpan(span)
@@ -353,3 +370,15 @@ class InstrumentCoverage extends MacroTransform with IdentityDenotTransformer:
353370object InstrumentCoverage :
354371 val name : String = " instrumentCoverage"
355372 val description : String = " instrument code for coverage checking"
373+
374+ /** Extractor object for trees produced by `insertInvokeCall`. */
375+ object InstrumentedBlock :
376+ private def isInvokedCall (app : Apply )(using Context ): Boolean =
377+ app.span.isSynthetic && app.symbol == defn.InvokedMethodRef .symbol
378+
379+ def unapply (t : Tree )(using Context ): Option [(Apply , Tree )] =
380+ t match
381+ case Block ((app : Apply ) :: Nil , expr) if isInvokedCall(app) =>
382+ Some ((app, expr))
383+ case _ =>
384+ None
0 commit comments