Skip to content

Emit inline errors at expansion site #7684

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

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 7 additions & 6 deletions compiler/src/dotty/tools/dotc/reporting/MessageRendering.scala
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ trait MessageRendering {
*/
def outer(pos: SourcePosition, prefix: String)(implicit ctx: Context): List[String] =
if (pos.outer.exists)
i"$prefix| This location is in code that was inlined at ${pos.outer}" ::
i"$prefix| This location contains code that was inlined from $pos" ::
outer(pos.outer, prefix)
else Nil

Expand Down Expand Up @@ -114,9 +114,9 @@ trait MessageRendering {
*/
def posStr(pos: SourcePosition, diagnosticLevel: String, message: Message)(implicit ctx: Context): String =
if (pos.exists) hl(diagnosticLevel)({
val pos1 = pos.nonInlined
val file =
if (pos.source.file.exists) s"${pos.source.file.toString}:${pos.line + 1}:${pos.column}"
else s"${pos.source.file.toString}: offset ${pos.start} (missing source file)"
s"${pos1.source.file.toString}:${pos1.line + 1}:${pos1.column}"
val errId =
if (message.errorId ne ErrorMessageID.NoExplanationID) {
val errorNumber = message.errorId.errorNumber
Expand Down Expand Up @@ -149,9 +149,10 @@ trait MessageRendering {
val posString = posStr(pos, diagnosticLevel, msg)
if (posString.nonEmpty) sb.append(posString).append(EOL)
if (pos.exists && pos.source.file.exists) {
val (srcBefore, srcAfter, offset) = sourceLines(pos, diagnosticLevel)
val marker = columnMarker(pos, offset, diagnosticLevel)
val err = errorMsg(pos, msg.msg, offset)
val pos1 = pos.nonInlined
val (srcBefore, srcAfter, offset) = sourceLines(pos1, diagnosticLevel)
val marker = columnMarker(pos1, offset, diagnosticLevel)
val err = errorMsg(pos1, msg.msg, offset)
sb.append((srcBefore ::: marker :: err :: outer(pos, " " * (offset - 1)) ::: srcAfter).mkString(EOL))
}
else sb.append(msg.msg)
Expand Down
12 changes: 11 additions & 1 deletion compiler/src/dotty/tools/dotc/util/SourcePosition.scala
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,17 @@ extends interfaces.SourcePosition with Showable {
def outermost: SourcePosition =
if outer == null || outer == NoSourcePosition then this else outer.outermost

/** Inner most position that is contained within the `outermost` position.
* Most precise position that that comes from the call site.
*/
def nonInlined: SourcePosition = {
val om = outermost
def rec(self: SourcePosition): SourcePosition =
if om.contains(self) then self else rec(self.outer)
rec(this)
}


override def toString: String =
s"${if (source.exists) source.file.toString else "(no source)"}:$span"

Expand All @@ -75,4 +86,3 @@ extends interfaces.SourcePosition with Showable {
override def toString: String = "?"
override def withOuter(outer: SourcePosition): SourcePosition = outer
}

9 changes: 5 additions & 4 deletions compiler/test/dotty/tools/vulpix/ParallelTesting.scala
Original file line number Diff line number Diff line change
Expand Up @@ -679,11 +679,12 @@ trait ParallelTesting extends RunnerOrchestration { self =>
}

def getMissingExpectedErrors(errorMap: HashMap[String, Integer], reporterErrors: Iterator[MessageContainer]) = !reporterErrors.forall { error =>
val key = if (error.pos.exists) {
val pos1 = error.pos.nonInlined
val key = if (pos1.exists) {
def toRelative(path: String): String = // For some reason, absolute paths leak from the compiler itself...
path.split("/").dropWhile(_ != "tests").mkString("/")
val fileName = toRelative(error.pos.source.file.toString)
s"$fileName:${error.pos.line}"
val fileName = toRelative(pos1.source.file.toString)
s"$fileName:${pos1.line}"

} else "nopos"

Expand All @@ -695,7 +696,7 @@ trait ParallelTesting extends RunnerOrchestration { self =>
true
}
else {
echo(s"Error reported in ${error.pos.source}, but no annotation found")
echo(s"Error reported in ${pos1.source}, but no annotation found")
false
}
}
Expand Down
2 changes: 1 addition & 1 deletion project/scripts/cmdTests
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ cp tests/neg/i6371/B_2.scala $OUT/B.scala
"$SBT" "dotc $OUT/A.scala -d $OUT1"
rm $OUT/A.scala
"$SBT" "dotc -classpath $OUT1 -d $OUT1 $OUT/B.scala" > "$tmp" 2>&1 || echo "ok"
grep -qe "A.scala: offset 63 (missing source file)" "$tmp"
grep -qe "B.scala:2:7" "$tmp"


## Disabled because of flakeyness, should be changed to not depend on sbt
Expand Down
2 changes: 1 addition & 1 deletion tests/neg-macros/delegate-match-1.check
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,4 @@
| ^
| AmbiguousImplicits
| both value a1 in class Test1 and value a2 in class Test1 match type A
| This location is in code that was inlined at Test_2.scala:6
| This location contains code that was inlined from Test_2.scala:6
2 changes: 1 addition & 1 deletion tests/neg-macros/delegate-match-2.check
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,4 @@
| ^
| DivergingImplicit
| method a1 in class Test produces a diverging implicit search when trying to match type A
| This location is in code that was inlined at Test_2.scala:5
| This location contains code that was inlined from Test_2.scala:5
2 changes: 1 addition & 1 deletion tests/neg-macros/delegate-match-3.check
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,4 @@
| ^
| NoMatchingImplicits
| no implicit values were found that match type A
| This location is in code that was inlined at Test_2.scala:3
| This location contains code that was inlined from Test_2.scala:3
6 changes: 3 additions & 3 deletions tests/neg-macros/i6432.check
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,14 @@
4 | foo"abc${"123"}xyz${"456"}fgh" // error // error // error
| ^^^
| abc
| This location is in code that was inlined at Test_2.scala:4
| This location contains code that was inlined from Test_2.scala:4
-- Error: tests/neg-macros/i6432/Test_2.scala:4:17 ---------------------------------------------------------------------
4 | foo"abc${"123"}xyz${"456"}fgh" // error // error // error
| ^^^
| xyz
| This location is in code that was inlined at Test_2.scala:4
| This location contains code that was inlined from Test_2.scala:4
-- Error: tests/neg-macros/i6432/Test_2.scala:4:28 ---------------------------------------------------------------------
4 | foo"abc${"123"}xyz${"456"}fgh" // error // error // error
| ^^^
| fgh
| This location is in code that was inlined at Test_2.scala:4
| This location contains code that was inlined from Test_2.scala:4
6 changes: 3 additions & 3 deletions tests/neg-macros/i6432b.check
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,14 @@
4 | foo"""abc${"123"}xyz${"456"}fgh""" // error // error // error
| ^^^
| abc
| This location is in code that was inlined at Test_2.scala:4
| This location contains code that was inlined from Test_2.scala:4
-- Error: tests/neg-macros/i6432b/Test_2.scala:4:19 --------------------------------------------------------------------
4 | foo"""abc${"123"}xyz${"456"}fgh""" // error // error // error
| ^^^
| xyz
| This location is in code that was inlined at Test_2.scala:4
| This location contains code that was inlined from Test_2.scala:4
-- Error: tests/neg-macros/i6432b/Test_2.scala:4:30 --------------------------------------------------------------------
4 | foo"""abc${"123"}xyz${"456"}fgh""" // error // error // error
| ^^^
| fgh
| This location is in code that was inlined at Test_2.scala:4
| This location contains code that was inlined from Test_2.scala:4
2 changes: 1 addition & 1 deletion tests/neg-macros/i6976.check
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,4 @@
| scala.MatchError: Inlined(EmptyTree,List(),Literal(Constant(2))) (of class dotty.tools.dotc.ast.Trees$Inlined)
| at playground.macros$.mcrImpl(Macro_1.scala:12)
|
| This location is in code that was inlined at Test_2.scala:5
| This location contains code that was inlined from Test_2.scala:5
2 changes: 1 addition & 1 deletion tests/neg-macros/macro-class-not-found-1.check
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,4 @@
| java.lang.NoClassDefFoundError
| at Foo$.aMacroImplementation(Foo.scala:8)
|
| This location is in code that was inlined at Bar.scala:4
| This location contains code that was inlined from Bar.scala:4
2 changes: 1 addition & 1 deletion tests/neg-macros/macro-class-not-found-2.check
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,4 @@
| java.lang.NoClassDefFoundError: this.is.not.a.Class
| at Foo$.aMacroImplementation(Foo.scala:8)
|
| This location is in code that was inlined at Bar.scala:4
| This location contains code that was inlined from Bar.scala:4
4 changes: 2 additions & 2 deletions tests/neg-macros/macros-in-same-project-2.scala
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,9 @@ import scala.quoted._

object Bar {

myMacro()
myMacro() // error

inline def myMacro(): Unit = myMacro2() // error
inline def myMacro(): Unit = myMacro2()
inline def myMacro2(): Unit = ${ aMacroImplementation }

def aMacroImplementation(given QuoteContext): Expr[Unit] = '{}
Expand Down
2 changes: 1 addition & 1 deletion tests/neg-macros/macros-in-same-project-6.check
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,4 @@
4 | Foo.myMacro() // error
| ^^^^^^^^^^^^^
| some error
| This location is in code that was inlined at Bar.scala:4
| This location contains code that was inlined from Bar.scala:4
20 changes: 9 additions & 11 deletions tests/neg/cannot-reduce-inline-match.check
Original file line number Diff line number Diff line change
@@ -1,11 +1,9 @@
-- Error: tests/neg/cannot-reduce-inline-match.scala:3:13 --------------------------------------------------------------
3 | inline x match { // error
| ^
| cannot reduce inline match with
| scrutinee: {
| "f"
| } : String("f")
| patterns : case _:Int
| This location is in code that was inlined at cannot-reduce-inline-match.scala:9
4 | case _: Int =>
5 | }
-- Error: tests/neg/cannot-reduce-inline-match.scala:9:5 ---------------------------------------------------------------
9 | foo("f") // error
| ^^^^^^^^
| cannot reduce inline match with
| scrutinee: {
| "f"
| } : String("f")
| patterns : case _:Int
| This location contains code that was inlined from cannot-reduce-inline-match.scala:3
4 changes: 2 additions & 2 deletions tests/neg/cannot-reduce-inline-match.scala
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
object Test {
inline def foo[T](x: T) =
inline x match { // error
inline x match {
case _: Int =>
}

foo(4)

foo("f")
foo("f") // error

}
4 changes: 2 additions & 2 deletions tests/neg/cannot-reduce-summonFrom.scala
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
object Test {

inline def bar() =
compiletime.summonFrom { // error
compiletime.summonFrom {
case _: Int =>
}

Expand All @@ -10,5 +10,5 @@ object Test {
bar()
}

bar()
bar() // error
}
2 changes: 1 addition & 1 deletion tests/neg/i6371/A_1.scala
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
object A {
inline def foo(a: Any): Unit = a match {
case _: Int => // error
case _: Int =>
case _ =>
}
}
2 changes: 1 addition & 1 deletion tests/neg/i6371/B_2.scala
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
object B {
A.foo("aa")
A.foo("aa") // error
}
4 changes: 2 additions & 2 deletions tests/neg/i7618.scala
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ enum Exp {
object Compiler {
import Exp._

inline def compile(e: Exp, env: Map[String, Expr[Int]])(given ctx: QuoteContext): Expr[Int] = inline e match { // error
inline def compile(e: Exp, env: Map[String, Expr[Int]])(given ctx: QuoteContext): Expr[Int] = inline e match {
case Num(n) =>
Expr(n)
case Plus(e1, e2) =>
Expand All @@ -31,6 +31,6 @@ object Example {
val exp = Plus(Plus(Num(2), Var("x")), Num(4))
val letExp = Let("x", Num(3), exp)

Compiler.compile(letExp, Map.empty)(given QuoteContext.macroContext) // error
Compiler.compile(letExp, Map.empty)(given QuoteContext.macroContext) // error // error
}
}
4 changes: 2 additions & 2 deletions tests/neg/i7618b.scala
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ enum Exp {
object Compiler {
import Exp._

inline def compile(e: Exp, env: Map[String, Expr[Int]])(given ctx: QuoteContext): Expr[Int] = inline e match { // error
inline def compile(e: Exp, env: Map[String, Expr[Int]])(given ctx: QuoteContext): Expr[Int] = inline e match {
case Num(n) =>
Expr(n)
case Plus(e1, e2) =>
Expand All @@ -31,6 +31,6 @@ object Example {
val exp = Plus(Plus(Num(2), Var("x")), Num(4))
val letExp = Let("x", Num(3), exp)

Compiler.compile(letExp, Map.empty)(given (??? : QuoteContext))
Compiler.compile(letExp, Map.empty)(given (??? : QuoteContext)) // error
}
}
9 changes: 9 additions & 0 deletions tests/neg/inline-error-pos.check
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
-- Error: tests/neg/inline-error-pos.scala:8:13 ------------------------------------------------------------------------
8 | val b = foo(2) // error
| ^^^^^^
| cannot reduce inline match with
| scrutinee: {
| 2
| } : Int(2)
| patterns : case 1
| This location contains code that was inlined from inline-error-pos.scala:3
9 changes: 9 additions & 0 deletions tests/neg/inline-error-pos.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@

inline def foo(x: Int): Int =
inline x match
case 1 => 9

object Foo {
val a = foo(1)
val b = foo(2) // error
}
2 changes: 1 addition & 1 deletion tests/neg/inlineAccess/C_1.scala
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ package p
private class D
class C {
inline def inl(): Unit = {
val d = new D() // error (when inlined): not accessible
val d = new D()
}
}

2 changes: 1 addition & 1 deletion tests/neg/inlineAccess/Test_2.scala
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,6 @@
object Test {
def main(args: Array[String]) = {
val c = new p.C()
c.inl()
c.inl() // error (when inlined): not accessible
}
}
4 changes: 2 additions & 2 deletions tests/neg/summonFrom-ambiguous-bind.scala
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ object `implicit-match-ambiguous-bind` {
implicit val ibox: Box[Int] = Box(0)
implicit val sbox: Box[String] = Box("")
inline def unbox = compiletime.summonFrom {
case b: Box[t] => b.value // error
case b: Box[t] => b.value
}
val unboxed = unbox
val unboxed = unbox // error
}
4 changes: 2 additions & 2 deletions tests/neg/summonFrom-ambiguous.scala
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@ object Test {
implicit val a2: A = new A

inline def f: Any = compiletime.summonFrom {
case _: A => ??? // error: ambiguous implicits
case _: A => ???
}

f
f // error: ambiguous implicits
}