Skip to content

Commit 771a336

Browse files
Merge pull request #15504 from dotty-staging/coverage-inline-defs
Avoid instrumentation of inline and erased definitions
2 parents b34ad70 + 7206bfe commit 771a336

File tree

9 files changed

+351
-80
lines changed

9 files changed

+351
-80
lines changed

compiler/src/dotty/tools/dotc/transform/InstrumentCoverage.scala

Lines changed: 17 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -131,17 +131,22 @@ class InstrumentCoverage extends MacroTransform with IdentityDenotTransformer:
131131
cpy.ValDef(tree)(rhs = rhs)
132132

133133
case tree: DefDef =>
134-
// Only transform the params (for the default values) and the rhs.
135-
val paramss = transformParamss(tree.paramss)
136-
val rhs = transform(tree.rhs)
137-
val finalRhs =
138-
if canInstrumentDefDef(tree) then
139-
// Ensure that the rhs is always instrumented, if possible
140-
instrumentBody(tree, rhs)
141-
else
142-
rhs
143-
cpy.DefDef(tree)(tree.name, paramss, tree.tpt, finalRhs)
144-
134+
if tree.symbol.isOneOf(Inline | Erased) then
135+
// Inline and erased definitions will not be in the generated code and therefore do not need to be instrumented.
136+
// Note that a retained inline method will have a `$retained` variant that will be instrumented.
137+
tree
138+
else
139+
// Only transform the params (for the default values) and the rhs.
140+
val paramss = transformParamss(tree.paramss)
141+
val rhs = transform(tree.rhs)
142+
val finalRhs =
143+
if canInstrumentDefDef(tree) then
144+
// Ensure that the rhs is always instrumented, if possible
145+
instrumentBody(tree, rhs)
146+
else
147+
rhs
148+
cpy.DefDef(tree)(tree.name, paramss, tree.tpt, finalRhs)
149+
end if
145150
case tree: PackageDef =>
146151
// only transform the statements of the package
147152
cpy.PackageDef(tree)(tree.pid, transform(tree.stats))
@@ -330,4 +335,4 @@ class InstrumentCoverage extends MacroTransform with IdentityDenotTransformer:
330335

331336
object InstrumentCoverage:
332337
val name: String = "instrumentCoverage"
333-
val description: String = "instrument code for coverage cheking"
338+
val description: String = "instrument code for coverage checking"

compiler/test/dotty/tools/dotc/coverage/CoverageTests.scala

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@ class CoverageTests:
5656
val expected = fixWindowsPaths(Files.readAllLines(expectFile).asScala)
5757
val obtained = fixWindowsPaths(Files.readAllLines(targetFile).asScala)
5858
if expected != obtained then
59+
// FIXME: zip will drop part of the output if one is shorter (i.e. will not print anything of one is a refix of the other)
5960
for ((exp, actual),i) <- expected.zip(obtained).filter(_ != _).zipWithIndex do
6061
Console.err.println(s"wrong line ${i+1}:")
6162
Console.err.println(s" expected: $exp")

tests/coverage/pos/Inlined.scoverage.check

Lines changed: 0 additions & 68 deletions
Original file line numberDiff line numberDiff line change
@@ -273,71 +273,3 @@ false
273273
false
274274
def testInlined
275275

276-
15
277-
Inlined.scala
278-
covtest
279-
Inlined$package$
280-
Object
281-
covtest.Inlined$package$
282-
assert
283-
288
284-
315
285-
10
286-
Scala3RunTime
287-
Select
288-
false
289-
0
290-
false
291-
scala.runtime.Scala3RunTime
292-
293-
16
294-
Inlined.scala
295-
covtest
296-
Inlined$package$
297-
Object
298-
covtest.Inlined$package$
299-
assert
300-
288
301-
330
302-
10
303-
assertFailed
304-
Apply
305-
false
306-
0
307-
false
308-
scala.runtime.Scala3RunTime.assertFailed()
309-
310-
17
311-
Inlined.scala
312-
covtest
313-
Inlined$package$
314-
Object
315-
covtest.Inlined$package$
316-
assert
317-
288
318-
330
319-
10
320-
<none>
321-
Block
322-
true
323-
0
324-
false
325-
scala.runtime.Scala3RunTime.assertFailed()
326-
327-
18
328-
Inlined.scala
329-
covtest
330-
Inlined$package$
331-
Object
332-
covtest.Inlined$package$
333-
assert
334-
202
335-
231
336-
9
337-
assert
338-
DefDef
339-
false
340-
0
341-
false
342-
transparent inline def assert
343-
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
foo
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
import scala.language.experimental.erasedDefinitions
2+
3+
class A:
4+
erased def x: String = "x".toString
5+
def foo(erased s: String): String = "foo"
6+
7+
@main
8+
def Test: Unit =
9+
val a = A()
10+
// FIXME: coverage should not track erased arguments and statements
11+
// a.x
12+
// println(a.foo(a.x))
13+
println("foo")
Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
# Coverage data, format version: 3.0
2+
# Statement data:
3+
# - id
4+
# - source path
5+
# - package name
6+
# - class name
7+
# - class type (Class, Object or Trait)
8+
# - full class name
9+
# - method name
10+
# - start offset
11+
# - end offset
12+
# - line number
13+
# - symbol name
14+
# - tree name
15+
# - is branch
16+
# - invocations count
17+
# - is ignored
18+
# - description (can be multi-line)
19+
# ' ' sign
20+
# ------------------------------------------
21+
0
22+
erased-def/test.scala
23+
<empty>
24+
A
25+
Class
26+
<empty>.A
27+
foo
28+
103
29+
110
30+
4
31+
foo
32+
DefDef
33+
false
34+
0
35+
false
36+
def foo
37+
38+
1
39+
erased-def/test.scala
40+
<empty>
41+
test$package$
42+
Object
43+
<empty>.test$package$
44+
Test
45+
179
46+
182
47+
8
48+
<init>
49+
Apply
50+
false
51+
0
52+
false
53+
A()
54+
55+
2
56+
erased-def/test.scala
57+
<empty>
58+
test$package$
59+
Object
60+
<empty>.test$package$
61+
Test
62+
289
63+
303
64+
12
65+
println
66+
Apply
67+
false
68+
0
69+
false
70+
println("foo")
71+
72+
3
73+
erased-def/test.scala
74+
<empty>
75+
test$package$
76+
Object
77+
<empty>.test$package$
78+
Test
79+
146
80+
160
81+
7
82+
Test
83+
DefDef
84+
false
85+
0
86+
false
87+
@main
88+
def Test
89+
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
1
2+
foo
3+
bar
4+
foo
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
abstract class B:
2+
val x: Int
3+
def foo: String
4+
5+
class A extends B:
6+
inline val x = 1
7+
inline val y = 2
8+
inline def foo: String = "foo".toString
9+
inline def bar: String = "bar".toString
10+
11+
@main
12+
def Test: Unit =
13+
val a = A()
14+
println(a.x)
15+
println(a.foo)
16+
println(a.bar)
17+
val b: B = a
18+
println(b.foo)

0 commit comments

Comments
 (0)