Skip to content

Commit 9744afe

Browse files
committed
Refactoring: Replace Addenda by list of Notes
1 parent 2e4914d commit 9744afe

File tree

9 files changed

+56
-64
lines changed

9 files changed

+56
-64
lines changed

compiler/src/dotty/tools/dotc/cc/Capability.scala

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@ package cc
55
import core.*
66
import Types.*, Symbols.*, Contexts.*, Decorators.*
77
import util.{SimpleIdentitySet, EqHashMap}
8-
import typer.ErrorReporting.Addenda
98
import util.common.alwaysTrue
109
import scala.collection.mutable
1110
import CCState.*

compiler/src/dotty/tools/dotc/cc/CaptureSet.scala

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,6 @@ import reporting.trace
1313
import printing.{Showable, Printer}
1414
import printing.Texts.*
1515
import util.{SimpleIdentitySet, Property, EqHashMap}
16-
import typer.ErrorReporting.Addenda
1716
import scala.collection.{mutable, immutable}
1817
import TypeComparer.ErrorNote
1918
import CCState.*

compiler/src/dotty/tools/dotc/cc/CheckCaptures.scala

Lines changed: 23 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ import typer.ForceDegree
1414
import typer.Inferencing.isFullyDefined
1515
import typer.RefChecks.{checkAllOverrides, checkSelfAgainstParents, OverridingPairsChecker}
1616
import typer.Checking.{checkBounds, checkAppliedTypesIn}
17-
import typer.ErrorReporting.{Addenda, NothingToAdd, err}
17+
import typer.ErrorReporting.{Note, err}
1818
import typer.ProtoTypes.{LhsProto, WildcardSelectionProto, SelectionProto}
1919
import util.{SimpleIdentitySet, EqHashMap, EqHashSet, SrcPos, Property}
2020
import util.chaining.tap
@@ -399,7 +399,7 @@ class CheckCaptures extends Recheck, SymTransformer:
399399
case (fail: IncludeFailure) :: _ => fail.cs
400400
case _ => target
401401
def msg(provisional: Boolean) =
402-
def toAdd: String = errorNotes(otherNotes).toAdd.mkString
402+
def toAdd: String = errorNotes(otherNotes).map(_.render).mkString
403403
def descr: String =
404404
val d = realTarget.description
405405
if d.isEmpty then provenance else ""
@@ -1208,7 +1208,7 @@ class CheckCaptures extends Recheck, SymTransformer:
12081208
// too annoying. This is a hole since a defualt getter's result type
12091209
// might leak into a type variable.
12101210

1211-
def fail(tree: Tree, expected: Type, addenda: Addenda): Unit =
1211+
def fail(tree: Tree, expected: Type, notes: List[Note]): Unit =
12121212
def maybeResult = if sym.is(Method) then " result" else ""
12131213
report.error(
12141214
em"""$sym needs an explicit$maybeResult type because the inferred type does not conform to
@@ -1218,7 +1218,7 @@ class CheckCaptures extends Recheck, SymTransformer:
12181218
| Externally visible type: $expected""",
12191219
tree.srcPos)
12201220

