Skip to content

Commit cbd308a

Browse files
committed
Unify to have a single error class that refers to a set and an element
1 parent ce78e87 commit cbd308a

File tree

2 files changed

+35
-36
lines changed

2 files changed

+35
-36
lines changed

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

Lines changed: 24 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -175,7 +175,7 @@ sealed abstract class CaptureSet extends Showable:
175175

176176
protected def addIfHiddenOrFail(elem: Capability)(using ctx: Context, vs: VarState): Boolean =
177177
elems.exists(_.maxSubsumes(elem, canAddHidden = true))
178-
|| failWith(IncludeFailure(this :: Nil))
178+
|| failWith(IncludeFailure(this, elem))
179179

180180
/** If this is a variable, add `cs` as a dependent set */
181181
protected def addDependent(cs: CaptureSet)(using Context, VarState): Boolean
@@ -604,7 +604,7 @@ object CaptureSet:
604604
if isConst || !recordElemsState() then // Fail if variable is solved or given VarState is frozen
605605
addIfHiddenOrFail(elem)
606606
else if !levelOK(elem) then
607-
failWith(LevelError(this, elem)) // or `elem` is not visible at the level of the set.
607+
failWith(IncludeFailure(this, elem, levelError = true)) // or `elem` is not visible at the level of the set.
608608
else
609609
// id == 108 then assert(false, i"trying to add $elem to $this")
610610
assert(elem.isWellformed, elem)
@@ -622,7 +622,7 @@ object CaptureSet:
622622
if !res then
623623
elems -= elem
624624
TypeComparer.updateErrorNotes:
625-
case IncludeFailure(trace) => IncludeFailure(this :: trace)
625+
case note: IncludeFailure => note.addToTrace(this)
626626
res
627627

628628
private def isPartOf(binder: Type)(using Context): Boolean =
@@ -667,13 +667,10 @@ object CaptureSet:
667667
true
668668

669669
def addDependent(cs: CaptureSet)(using Context, VarState): Boolean =
670-
if (cs eq this) || cs.isUniversal || isConst then
671-
true
672-
else if recordDepsState() then
673-
deps += cs
674-
true
675-
else
676-
failWith(IncludeFailure(this :: Nil))
670+
(cs eq this)
671+
|| cs.isUniversal
672+
|| isConst
673+
|| recordDepsState() && { deps += cs; true }
677674

678675
override def disallowRootCapability(upto: Symbol)(handler: () => Context ?=> Unit)(using Context): this.type =
679676
rootLimit = upto
@@ -871,7 +868,7 @@ object CaptureSet:
871868
// Filtered elements have to be back-propagated to source.
872869
// Elements that don't satisfy `p` are not allowed.
873870
if p(elem) then source.tryInclude(elem, this)
874-
else failWith(IncludeFailure(this :: Nil))
871+
else failWith(IncludeFailure(this, elem))
875872

876873
override def computeApprox(origin: CaptureSet)(using Context): CaptureSet =
877874
if source eq origin then
@@ -1079,25 +1076,24 @@ object CaptureSet:
10791076
*/
10801077
case class ExistentialSubsumesFailure(val ex: ResultCap, val other: Capability) extends ErrorNote
10811078

1082-
sealed abstract class CompareFailure extends ErrorNote, Showable:
1083-
override def kind = classOf[CompareFailure]
1079+
case class IncludeFailure(cs: CaptureSet, elem: Capability, levelError: Boolean = false) extends ErrorNote, Showable:
1080+
private var myTrace: List[CaptureSet] = cs :: Nil
1081+
1082+
def trace: List[CaptureSet] = myTrace
1083+
def addToTrace(cs1: CaptureSet) =
1084+
val res = IncludeFailure(cs, elem, levelError)
1085+
res.myTrace = cs1 :: this.myTrace
1086+
res
1087+
10841088
override def toText(printer: Printer): Text =
10851089
inContext(printer.printerContext):
1086-
this match
1087-
case IncludeFailure(trace) =>
1088-
if ctx.settings.YccDebug.value then printer.toText(trace, ", ")
1089-
else blocking.show
1090-
case LevelError(cs: CaptureSet, elem: Capability) =>
1091-
Str(i"($elem at wrong level for $cs at level ${cs.level.toString})")
1092-
1093-
/** If not isOK, the blocking capture set */
1094-
def blocking: CaptureSet = (this: @unchecked) match
1095-
case IncludeFailure(cs) => cs.last
1096-
case LevelError(cs, _) => cs
1097-
end CompareFailure
1098-
1099-
case class IncludeFailure(trace: List[CaptureSet]) extends CompareFailure
1100-
case class LevelError(cs: CaptureSet, elem: Capability) extends CompareFailure
1090+
if levelError then
1091+
i"($elem at wrong level for $cs at level ${cs.level.toString})"
1092+
else
1093+
if ctx.settings.YccDebug.value
1094+
then i"$elem cannot be included in $trace"
1095+
else i"$elem cannot be included in $cs"
1096+
end IncludeFailure
11011097

