-
Notifications
You must be signed in to change notification settings - Fork 1.1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Fix lifting of arguments with -coverage-out #15530
Conversation
9362f57
to
8d2f6c0
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Otherwise LGTM!
compiler/src/dotty/tools/dotc/transform/InstrumentCoverage.scala
Outdated
Show resolved
Hide resolved
compiler/src/dotty/tools/dotc/transform/InstrumentCoverage.scala
Outdated
Show resolved
Hide resolved
8d2f6c0
to
22eaebb
Compare
Looks like the ci is failing with a coverage test check file mismatch |
Ah yes, it must be because of #15504. I'll update the checkfiles |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM! If you have the time, I think this is something that would be worth backporting to the release-3.2.0 branch too (and #15504 too presumably?)
Fixes #15078, fixes #15487, fixes #15505
Summary:
LiftCoverage
extendedLiftComplex
, it now extendsLiftImpure
and forces the lifting of non-erased applicationsStringContext.s, f, raw
are now excluded from liftingElimRepeated
didn't handle lifted arguments properly, because it assumed that every argument was aTyped
tree, which is not the case for arguments lifted by the coverage transformation. This is now fixed.Most of the added lines are tests :)
How I fixed it
Let's see if I can imitate the awesome explanations of Martin 😄
InstrumentCoverage
modifies the AST just after the pickling, and insert calls toscala.runtime.coverage.Invoker.invoked
that record, at runtime, which methods are called.See an example here. To lift functions' arguments, it uses
LiftCoverage
, which lives with itsLiftXX
siblings inEtaExpansion.scala
.LiftCoverage
previously extendedLiftComplex
. A quick look at the definition ofLiftComplex
tells me that it lifts everything, except trees that are constants or have the maximal purityPurePath
. AndTreeInfo.exprPurity
says that erased things arePure
, notPurePath
! It seems thatLiftImpure
would be more appropriate thanLiftComplex
. Therefore, I happily typeLiftCoverage extends LiftImpure
. But stopping there would introduce another bug!For example, given this code:
We want to generate something like this, even if g has no side effects:
This way, f will throw its exception and prevent g from being marked as covered, which would be wrong.
Therefore, all non-erased applications must be lifted. This means that, when lifting arguments,
LiftCoverage.noLift
must returnfalse
for all non-erasedApply
:Similarly, string interpolators
s
,f
andraw
shouldn't be lifted. I've excluded those three functions from lifting inInstrumentCoverage.needsLift
.Finally, I took a look at the mysterious issue #15078.
For a call to this java method:
-Ycheck-all
reported the following problem:And the code crashed at runtime...
Yet again, it only happened when the arguments were lifted by
-coverage-out
. A quick minimization revealed that the problem was the handling of the java varargs, in the presence of lifted arguments.I know that
ElimRepeated
is the phase that takes care of handling varargs. Some debugging showed thatElimRepeated.transformApply
was triggered, with:isWildcardStarArg(arg)
: truearg
of typeIdent
isWildcardStarArg
properly handledIdent
, but notElimRepeated
, which assumed that everything was aTyped
tree. Fixing that made the bug vanish.