1221-
def addenda(expected: Type) = Addenda:
1221+
def addendum(expected: Type) = Note:
12221222
def result = if tree.isInstanceOf[ValDef] then"" else " result"
12231223
i"""
12241224
|
@@ -1237,7 +1237,7 @@ class CheckCaptures extends Recheck, SymTransformer:
12371237
val expected = tpt.tpe.dropAllRetains
12381238
todoAtPostCheck += { () =>
12391239
withCapAsRoot:
1240-
testAdapted(tp, expected, tree.rhs, addenda(expected))(fail)
1240+
testAdapted(tp, expected, tree.rhs, addendum(expected) :: Nil)(fail)
12411241
// The check that inferred <: expected is done after recheck so that it
12421242
// does not interfere with normal rechecking by constraining capture set variables.
12431243
}
@@ -1444,34 +1444,34 @@ class CheckCaptures extends Recheck, SymTransformer:
14441444

14451445
type BoxErrors = mutable.ListBuffer[Message] | Null
14461446

1447-
private def errorNotes(notes: List[TypeComparer.ErrorNote])(using Context): Addenda =
1448-
if notes.isEmpty then NothingToAdd
1449-
else new Addenda:
1450-
override def toAdd(using Context) = notes.map: note =>
1447+
private def errorNotes(notes: List[TypeComparer.ErrorNote])(using Context): List[Note] =
1448+
notes.map: note =>
1449+
Note:
14511450
i"""
14521451
|
14531452
|Note that ${note.description}."""
14541453

14551454
/** Addendas for error messages that show where we have under-approximated by
1456-
* mapping a a capability in contravariant position to the empty set because
1455+
* mapping of a capability in contravariant position to the empty set because
14571456
* the original result type of the map was not itself a capability.
14581457
*/
1459-
private def addApproxAddenda(using Context) =
1460-
new TypeAccumulator[Addenda]:
1461-
def apply(add: Addenda, t: Type) = t match
1458+
private def addApproxAddenda(using Context): TypeAccumulator[List[Note]] =
1459+
new TypeAccumulator:
1460+
def apply(notes: List[Note], t: Type) = t match
14621461
case CapturingType(t, CaptureSet.EmptyWithProvenance(ref, mapped)) =>
14631462
/* val (origCore, kind) = original match
14641463
case tp @ AnnotatedType(parent, ann) if ann.hasSymbol(defn.ReachCapabilityAnnot) =>
14651464
(parent, " deep")
14661465
case _ =>
14671466
(original, "")*/
1468-
add ++ Addenda:
1467+
Note:
14691468
i"""
14701469
|
14711470
|Note that a capability $ref in a capture set appearing in contravariant position
14721471
|was mapped to $mapped which is not a capability. Therefore, it was under-approximated to the empty set."""
1472+
:: notes
14731473
case _ =>
1474-
foldOver(add, t)
1474+
foldOver(notes, t)
14751475

14761476
/** Massage `actual` and `expected` types before checking conformance.
14771477
* Massaging is done by the methods following this one:
@@ -1480,8 +1480,8 @@ class CheckCaptures extends Recheck, SymTransformer:
14801480
* If the resulting types are not compatible, try again with an actual type
14811481
* where local capture roots are instantiated to root variables.
14821482
*/
1483-
override def checkConformsExpr(actual: Type, expected: Type, tree: Tree, addenda: Addenda)(using Context): Type =
1484-
try testAdapted(actual, expected, tree, addenda)(err.typeMismatch)
1483+
override def checkConformsExpr(actual: Type, expected: Type, tree: Tree, notes: List[Note])(using Context): Type =
1484+
try testAdapted(actual, expected, tree, notes: List[Note])(err.typeMismatch)
14851485
catch case ex: AssertionError =>
14861486
println(i"error while checking $tree: $actual against $expected")
14871487
throw ex
@@ -1496,8 +1496,8 @@ class CheckCaptures extends Recheck, SymTransformer:
14961496
case _ => NoType
14971497
case _ => NoType
14981498

1499-
inline def testAdapted(actual: Type, expected: Type, tree: Tree, addenda: Addenda)
1500-
(fail: (Tree, Type, Addenda) => Unit)(using Context): Type =
1499+
inline def testAdapted(actual: Type, expected: Type, tree: Tree, notes: List[Note])
1500+
(fail: (Tree, Type, List[Note]) => Unit)(using Context): Type =
15011501

15021502
var expected1 = alignDependentFunction(expected, actual.stripCapturing)
15031503
val falseDeps = expected1 ne expected
@@ -1544,11 +1544,12 @@ class CheckCaptures extends Recheck, SymTransformer:
15441544
}
15451545

15461546
TypeComparer.compareResult(tryCurrentType || tryWidenNamed) match
1547-
case TypeComparer.CompareResult.Fail(notes) =>
1547+
case TypeComparer.CompareResult.Fail(errNotes) =>
15481548
capt.println(i"conforms failed for ${tree}: $actual vs $expected")
15491549
if falseDeps then expected1 = unalignFunction(expected1)
1550-
fail(tree.withType(actualBoxed), expected1,
1551-
addApproxAddenda(addenda ++ errorNotes(notes), expected1))
1550+
val toAdd0 = notes ++ errorNotes(errNotes)
1551+
val toAdd1 = addApproxAddenda(toAdd0, expected1)
1552+
fail(tree.withType(actualBoxed), expected1, toAdd1)
15521553
actual
15531554
case /*OK*/ _ =>
15541555
if debugSuccesses then tree match

compiler/src/dotty/tools/dotc/core/TypeComparer.scala

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3327,7 +3327,7 @@ class TypeComparer(@constructorOnly initctx: Context) extends ConstraintHandling
33273327
* the same class as `note`.
33283328
*/
33293329
def addErrorNote(note: ErrorNote): Unit =
3330-
if errorNotes.forall(_._2.kind != note.kind) then
3330+
if errorNotes.forall(_._2.getClass != note.getClass) then
33313331
errorNotes = (recCount, note) :: errorNotes
33323332
assert(maxErrorLevel <= recCount)
33333333
maxErrorLevel = recCount
@@ -3357,11 +3357,6 @@ object TypeComparer {
33573357

33583358
/** A base trait for data producing addenda to error messages */
33593359
trait ErrorNote:
3360-
/** A disciminating kind. An error note is not added if it has the same kind
3361-
* as an already existing error note.
3362-
*/
3363-
def kind: Class[?] = getClass
3364-
33653360
def description(using Context): String
33663361
end ErrorNote
33673362

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

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ import ast.desugar
1818
import config.{Feature, MigrationVersion, ScalaVersion}
1919
import transform.patmat.Space
2020
import transform.patmat.SpaceEngine
21-
import typer.ErrorReporting.{err, matchReductionAddendum, substitutableTypeSymbolsInScope, Addenda, NothingToAdd}
21+
import typer.ErrorReporting.{err, matchReductionAddendum, substitutableTypeSymbolsInScope, Note}
2222
import typer.ProtoTypes.{ViewProto, SelectionProto, FunProto}
2323
import typer.Implicits.*
2424
import typer.Inferencing
@@ -298,7 +298,7 @@ extends NotFoundMsg(MissingIdentID) {
298298
}
299299
}
300300

301-
class TypeMismatch(val found: Type, expected: Type, val inTree: Option[untpd.Tree], addenda: Addenda = NothingToAdd)(using Context)
301+
class TypeMismatch(val found: Type, expected: Type, val inTree: Option[untpd.Tree], notes: List[Note] = Nil)(using Context)
302302
extends TypeMismatchMsg(found, expected)(TypeMismatchID):
303303

304304
private val shouldSuggestNN =
@@ -359,8 +359,7 @@ class TypeMismatch(val found: Type, expected: Type, val inTree: Option[untpd.Tre
359359
def importSuggestions =
360360
if expected.isTopType || found.isBottomType then ""
361361
else ctx.typer.importSuggestionAddendum(ViewProto(found.widen, expected))
362-
363-
addenda.toAdd.mkString ++ super.msgPostscript ++ importSuggestions
362+
notes.map(_.render).mkString ++ super.msgPostscript ++ importSuggestions
364363

365364
override def explain(using Context) =
366365
val treeStr = inTree.map(x => s"\nTree:\n\n${x.show}\n").getOrElse("")

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

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ import typer.ErrorReporting.err
1515
import typer.ProtoTypes.{AnySelectionProto, LhsProto}
1616
import typer.TypeAssigner.seqLitType
1717
import typer.ConstFold
18-
import typer.ErrorReporting.{Addenda, NothingToAdd}
18+
import typer.ErrorReporting.Note
1919
import config.Printers.recheckr
2020
import util.Property
2121
import StdNames.nme
@@ -633,11 +633,11 @@ abstract class Recheck extends Phase, SymTransformer:
633633
println(i"fail while $actual iscompat $expected")
634634
throw ex
635635

636-
def checkConformsExpr(actual: Type, expected: Type, tree: Tree, addenda: Addenda = NothingToAdd)(using Context): Type =
636+
def checkConformsExpr(actual: Type, expected: Type, tree: Tree, notes: List[Note] = Nil)(using Context): Type =
637637
//println(i"check conforms $actual <:< $expected")
638638
if !isCompatible(actual, expected) then
639639
recheckr.println(i"conforms failed for ${tree}: $actual vs $expected")
640-
err.typeMismatch(tree.withType(actual), expected, addenda)
640+
err.typeMismatch(tree.withType(actual), expected, notes)
641641
actual
642642

643643
def checkUnit(unit: CompilationUnit)(using Context): Unit =

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

Lines changed: 10 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -71,18 +71,13 @@ object ErrorReporting {
7171
case _ => foldOver(s, tp)
7272
tps.foldLeft("")(collectMatchTrace)
7373

74-
/** A mixin trait that can produce added elements for an error message */
75-
trait Addenda:
76-
def toAdd(using Context): List[String]
77-
def ++(follow: Addenda) = new Addenda:
78-
def toAdd(using Context) = Addenda.this.toAdd ++ follow.toAdd
74+
/** A note can produce an added string for an error message */
75+
abstract class Note(val prefix: Boolean = false):
76+
def render(using Context): String
7977

80-
object Addenda:
81-
def apply(msg: Context ?=> String): Addenda = new Addenda:
82-
def toAdd(using Context) = msg :: Nil
83-
84-
object NothingToAdd extends Addenda:
85-
def toAdd(using Context): List[String] = Nil
78+
object Note:
79+
def apply(msg: Context ?=> String, prefix: Boolean = false) = new Note(prefix):
80+
def render(using Context) = msg
8681

8782
class Errors(using Context) {
8883

@@ -180,7 +175,7 @@ object ErrorReporting {
180175

181176
def patternConstrStr(tree: Tree): String = ???
182177

183-
def typeMismatch(tree: Tree, pt: Type, addenda: Addenda = NothingToAdd): Tree = {
178+
def typeMismatch(tree: Tree, pt: Type, notes: List[Note] = Nil): Tree = {
184179
val normTp = normalize(tree.tpe, pt)
185180
val normPt = normalize(pt, pt)
186181

@@ -199,11 +194,11 @@ object ErrorReporting {
199194

200195
def missingElse = tree match
201196
case If(_, _, elsep @ Literal(Constant(()))) if elsep.span.isSynthetic =>
202-
Addenda("\nMaybe you are missing an else part for the conditional?")
197+
Note("\nMaybe you are missing an else part for the conditional?") :: Nil
203198
case _ =>
204-
NothingToAdd
199+
Nil
205200

206-
errorTree(tree, TypeMismatch(treeTp, expectedTp, Some(tree), addenda ++ missingElse))
201+
errorTree(tree, TypeMismatch(treeTp, expectedTp, Some(tree), notes ++ missingElse))
207202
}
208203

209204
/** A subtype log explaining why `found` does not conform to `expected` */

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

Lines changed: 14 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -467,7 +467,7 @@ object Implicits:
467467
}
468468
}
469469

470-
abstract class SearchFailureType extends ErrorType, Addenda {
470+
abstract class SearchFailureType extends ErrorType {
471471
def expectedType: Type
472472
def argument: Tree
473473

@@ -485,7 +485,7 @@ object Implicits:
485485
else i"convert from ${argument.tpe} to ${clarify(expectedType)}"
486486
}
487487

488-
def toAdd(using Context) = Nil
488+
def notes(using Context): List[Note] = Nil
489489
}
490490

491491
class NoMatchingImplicits(val expectedType: Type, val argument: Tree, constraint: Constraint = OrderingConstraint.empty)
@@ -540,10 +540,12 @@ object Implicits:
540540
/** A failure value indicating that an implicit search for a conversion was not tried */
541541
case class TooUnspecific(target: Type) extends NoMatchingImplicits(NoType, EmptyTree, OrderingConstraint.empty):
542542

543-
override def toAdd(using Context) =
544-
i"""
545-
|Note that implicit conversions were not tried because the result of an implicit conversion
546-
|must be more specific than $target""" :: Nil
543+
override def notes(using Context) =
544+
Note:
545+
i"""
546+
|Note that implicit conversions were not tried because the result of an implicit conversion
547+
|must be more specific than $target"""
548+
:: Nil
547549

548550
override def msg(using Context) =
549551
super.msg.append(i"\nThe expected type $target is not specific enough, so no search was attempted")
@@ -567,14 +569,16 @@ object Implicits:
567569
str2 = alt2.ref.showRef
568570
em"both $str1 and $str2 $qualify".withoutDisambiguation()
569571

570-
override def toAdd(using Context) =
572+
override def notes(using Context) =
571573
if !argument.isEmpty && argument.tpe.widen.isRef(defn.NothingClass) then
572574
Nil
573575
else
574576
val what = if (expectedType.isInstanceOf[SelectionProto]) "extension methods" else "conversions"
575-
i"""
576-
|Note that implicit $what cannot be applied because they are ambiguous;
577-
|$explanation""" :: Nil
577+
Note:
578+
i"""
579+
|Note that implicit $what cannot be applied because they are ambiguous;
580+
|$explanation"""
581+
:: Nil
578582

579583
def asNested = if nested then this else AmbiguousImplicits(alt1, alt2, expectedType, argument, nested = true)
580584
end AmbiguousImplicits

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4218,7 +4218,7 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer
42184218
then
42194219
tryExtensionOrConversion(tree, pt, mbrProto, qual, locked, compat, inSelect)
42204220
else
4221-
err.typeMismatch(qual, selProto, failure.reason) // TODO: report NotAMember instead, but need to be aware of failure
4221+
err.typeMismatch(qual, selProto, failure.reason.notes) // TODO: report NotAMember instead, but need to be aware of failure
42224222
rememberSearchFailure(qual, failure)
42234223
catch case ex: TypeError => nestedFailure(ex)
42244224

@@ -4889,7 +4889,7 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer
48894889
else
48904890
val tree1 = healAdapt(tree, pt)
48914891
if tree1 ne tree then readapt(tree1)
4892-
else err.typeMismatch(tree, pt, failure)
4892+
else err.typeMismatch(tree, pt, failure.notes)
48934893

48944894
pt match
48954895
case _: SelectionProto =>

0 commit comments

Comments
 (0)