Skip to content

Commit e25362d

Browse files
authored
Refactor string interpolators and error message handling (#16384)
The idea is that we want to concentrate error handling logic in the `Message` type instead of dispersing it over various string interpolators. - [x] Pass more messages instead of strings to `report` methods. - [x] Make this easier by having string interpolators that produce messages - [x] Use messages instead of strings elsewhere - [x] Move logic for limiting size of messages and filtering out nonsensical errors into `Message`. From the doc comment for `Message`: ## Tips for error message generation - You can use the `em` interpolator for error messages. It's defined in core.Decorators. - You can also use a simple string argument for `error` or `warning` (not for the other variants), but the string should not be interpolated or composed of objects that require a Context for evaluation. - When embedding interpolated substrings defined elsewhere in error messages, use `i` and make sure they are defined as def's instead of vals. That way, the possibly expensive interpolation will performed only in the case where the message is eventually printed. Note: At least during typer, it's common for messages to be discarded without being printed. Also, by making them defs, you ensure that they will be evaluated in the Message context, which makes formatting safer and more robust. - For common messages, or messages that might require explanation, prefer defining a new `Message` in file `messages.scala` and use that instead. The advantage is that these messages have unique IDs that can be referenced elsewhere.
2 parents c9ace66 + d704ede commit e25362d

File tree

157 files changed

+3730
-3665
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

157 files changed

+3730
-3665
lines changed

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

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ import dotty.tools.dotc.transform.SymUtils._
2323
import dotty.tools.dotc.util.Spans._
2424
import dotty.tools.dotc.core.Contexts._
2525
import dotty.tools.dotc.core.Phases._
26+
import dotty.tools.dotc.core.Decorators.em
2627
import dotty.tools.dotc.report
2728

2829
/*
@@ -700,7 +701,7 @@ trait BCodeBodyBuilder extends BCodeSkelBuilder {
700701
var elemKind = arr.elementType
701702
val argsSize = args.length
702703
if (argsSize > dims) {
703-
report.error(s"too many arguments for array constructor: found ${args.length} but array has only $dims dimension(s)", ctx.source.atSpan(app.span))
704+
report.error(em"too many arguments for array constructor: found ${args.length} but array has only $dims dimension(s)", ctx.source.atSpan(app.span))
704705
}
705706
if (argsSize < dims) {
706707
/* In one step:

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

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,7 @@ trait BCodeHelpers extends BCodeIdiomatic with BytecodeWriters {
7979
outputDirectory
8080
} catch {
8181
case ex: Throwable =>
82-
report.error(s"Couldn't create file for class $cName\n${ex.getMessage}", ctx.source.atSpan(csym.span))
82+
report.error(em"Couldn't create file for class $cName\n${ex.getMessage}", ctx.source.atSpan(csym.span))
8383
null
8484
}
8585
}
@@ -422,7 +422,7 @@ trait BCodeHelpers extends BCodeIdiomatic with BytecodeWriters {
422422
emitAssocs(nestedVisitor, assocs, bcodeStore)(innerClasesStore)
423423

424424
case t =>
425-
report.error(ex"Annotation argument is not a constant", t.sourcePos)
425+
report.error(em"Annotation argument is not a constant", t.sourcePos)
426426
}
427427
}
428428

@@ -871,10 +871,11 @@ trait BCodeHelpers extends BCodeIdiomatic with BytecodeWriters {
871871
try body
872872
catch {
873873
case ex: Throwable =>
874-
report.error(i"""|compiler bug: created invalid generic signature for $sym in ${sym.denot.owner.showFullName}
875-
|signature: $sig
876-
|if this is reproducible, please report bug at https://github.com/lampepfl/dotty/issues
877-
""".trim, sym.sourcePos)
874+
report.error(
875+
em"""|compiler bug: created invalid generic signature for $sym in ${sym.denot.owner.showFullName}
876+
|signature: $sig
877+
|if this is reproducible, please report bug at https://github.com/lampepfl/dotty/issues
878+
""", sym.sourcePos)
878879
throw ex
879880
}
880881
}

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

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -748,7 +748,7 @@ trait BCodeSkelBuilder extends BCodeHelpers {
748748

749749
if (params.size > MaximumJvmParameters) {
750750
// SI-7324
751-
report.error(s"Platform restriction: a parameter list's length cannot exceed $MaximumJvmParameters.", ctx.source.atSpan(methSymbol.span))
751+
report.error(em"Platform restriction: a parameter list's length cannot exceed $MaximumJvmParameters.", ctx.source.atSpan(methSymbol.span))
752752
return
753753
}
754754

@@ -800,9 +800,10 @@ trait BCodeSkelBuilder extends BCodeHelpers {
800800
val veryFirstProgramPoint = currProgramPoint()
801801

802802
if trimmedRhs == tpd.EmptyTree then
803-
report.error("Concrete method has no definition: " + dd + (
804-
if (ctx.settings.Ydebug.value) "(found: " + methSymbol.owner.info.decls.toList.mkString(", ") + ")"
805-
else ""),
803+
report.error(
804+
em"Concrete method has no definition: $dd${
805+
if (ctx.settings.Ydebug.value) "(found: " + methSymbol.owner.info.decls.toList.mkString(", ") + ")"
806+
else ""}",
806807
ctx.source.atSpan(NoSpan)
807808
)
808809
else

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

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import Contexts._
1414
import Types._
1515
import Symbols._
1616
import Phases._
17+
import Decorators.em
1718

1819
import dotty.tools.dotc.util.ReadOnlyMap
1920
import dotty.tools.dotc.report
@@ -71,7 +72,7 @@ class DottyBackendInterface(val outputDirectory: AbstractFile, val superCallsMap
7172
def _1: Type = field.tpe match {
7273
case JavaArrayType(elem) => elem
7374
case _ =>
74-
report.error(s"JavaSeqArray with type ${field.tpe} reached backend: $field", ctx.source.atSpan(field.span))
75+
report.error(em"JavaSeqArray with type ${field.tpe} reached backend: $field", ctx.source.atSpan(field.span))
7576
UnspecifiedErrorType
7677
}
7778
def _2: List[Tree] = field.elems

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

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ import dotty.tools.dotc.sbt.ExtractDependencies
2121
import Contexts._
2222
import Phases._
2323
import Symbols._
24+
import Decorators.em
2425

2526
import java.io.DataOutputStream
2627
import java.nio.channels.ClosedByInterruptException
@@ -308,7 +309,7 @@ class GenBCodePipeline(val int: DottyBackendInterface, val primitives: DottyPrim
308309
getFileForClassfile(outF, cls.name, ".class")
309310
} catch {
310311
case e: FileConflictException =>
311-
report.error(s"error writing ${cls.name}: ${e.getMessage}")
312+
report.error(em"error writing ${cls.name}: ${e.getMessage}")
312313
null
313314
}
314315
} else null
@@ -608,11 +609,11 @@ class GenBCodePipeline(val int: DottyBackendInterface, val primitives: DottyPrim
608609
val method =
609610
s"${e.getClassName.replaceAll("/", ".")}.${e.getMethodName}"
610611
val msg =
611-
s"Generated bytecode for method '$method' is too large. Size: ${e.getCodeSize} bytes. Limit is 64KB"
612+
em"Generated bytecode for method '$method' is too large. Size: ${e.getCodeSize} bytes. Limit is 64KB"
612613
report.error(msg)
613614
case e: ClassTooLargeException =>
614615
val msg =
615-
s"Class '${e.getClassName.replaceAll("/", ".")}' is too large. Constant pool size: ${e.getConstantPoolCount}. Limit is 64K entries"
616+
em"Class '${e.getClassName.replaceAll("/", ".")}' is too large. Constant pool size: ${e.getConstantPoolCount}. Limit is 64K entries"
616617
report.error(msg)
617618

618619
}

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

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import Contexts._
88
import Names.TermName, StdNames._
99
import Types.{JavaArrayType, UnspecifiedErrorType, Type}
1010
import Symbols.{Symbol, NoSymbol}
11+
import Decorators.em
1112
import dotc.report
1213
import dotc.util.ReadOnlyMap
1314

@@ -66,7 +67,7 @@ class DottyPrimitives(ictx: Context) {
6667
case defn.ArrayOf(el) => el
6768
case JavaArrayType(el) => el
6869
case _ =>
69-
report.error(s"expected Array $tpe")
70+
report.error(em"expected Array $tpe")
7071
UnspecifiedErrorType
7172
}
7273

@@ -133,7 +134,7 @@ class DottyPrimitives(ictx: Context) {
133134
def addPrimitives(cls: Symbol, method: TermName, code: Int)(using Context): Unit = {
134135
val alts = cls.info.member(method).alternatives.map(_.symbol)
135136
if (alts.isEmpty)
136-
report.error(s"Unknown primitive method $cls.$method")
137+
report.error(em"Unknown primitive method $cls.$method")
137138
else alts foreach (s =>
138139
addPrimitive(s,
139140
s.info.paramInfoss match {

compiler/src/dotty/tools/backend/sjs/JSCodeGen.scala

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2926,7 +2926,7 @@ class JSCodeGen()(using genCtx: Context) {
29262926
case defn.ArrayOf(el) => el
29272927
case JavaArrayType(el) => el
29282928
case tpe =>
2929-
val msg = ex"expected Array $tpe"
2929+
val msg = em"expected Array $tpe"
29302930
report.error(msg)
29312931
ErrorType(msg)
29322932
}
@@ -3652,7 +3652,7 @@ class JSCodeGen()(using genCtx: Context) {
36523652
} else if (sym.isJSType) {
36533653
if (sym.is(Trait)) {
36543654
report.error(
3655-
s"isInstanceOf[${sym.fullName}] not supported because it is a JS trait",
3655+
em"isInstanceOf[${sym.fullName}] not supported because it is a JS trait",
36563656
pos)
36573657
js.BooleanLiteral(true)
36583658
} else {

compiler/src/dotty/tools/backend/sjs/JSExportsGen.scala

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -135,8 +135,7 @@ final class JSExportsGen(jsCodeGen: JSCodeGen)(using Context) {
135135

136136
for ((info, _) <- tups.tail) {
137137
report.error(
138-
em"export overload conflicts with export of $firstSym: " +
139-
"a field may not share its exported name with another export",
138+
em"export overload conflicts with export of $firstSym: a field may not share its exported name with another export",
140139
info.pos)
141140
}
142141

@@ -264,8 +263,8 @@ final class JSExportsGen(jsCodeGen: JSCodeGen)(using Context) {
264263
.alternatives
265264

266265
assert(!alts.isEmpty,
267-
em"Ended up with no alternatives for ${classSym.fullName}::$name. " +
268-
em"Original set was ${alts} with types ${alts.map(_.info)}")
266+
em"""Ended up with no alternatives for ${classSym.fullName}::$name.
267+
|Original set was ${alts} with types ${alts.map(_.info)}""")
269268

270269
val (jsName, isProp) = exportNameInfo(name)
271270

@@ -309,7 +308,7 @@ final class JSExportsGen(jsCodeGen: JSCodeGen)(using Context) {
309308
if (isProp && methodSyms.nonEmpty) {
310309
val firstAlt = alts.head
311310
report.error(
312-
i"Conflicting properties and methods for ${classSym.fullName}::$name.",
311+
em"Conflicting properties and methods for ${classSym.fullName}::$name.",
313312
firstAlt.srcPos)
314313
implicit val pos = firstAlt.span
315314
js.JSPropertyDef(js.MemberFlags.empty, genExpr(name)(firstAlt.sourcePos), None, None)
@@ -613,7 +612,7 @@ final class JSExportsGen(jsCodeGen: JSCodeGen)(using Context) {
613612
val altsTypesInfo = alts.map(_.info.show).sorted.mkString("\n ")
614613

615614
report.error(
616-
s"Cannot disambiguate overloads for $fullKind $displayName with types\n $altsTypesInfo",
615+
em"Cannot disambiguate overloads for $fullKind $displayName with types\n $altsTypesInfo",
617616
pos)
618617
}
619618

compiler/src/dotty/tools/backend/sjs/JSPositions.scala

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import java.net.{URI, URISyntaxException}
66

77
import dotty.tools.dotc.core._
88
import Contexts._
9+
import Decorators.em
910

1011
import dotty.tools.dotc.report
1112

@@ -31,7 +32,7 @@ class JSPositions()(using Context) {
3132
URIMap(from, to) :: Nil
3233
} catch {
3334
case e: URISyntaxException =>
34-
report.error(s"${e.getInput} is not a valid URI")
35+
report.error(em"${e.getInput} is not a valid URI")
3536
Nil
3637
}
3738
}

compiler/src/dotty/tools/backend/sjs/JSPrimitives.scala

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import Names.TermName
55
import Types._
66
import Contexts._
77
import Symbols._
8+
import Decorators.em
89

910
import dotty.tools.dotc.ast.tpd._
1011
import dotty.tools.backend.jvm.DottyPrimitives
@@ -90,7 +91,7 @@ class JSPrimitives(ictx: Context) extends DottyPrimitives(ictx) {
9091
def addPrimitives(cls: Symbol, method: TermName, code: Int)(using Context): Unit = {
9192
val alts = cls.info.member(method).alternatives.map(_.symbol)
9293
if (alts.isEmpty) {
93-
report.error(s"Unknown primitive method $cls.$method")
94+
report.error(em"Unknown primitive method $cls.$method")
9495
} else {
9596
for (s <- alts)
9697
addPrimitive(s, code)

0 commit comments

Comments
 (0)