Skip to content

Commit 8c7c7c8

Browse files
committed
Attempted fix for nested and parameter inlines generate wrong line number
1 parent 784403f commit 8c7c7c8

File tree

2 files changed

+56
-25
lines changed

2 files changed

+56
-25
lines changed

compiler/src/dotty/tools/backend/jvm/BCodeSkelBuilder.scala

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@ package backend
33
package jvm
44

55
import scala.language.unsafeNulls
6-
76
import scala.annotation.tailrec
87

98
import scala.collection.{ mutable, immutable }
@@ -25,6 +24,7 @@ import dotty.tools.dotc.report
2524
import dotty.tools.dotc.transform.SymUtils._
2625

2726
import InlinedSourceMaps._
27+
import dotty.tools.dotc.inlines.Inlines.InliningPosition
2828

2929
/*
3030
*
@@ -586,8 +586,16 @@ trait BCodeSkelBuilder extends BCodeHelpers {
586586

587587
if (!emitLines || !tree.span.exists) return;
588588
if tree.source != cunit.source then
589-
sourceMap.lineFor(tree.sourcePos, lastRealLineNr) match
590-
case Some(nr) => emitNr(nr)
589+
tree.getAttachment(InliningPosition) match
590+
case Some(pos) =>
591+
val sourcePosition = pos.targetPos.find(p => p._1.source == cunit.source)
592+
if sourcePosition.nonEmpty then
593+
val offset = sourcePosition.get._1.span.point
594+
lastRealLineNr = ctx.source.offsetToLine(offset) + 1
595+
case None => ()
596+
sourceMap.lineFor(tree.sourcePos, lastRealLineNr, tree.getAttachment(InliningPosition)) match
597+
case Some(nr) =>
598+
emitNr(nr)
591599
case None => ()
592600
else
593601
val nr = ctx.source.offsetToLine(tree.span.point) + 1

compiler/src/dotty/tools/backend/jvm/InlinedSourceMaps.scala

Lines changed: 45 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -81,43 +81,53 @@ object InlinedSourceMaps:
8181
b ++= "*E\n"
8282
end Stratum
8383

84+
//targetPos is the position of the inlined call inlined(5)
85+
//origPos is the position of the inlined code inline def inlined(arg) { ... }
8486
def sourceMapFor(cunit: CompilationUnit)(internalNameProvider: Symbol => String)(using Context): InlinedSourceMap =
8587
val requests = mutable.ListBuffer.empty[(SourcePosition, SourcePosition)]
8688
var internalNames = Map.empty[SourceFile, String]
8789

8890
class RequestCollector(enclosingFile: SourceFile) extends TreeTraverser:
8991
override def traverse(tree: Tree)(using Context): Unit =
90-
if tree.source != enclosingFile && tree.source != cunit.source then
92+
if tree.hasAttachment(InliningPosition) then
9193
tree.getAttachment(InliningPosition) match
92-
case Some(InliningPosition(targetPos, cls)) =>
93-
requests += (targetPos -> tree.sourcePos)
94-
95-
cls match
96-
case Some(symbol) if !internalNames.isDefinedAt(tree.source) =>
97-
internalNames += (tree.source -> internalNameProvider(symbol))
98-
// We are skipping any internal name info if we already have one stored in our map
99-
// because a debugger will use internal name only to localize matching source.
100-
// Both old and new internal names are associated with the same source file
101-
// so it doesn't matter if internal name is not matching used symbol.
102-
case _ => ()
103-
RequestCollector(tree.source).traverseChildren(tree)
94+
case Some(InliningPosition(l)) =>
95+
l.foreach {
96+
(targetPos, cls) =>
97+
if tree.source != enclosingFile && tree.source != cunit.source then
98+
requests += (targetPos -> tree.sourcePos)
99+
100+
cls match
101+
case Some(symbol) if !internalNames.isDefinedAt(tree.source) =>
102+
internalNames += (tree.source -> internalNameProvider(symbol))
103+
// We are skipping any internal name info if we already have one stored in our map
104+
// because a debugger will use internal name only to localize matching source.
105+
// Both old and new internal names are associated with the same source file
106+
// so it doesn't matter if internal name is not matching used symbol.
107+
case _ => ()
108+
}
109+
traverseChildren(tree)
104110
case None =>
105111
// Not exactly sure in which cases it is happening. Should we report warning?
106-
RequestCollector(tree.source).traverseChildren(tree)
107-
else traverseChildren(tree)
112+
traverseChildren(tree)
113+
else
114+
traverseChildren(tree)
108115
end RequestCollector
109116

110117
// Don't generate mappings for the quotes compiled at runtime by the staging compiler
111118
if cunit.source.file.isVirtual then InlinedSourceMap(cunit, Nil, Map.empty[SourceFile, String])
112119
else
113120
var lastLine = cunit.tpdTree.sourcePos.endLine
121+
// returns the first fake line (starting from 0)
114122
def allocate(origPos: SourcePosition): Int =
115123
val line = lastLine + 1
116124
lastLine += origPos.lines.length
117125
line
118126

119127
RequestCollector(cunit.source).traverse(cunit.tpdTree)
120-
val allocated = requests.sortBy(_._1.start).map(r => Request(r._1, r._2, allocate(r._2)))
128+
129+
val allocated = requests.map(r => Request(r._1, r._2, allocate(r._2)))
130+
121131
InlinedSourceMap(cunit, allocated.toList, internalNames)
122132
end sourceMapFor
123133

@@ -153,13 +163,26 @@ object InlinedSourceMaps:
153163
b.toString
154164
}
155165

156-
def lineFor(sourcePos: SourcePosition, lastRealNr: Int): Option[Int] =
157-
requests.find(r => r.origPos.contains(sourcePos) && r.targetPos.endLine + 1 >= lastRealNr) match
166+
var lastNestedInlineLine = -1
167+
168+
def lineFor(sourcePos: SourcePosition, lastRealNr: Int, attachement: Option[InliningPosition]): Option[Int] =
169+
170+
if attachement.isDefined then
171+
attachement.get.targetPos.find(p => p._1.source == sourcePos.source) match
172+
case Some((pos, _)) =>
173+
lastNestedInlineLine = pos.startLine
174+
case None => ()
175+
176+
requests.find(r =>
177+
r.origPos.contains(sourcePos) &&
178+
(if r.targetPos.source == cunit.source then r.targetPos.endLine + 1 >= lastRealNr
179+
else r.targetPos.startLine >= lastNestedInlineLine
180+
)
181+
) match
158182
case Some(request) =>
159183
val offset = sourcePos.startLine - request.origPos.startLine
160-
Some(request.firstFakeLine + offset + 1)
184+
val virtualLine = request.firstFakeLine + offset
185+
Some(virtualLine + 1) // + 1 because the first line is 1 in the LineNumberTable
161186
case None =>
162187
// report.warning(s"${sourcePos.show} was inlined in ${cunit.source} but its inlining position was not recorded.")
163-
None
164-
165-
188+
None

0 commit comments

Comments
 (0)