Skip to content
Open
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
26 changes: 22 additions & 4 deletions compiler/src/dotty/tools/dotc/reporting/MessageRendering.scala
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,11 @@ trait MessageRendering {
import Highlight.*
import Offsets.*

/** The maximal number of lines of code that are shown in a message after the
* `^` and error message.
*/
private inline val maxRenderedLinesAfterPoint = 3

/** Remove ANSI coloring from `str`, useful for getting real length of
* strings
*
Expand Down Expand Up @@ -64,9 +69,21 @@ trait MessageRendering {
val lines = linesFrom(syntax)
val (before, after) = pos.beforeAndAfterPoint

def compress(offsetsAndLines: List[(Int, String)]): List[(Int, String)] =
if offsetsAndLines.isEmpty then offsetsAndLines
else
val compressedLines =
if offsetsAndLines.length > maxRenderedLinesAfterPoint then
offsetsAndLines.take(maxRenderedLinesAfterPoint - 2)
++ List(
(offsetsAndLines(maxRenderedLinesAfterPoint - 2)._1, "..."),
offsetsAndLines.last)
else offsetsAndLines
compressedLines

(
before.zip(lines).map(render),
after.zip(lines.drop(before.length)).map(render),
compress(after.zip(lines.drop(before.length))).map(render),
maxLen
)
}
Expand Down Expand Up @@ -140,7 +157,7 @@ trait MessageRendering {
*
* @return aligned error message
*/
private def errorMsg(pos: SourcePosition, msg: String)(using Context, Level, Offset): String = {
private def errorMsg(pos: SourcePosition, msg: String, addLine: Boolean)(using Context, Level, Offset): String = {
val padding = msg.linesIterator.foldLeft(pos.startColumnPadding) { (pad, line) =>
val lineLength = stripColor(line).length
val maxPad = math.max(0, ctx.settings.pageWidth.value - offset - lineLength) - offset
Expand All @@ -149,9 +166,10 @@ trait MessageRendering {
else pad
}

msg.linesIterator
val msgStr = msg.linesIterator
.map { line => offsetBox + (if line.isEmpty then "" else padding + line) }
.mkString(EOL)
if addLine then msgStr ++ s"${EOL}$offsetBox" else msgStr
}

// file.path or munge it to normalize for testing
Expand Down Expand Up @@ -280,7 +298,7 @@ trait MessageRendering {
if pos.exists && pos1.exists && pos1.source.file.exists then
val (srcBefore, srcAfter, offset) = sourceLines(pos1)
val marker = positionMarker(pos1)
val err = errorMsg(pos1, msg.message)
val err = errorMsg(pos1, msg.message, srcAfter.nonEmpty)
sb.append((srcBefore ::: marker :: err :: srcAfter).mkString(EOL))

if inlineStack.nonEmpty then
Expand Down
1 change: 1 addition & 0 deletions tests/neg-custom-args/captures/boundary-homebrew.check
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
|where: ?=> refers to a fresh root capability created in anonymous function of type (using l1²: boundary.Label[boundary.Label[Int]^]^): boundary.Label[Int]^ when checking argument to parameter body of method apply
| ^ refers to the universal root capability
| cap is a fresh root capability created in anonymous function of type (using l2: boundary.Label[Int]^'s2): Int of parameter parameter l2² of method $anonfun
|
20 | boundary.break(l2)(using l1)
21 | 15
|
Expand Down
2 changes: 2 additions & 0 deletions tests/neg-custom-args/captures/boundary.check
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
|
| where: ^ and cap refer to the universal root capability
| ^² refers to a fresh root capability classified as Control in the type of value local
|
6 | boundary[Unit]: l2 ?=>
7 | boundary.break(l2)(using l1) // error
8 | ???
Expand Down Expand Up @@ -47,6 +48,7 @@
|
| where: ^ and cap² refer to the universal root capability
| ^² and cap refer to a fresh root capability created in package <empty>
|
6 | boundary[Unit]: l2 ?=>
7 | boundary.break(l2)(using l1) // error
8 | ???
Expand Down
1 change: 1 addition & 0 deletions tests/neg-custom-args/captures/capt1.check
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@
| Required: A
|
| Note that capability x is not included in capture set {}.
|
28 | def m() = if x == null then y else y
|
| longer explanation available when compiling with `-explain`
Expand Down
2 changes: 2 additions & 0 deletions tests/neg-custom-args/captures/check-inferred.check
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
|
| Inferred type : () ->{Counter.this.count} Unit
| Externally visible type: () -> Unit
|
19 | count.put(count.get + 1)
-- Error: tests/neg-custom-args/captures/check-inferred.scala:20:13 ----------------------------------------------------
20 | val decr = () => // error
Expand All @@ -15,6 +16,7 @@
|
| Inferred type : () ->{Counter.this.count} Unit
| Externally visible type: () -> Unit
|
21 | count.put(count.get - 1)
-- Error: tests/neg-custom-args/captures/check-inferred.scala:24:14 ----------------------------------------------------
24 | val count = Ref(): Object^ // error // error
Expand Down
2 changes: 2 additions & 0 deletions tests/neg-custom-args/captures/class-caps.check
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
| Required: (Int, Int) -> Int
|
| Note that capability Test.this.console is not included in capture set {}.
|
19 | log(s"adding a ($a) to b ($b)")(using console)
20 | a + b
|
Expand All @@ -16,6 +17,7 @@
| Required: (Int, Int) -> Int
|
| Note that capability Test1.this.console is not included in capture set {}.
|
29 | log(s"adding a ($a) to b ($b)")(using console)
30 | a + b
|
Expand Down
3 changes: 3 additions & 0 deletions tests/neg-custom-args/captures/classifiers-secondclass.check
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
|Note that capability f.write is not included in capture set {cap.only[Read]}.
|
|where: cap is a fresh root capability created in anonymous function of type (f²: Levels.File^): Unit when checking argument to parameter op of method parReduce
|
42 | f.write(42) // the error stems from here
43 | a + b + f.read() // ok
|
Expand All @@ -20,6 +21,7 @@
|Note that capability f.write is not included in capture set {cap.only[Read]}.
|
|where: cap is a fresh root capability created in anonymous function of type (g²: Levels.File^): Unit when checking argument to parameter op of method parReduce
|
54 | f.write(42) // the error stems from here
55 | a + b + f.read() + g.read() // ok
|
Expand All @@ -33,6 +35,7 @@
|Note that capability g.write is not included in capture set {cap.only[Read]}.
|
|where: cap is a fresh root capability created in anonymous function of type (g²: Levels.File^): Unit when checking argument to parameter op of method parReduce
|
57 | g.write(42) // the error stems from here
58 | 0
|
Expand Down
2 changes: 2 additions & 0 deletions tests/neg-custom-args/captures/delayedRunops.check
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
| Required: () -> Unit
|
| Note that capability ops* is not included in capture set {}.
|
13 | val ops1 = ops
14 | runOps(ops1)
|
Expand All @@ -16,6 +17,7 @@
| Required: () -> Unit
|
| Note that capability ops* is not included in capture set {}.
|
25 | val ops1: List[() ->{ops*} Unit] = ops
26 | runOps(ops1)
|
Expand Down
3 changes: 3 additions & 0 deletions tests/neg-custom-args/captures/effect-swaps-explicit.check
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
| Required: Result[Future[T], Nothing]
|
| Note that capability fr is not included in capture set {}.
|
65 | fr.await.ok
|--------------------------------------------------------------------------------------------------------------------
|Inline stack trace
Expand All @@ -27,6 +28,7 @@
|
|where: ?=> refers to a fresh root capability created in method fail4 when checking argument to parameter body of method make
| ^ refers to the universal root capability
|
70 | fr.await.ok
|
| longer explanation available when compiling with `-explain`
Expand All @@ -40,6 +42,7 @@
|
|where: ?=> refers to a fresh root capability created in method fail5 when checking argument to parameter body of method make
| ^ refers to the universal root capability
|
74 | Future: fut ?=>
75 | fr.await.ok
|
Expand Down
3 changes: 3 additions & 0 deletions tests/neg-custom-args/captures/effect-swaps.check
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
| Required: Result[Future[T], Nothing]
|
| Note that capability fr is not included in capture set {}.
|
65 | fr.await.ok
|--------------------------------------------------------------------------------------------------------------------
|Inline stack trace
Expand All @@ -27,6 +28,7 @@
|
|where: ?=> refers to a fresh root capability created in method fail4 when checking argument to parameter body of method make
| ^ refers to the universal root capability
|
70 | fr.await.ok
|
| longer explanation available when compiling with `-explain`
Expand All @@ -40,6 +42,7 @@
|
|where: ?=> refers to a fresh root capability created in method fail5 when checking argument to parameter body of method make
| ^ refers to the universal root capability
|
74 | Future: fut ?=>
75 | fr.await.ok
|
Expand Down
1 change: 1 addition & 0 deletions tests/neg-custom-args/captures/filevar.check
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
| ^ refers to the universal root capability
| l is a reference to a value parameter
| l² is a reference to a value parameter
|
16 | val o = Service()
17 | o.file = f
18 | o.log
Expand Down
3 changes: 3 additions & 0 deletions tests/neg-custom-args/captures/heal-tparam-cs.check
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
|
|where: => refers to a fresh root capability created in value test1 when checking argument to parameter op of method localCap
| ^ refers to the universal root capability
|
11 | () => { c.use() }
|
| longer explanation available when compiling with `-explain`
Expand All @@ -24,6 +25,7 @@
|where: => refers to a root capability associated with the result type of (c: Capp^): () => Unit
| =>² and ^ refer to the universal root capability
| cap is a root capability associated with the result type of (x$0: Capp^'s4): () ->{x$0} Unit
|
16 | (c1: Capp^) => () => { c1.use() }
17 | }
|
Expand All @@ -35,6 +37,7 @@
| Required: (c: Capp^{io}) -> () ->{net} Unit
|
| Note that capability x$0 is not included in capture set {net}.
|
26 | (c1: Capp^{io}) => () => { c1.use() }
27 | }
|
Expand Down
13 changes: 7 additions & 6 deletions tests/neg-custom-args/captures/i16114.check
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,9 @@
| Required: Unit ->{io} Unit
|
| Note that capability fs is not included in capture set {io}.
|
18 | expect[Cap^] {
19 | io.use()
20 | fs
19 |...
21 | }
|
| longer explanation available when compiling with `-explain`
Expand All @@ -18,9 +18,9 @@
| Required: Unit ->{fs} Unit
|
| Note that capability io is not included in capture set {fs}.
|
24 | expect[Cap^] {
25 | fs.use()
26 | io
25 |...
27 | }
|
| longer explanation available when compiling with `-explain`
Expand All @@ -31,6 +31,7 @@
| Required: Unit -> Unit
|
| Note that capability io is not included in capture set {}.
|
36 | expect[Cap^](io)
|
| longer explanation available when compiling with `-explain`
Expand All @@ -41,9 +42,9 @@
| Required: Unit -> Unit
|
| Note that capability io is not included in capture set {}.
|
39 | expect[Cap^] {
40 | io.use()
41 | io
40 |...
42 | }
|
| longer explanation available when compiling with `-explain`
1 change: 1 addition & 0 deletions tests/neg-custom-args/captures/i21347.check
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,5 @@
| ^
| Local reach capability ops* leaks into capture scope of method runOpsAlt.
| You could try to abstract the capabilities referred to by ops* in a capset variable.
|
12 | op()
1 change: 1 addition & 0 deletions tests/neg-custom-args/captures/i23431.check
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@
| ^ refers to the universal root capability
| cap is a fresh root capability created in anonymous function of type (io3: IO^'s1): Unit of parameter parameter io3² of method $anonfun
| cap² is a fresh root capability in the type of variable myIO
|
13 | myIO = io3
|
| longer explanation available when compiling with `-explain`
Expand Down
1 change: 1 addition & 0 deletions tests/neg-custom-args/captures/i23582.check
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
|Note that capability write is not included in capture set {cap.only[Read]}.
|
|where: cap is a fresh root capability created in method test when checking argument to parameter op of method parReduce
|
28 | write(x)
29 | x + y + read()
|
Expand Down
4 changes: 2 additions & 2 deletions tests/neg-custom-args/captures/i24309-region-orig.check
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
| ^
| Local reach capability r1.R leaks into capture scope of an enclosing function.
| You could try to abstract the capabilities referred to by r1.R in a capset variable.
|
18 | var a: Ref^{r1.R} = r1.alloc(0)
19 | var b: Ref^{r2.R} = r2.alloc(0)
20 | val c: Ref^{r1.R} = b
19 |...
21 | a
1 change: 1 addition & 0 deletions tests/neg-custom-args/captures/lazylists-exceptions.check
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
|
| Found: LazyList[Int]^{canThrow$1}
| Required: LazyList[Int]^'s1
|
38 | if i > 9 then throw Ex1()
39 | i * i
40 | }
Expand Down
1 change: 1 addition & 0 deletions tests/neg-custom-args/captures/lazylists2.check
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@
60 | class Mapped2 extends Mapped: // error
| ^
| references {f, xs} are not all included in the allowed capture set {} of the self type of class Mapped2
|
61 | this: Mapped =>
-- [E007] Type Mismatch Error: tests/neg-custom-args/captures/lazylists2.scala:62:4 ------------------------------------
62 | new Mapped2 // error
Expand Down
5 changes: 2 additions & 3 deletions tests/neg-custom-args/captures/lazyvals3.check
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,9 @@
| Required: Int ->{ev1, console} Boolean
|
| Note that capability c is not included in capture set {ev1, console}.
|
25 | if n == 1 then
26 | console.println("CONSOLE: 1")
27 | true
28 | else
26 |...
29 | ev1(n - 1)
|
| longer explanation available when compiling with `-explain`
1 change: 1 addition & 0 deletions tests/neg-custom-args/captures/leaking-iterators.check
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
|
|where: => refers to a fresh root capability created in method test when checking argument to parameter op of method usingLogFile
| ^ refers to the universal root capability
|
57 | xs.iterator.map: x =>
58 | log.write(x)
59 | x * x
Expand Down
1 change: 1 addition & 0 deletions tests/neg-custom-args/captures/mut-iterator4.check
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
|Note that capability cap is not included in capture set {it, f}.
|
|where: cap is a fresh root capability created in method mappedIterator when constructing instance Object with (Iterator[U]^{cap².rd}) {...}
|
22 | def hasNext = it.hasNext
23 | update def next() = f(it.next())
|
Expand Down
1 change: 1 addition & 0 deletions tests/neg-custom-args/captures/nicolas1.check
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
| Note that capability tail* is not included in capture set {head}.
|
| where: ^ refers to the universal root capability
|
11 | all(nextInt(all.length))
|
| longer explanation available when compiling with `-explain`
Loading
Loading