Skip to content

Commit 96bf85e

Browse files
committed
Show inlined positions with source code
This gives more context to the users on what happen and where the code came from.
1 parent 0a834ff commit 96bf85e

27 files changed

+196
-70
lines changed

compiler/src/dotty/tools/dotc/reporting/MessageRendering.scala

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -25,15 +25,9 @@ trait MessageRendering {
2525
def stripColor(str: String): String =
2626
str.replaceAll("\u001b\\[.*?m", "")
2727

28-
/** When inlining a method call, if there's an error we'd like to get the
29-
* outer context and the `pos` at which the call was inlined.
30-
*
31-
* @return a list of strings with inline locations
32-
*/
33-
def outer(pos: SourcePosition, prefix: String)(using Context): List[String] =
34-
if (pos.outer.exists)
35-
i"$prefix| This location contains code that was inlined from $pos" ::
36-
outer(pos.outer, prefix)
28+
/** List of all the inline calls that surround the position */
29+
def inlinePosStack(pos: SourcePosition): List[SourcePosition] =
30+
if pos.outer.exists then pos :: inlinePosStack(pos.outer)
3731
else Nil
3832

3933
/** Get the sourcelines before and after the position, as well as the offset
@@ -173,10 +167,17 @@ trait MessageRendering {
173167
if (pos.exists) {
174168
val pos1 = pos.nonInlined
175169
if (pos1.exists && pos1.source.file.exists) {
170+
// Print error message at inline position
176171
val (srcBefore, srcAfter, offset) = sourceLines(pos1, levelString)
177172
val marker = columnMarker(pos1, offset, levelString)
178173
val err = errorMsg(pos1, msg.message, offset)
179-
sb.append((srcBefore ::: marker :: err :: outer(pos, " " * (offset - 1)) ::: srcAfter).mkString(EOL))
174+
sb.append((srcBefore ::: marker :: err :: srcAfter).mkString(EOL))
175+
// print inline stack trace
176+
for inlinedPos <- inlinePosStack(pos) if inlinedPos != pos1 do
177+
val (srcBefore, srcAfter, offset) = sourceLines(inlinedPos, levelString)
178+
val marker = columnMarker(inlinedPos, offset, levelString)
179+
val prefix = " " * (offset - 1)
180+
sb.append((i"\nThis location contains code that was inlined from $pos" :: srcBefore ::: marker :: srcAfter).mkString(EOL))
180181
}
181182
else sb.append(msg.message)
182183
}

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ object Splicer {
4949
val oldContextClassLoader = Thread.currentThread().getContextClassLoader
5050
Thread.currentThread().setContextClassLoader(classLoader)
5151
try {
52-
val interpreter = new Interpreter(spliceExpansionPos, classLoader)
52+
val interpreter = new Interpreter(splicePos, classLoader)
5353

5454
// Some parts of the macro are evaluated during the unpickling performed in quotedExprToTree
5555
val interpretedExpr = interpreter.interpret[Quotes => scala.quoted.Expr[Any]](tree)

compiler/src/dotty/tools/dotc/typer/Inliner.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -853,7 +853,7 @@ class Inliner(call: tpd.Tree, rhsToInline: tpd.Tree)(using Context) {
853853
evidence.tpe match
854854
case fail: Implicits.SearchFailureType =>
855855
val msg = evTyper.missingArgMsg(evidence, tpt.tpe, "")
856-
errorTree(tpt, em"$msg")
856+
errorTree(call, em"$msg")
857857
case _ =>
858858
evidence
859859
return searchImplicit(callTypeArgs.head)

compiler/test-resources/repl/i9227

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,5 +3,4 @@ scala> import scala.quoted._; inline def myMacro[T]: Unit = ${ myMacroImpl[T] };
33
1 | import scala.quoted._; inline def myMacro[T]: Unit = ${ myMacroImpl[T] }; def myMacroImpl[T](using Quotes): Expr[Unit] = '{}; println(myMacro[Int])
44
| ^^^^^^^^^^^^
55
| Cannot call macro method myMacroImpl defined in the same source file
6-
| This location contains code that was inlined from rs$line$1:1
76
1 error found

tests/neg-macros/delegate-match-1.check

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,4 +4,3 @@
44
| ^
55
| AmbiguousImplicits
66
| both value a1 in class Test1 and value a2 in class Test1 match type A
7-
| This location contains code that was inlined from Test_2.scala:6

tests/neg-macros/delegate-match-2.check

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,4 +4,3 @@
44
| ^
55
| DivergingImplicit
66
| method a1 in class Test produces a diverging implicit search when trying to match type A
7-
| This location contains code that was inlined from Test_2.scala:5

tests/neg-macros/delegate-match-3.check

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,4 +4,3 @@
44
| ^
55
| NoMatchingImplicits
66
| no implicit values were found that match type A
7-
| This location contains code that was inlined from Test_2.scala:3

tests/neg-macros/i11386.check

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,13 @@
33
6 | dummy(0) // error
44
| ^
55
| test
6-
| This location contains code that was inlined from Test_2.scala:6
7-
| This location contains code that was inlined from Macro_1.scala:7
6+
This location contains code that was inlined from Test_2.scala:6
7+
7 | notNull(i)
8+
| ^^^^^^^^^^
89
-- Error: tests/neg-macros/i11386/Test_2.scala:8:20 --------------------------------------------------------------------
910
8 | dummy(int2String(0)) // error
1011
| ^^^^^^^^^^^^^
1112
| test
12-
| This location contains code that was inlined from Test_2.scala:8
13-
| This location contains code that was inlined from Macro_1.scala:7
13+
This location contains code that was inlined from Test_2.scala:8
14+
7 | notNull(i)
15+
| ^^^^^^^^^^

tests/neg-macros/i13991.check

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
2+
-- Error: tests/neg-macros/i13991/Test_2.scala:6:5 ---------------------------------------------------------------------
3+
6 | v2 // error
4+
| ^^
5+
| Error
6+
This location contains code that was inlined from Test_2.scala:3
7+
3 | inline def v2 = InlineMac.sample("foo")
8+
| ^^^^^
9+
This location contains code that was inlined from Test_2.scala:3
10+
3 | inline def v2 = InlineMac.sample("foo")
11+
| ^^^^^^^^^^^^^^^^^^^^^^^

tests/neg-macros/i13991/Macro_1.scala

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
import scala.quoted.*
2+
3+
object InlineMac:
4+
5+
inline def sample(inline expr: String): Int =
6+
${ sampleImpl('expr) }
7+
8+
def sampleImpl(expr: Expr[String])(using Quotes): Expr[Int] =
9+
import quotes.reflect.*
10+
report.errorAndAbort("Error", expr)

0 commit comments

Comments
 (0)