11021098
/** A VarState serves as a snapshot mechanism that can undo
11031099
* additions of elements or super sets if an operation fails

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

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ import util.{SimpleIdentitySet, EqHashMap, EqHashSet, SrcPos, Property}
1818
import transform.{Recheck, PreRecheck, CapturedVars}
1919
import Recheck.*
2020
import scala.collection.mutable
21-
import CaptureSet.{withCaptureSetsExplained, CompareFailure, LevelError, ExistentialSubsumesFailure}
21+
import CaptureSet.{withCaptureSetsExplained, IncludeFailure, ExistentialSubsumesFailure}
2222
import CCState.*
2323
import StdNames.nme
2424
import NameKinds.{DefaultGetterName, WildcardParamName, UniqueNameKind}
@@ -355,18 +355,18 @@ class CheckCaptures extends Recheck, SymTransformer:
355355
def checkOK(res: TypeComparer.CompareResult, prefix: => String, added: Capability | CaptureSet, target: CaptureSet, pos: SrcPos, provenance: => String = "")(using Context): Unit =
356356
res match
357357
case TypeComparer.CompareResult.Fail(notes) =>
358-
val ((res: CompareFailure) :: Nil, otherNotes) =
359-
notes.partition(_.isInstanceOf[CompareFailure]): @unchecked
358+
val ((res: IncludeFailure) :: Nil, otherNotes) =
359+
notes.partition(_.isInstanceOf[IncludeFailure]): @unchecked
360360
def msg(provisional: Boolean) =
361361
def toAdd: String = errorNotes(otherNotes).toAdd.mkString
362362
def descr: String =
363-
val d = res.blocking.description
363+
val d = res.cs.description
364364
if d.isEmpty then provenance else ""
365365
def kind = if provisional then "previously estimated\n" else "allowed "
366-
em"$prefix included in the ${kind}capture set ${res.blocking}$descr$toAdd"
366+
em"$prefix included in the ${kind}capture set ${res.cs}$descr$toAdd"
367367
target match
368368
case target: CaptureSet.Var
369-
if res.blocking.isProvisionallySolved =>
369+
if res.cs.isProvisionallySolved =>
370370
report.warning(
371371
msg(provisional = true)
372372
.prepend(i"Another capture checking run needs to be scheduled because\n"),
@@ -1275,12 +1275,15 @@ class CheckCaptures extends Recheck, SymTransformer:
12751275
type BoxErrors = mutable.ListBuffer[Message] | Null
12761276

12771277
private def errorNotes(notes: List[TypeComparer.ErrorNote])(using Context): Addenda =
1278-
val printableNotes = notes.filter(_.isInstanceOf[LevelError | ExistentialSubsumesFailure])
1278+
val printableNotes = notes.filter:
1279+
case IncludeFailure(_, _, true) => true
1280+
case _: ExistentialSubsumesFailure => true
1281+
case _ => false
12791282
if printableNotes.isEmpty then NothingToAdd
12801283
else new Addenda:
12811284
override def toAdd(using Context) = printableNotes.map: note =>
12821285
val msg = note match
1283-
case LevelError(cs, ref) =>
1286+
case IncludeFailure(cs, ref, _) =>
12841287
if ref.core.isCapOrFresh then
12851288
i"""the universal capability $ref
12861289
|cannot be included in capture set $cs"""

0 commit comments

Comments
 (0)