-
Notifications
You must be signed in to change notification settings - Fork 1.1k
Fix lifting of arguments with -coverage-out #15530
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
Conversation
9362f57 to
8d2f6c0
Compare
smarter
left a comment
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 |
smarter
left a comment
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:
LiftCoverageextendedLiftComplex, it now extendsLiftImpureand forces the lifting of non-erased applicationsStringContext.s, f, raware now excluded from liftingElimRepeateddidn't handle lifted arguments properly, because it assumed that every argument was aTypedtree, 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 😄
InstrumentCoveragemodifies the AST just after the pickling, and insert calls toscala.runtime.coverage.Invoker.invokedthat record, at runtime, which methods are called.See an example here. To lift functions' arguments, it uses
LiftCoverage, which lives with itsLiftXXsiblings inEtaExpansion.scala.LiftCoveragepreviously extendedLiftComplex. A quick look at the definition ofLiftComplextells me that it lifts everything, except trees that are constants or have the maximal purityPurePath. AndTreeInfo.exprPuritysays that erased things arePure, notPurePath! It seems thatLiftImpurewould 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.noLiftmust returnfalsefor all non-erasedApply:Similarly, string interpolators
s,fandrawshouldn'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-allreported 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
ElimRepeatedis the phase that takes care of handling varargs. Some debugging showed thatElimRepeated.transformApplywas triggered, with:isWildcardStarArg(arg): trueargof typeIdentisWildcardStarArgproperly handledIdent, but notElimRepeated, which assumed that everything was aTypedtree. Fixing that made the bug vanish.