From 4df32fc167dfca6d78b06da7e35418f1906d3e08 Mon Sep 17 00:00:00 2001 From: Kacper Korban Date: Tue, 29 Aug 2023 14:23:06 +0200 Subject: [PATCH] Coverage: Do not lift applications of context functions closes lampepfl#16502 [Cherry-picked 3e7dae83eb61cc0b3b3823bd372ac38ecbb49b36] --- .../dotc/transform/InstrumentCoverage.scala | 15 +++- tests/coverage/pos/i16502.scala | 8 ++ tests/coverage/pos/i16502.scoverage.check | 88 +++++++++++++++++++ 3 files changed, 109 insertions(+), 2 deletions(-) create mode 100644 tests/coverage/pos/i16502.scala create mode 100644 tests/coverage/pos/i16502.scoverage.check diff --git a/compiler/src/dotty/tools/dotc/transform/InstrumentCoverage.scala b/compiler/src/dotty/tools/dotc/transform/InstrumentCoverage.scala index 104c73b6c466..4adbe1313cd7 100644 --- a/compiler/src/dotty/tools/dotc/transform/InstrumentCoverage.scala +++ b/compiler/src/dotty/tools/dotc/transform/InstrumentCoverage.scala @@ -452,8 +452,13 @@ class InstrumentCoverage extends MacroTransform with IdentityDenotTransformer: * they shouldn't be lifted. */ val sym = fun.symbol - sym.exists && (isShortCircuitedOp(sym) || StringInterpolatorOpt.isCompilerIntrinsic(sym) || sym == defn.Object_synchronized) - end + sym.exists && ( + isShortCircuitedOp(sym) + || StringInterpolatorOpt.isCompilerIntrinsic(sym) + || sym == defn.Object_synchronized + || isContextFunctionApply(fun) + ) + end isUnliftableFun val fun = tree.fun val nestedApplyNeedsLift = fun match @@ -463,6 +468,12 @@ class InstrumentCoverage extends MacroTransform with IdentityDenotTransformer: nestedApplyNeedsLift || !isUnliftableFun(fun) && !tree.args.isEmpty && !tree.args.forall(LiftCoverage.noLift) + private def isContextFunctionApply(fun: Tree)(using Context): Boolean = + fun match + case Select(prefix, nme.apply) => + defn.isContextFunctionType(prefix.tpe.widen) + case _ => false + /** Check if an Apply can be instrumented. Prevents this phase from generating incorrect code. */ private def canInstrumentApply(tree: Apply)(using Context): Boolean = def isSecondaryCtorDelegateCall: Boolean = tree.fun match diff --git a/tests/coverage/pos/i16502.scala b/tests/coverage/pos/i16502.scala new file mode 100644 index 000000000000..bd7847138c3f --- /dev/null +++ b/tests/coverage/pos/i16502.scala @@ -0,0 +1,8 @@ +import scala.concurrent.* + +def asyncSum: ExecutionContext ?=> Future[Int] = Future(1) + +@main +def Test(): Unit = + import scala.concurrent.ExecutionContext.Implicits.global + asyncSum diff --git a/tests/coverage/pos/i16502.scoverage.check b/tests/coverage/pos/i16502.scoverage.check new file mode 100644 index 000000000000..febd55de39b5 --- /dev/null +++ b/tests/coverage/pos/i16502.scoverage.check @@ -0,0 +1,88 @@ +# Coverage data, format version: 3.0 +# Statement data: +# - id +# - source path +# - package name +# - class name +# - class type (Class, Object or Trait) +# - full class name +# - method name +# - start offset +# - end offset +# - line number +# - symbol name +# - tree name +# - is branch +# - invocations count +# - is ignored +# - description (can be multi-line) +# ' ' sign +# ------------------------------------------ +0 +i16502.scala + +i16502$package$ +Object +.i16502$package$ +$anonfun +76 +85 +2 +apply +Apply +false +0 +false +Future(1) + +1 +i16502.scala + +i16502$package$ +Object +.i16502$package$ +asyncSum +27 +39 +2 +asyncSum +DefDef +false +0 +false +def asyncSum + +2 +i16502.scala + +i16502$package$ +Object +.i16502$package$ +Test +174 +182 +7 +apply +Apply +false +0 +false +asyncSum + +3 +i16502.scala + +i16502$package$ +Object +.i16502$package$ +Test +87 +101 +5 +Test +DefDef +false +0 +false +@main\ndef Test +