Skip to content

Commit 515c3e1

Browse files
authored
Refactorings for CC error reporting (#23260)
Be more systematic which error are added to messages. Harmonize treatment in TypeComparer, CaptureSet, and Capability. Now, all their comparison operations return boolean results and can additionally install error notes in the current TypeComparer. Error notes are shown if they are relevant for the overall outcome of the comparison.
2 parents f906270 + 4e9ebec commit 515c3e1

33 files changed

+312
-268
lines changed

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

Lines changed: 1 addition & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ package dotc
33
package cc
44

55
import core.*
6-
import CaptureSet.{CompareResult, CompareFailure, VarState}
6+
import CaptureSet.VarState
77
import collection.mutable
88
import reporting.Message
99
import Contexts.Context
@@ -16,24 +16,6 @@ class CCState:
1616

1717
// ------ Error diagnostics -----------------------------
1818

19-
/** Error reprting notes produces since the last call to `test` */
20-
var notes: List[ErrorNote] = Nil
21-
22-
def addNote(note: ErrorNote): Unit =
23-
if !notes.exists(_.getClass == note.getClass) then
24-
notes = note :: notes
25-
26-
def test(op: => CompareResult): CompareResult =
27-
val saved = notes
28-
notes = Nil
29-
try op match
30-
case res: CompareFailure => res.withNotes(notes)
31-
case res => res
32-
finally notes = saved
33-
34-
def testOK(op: => Boolean): CompareResult =
35-
test(if op then CompareResult.OK else CompareResult.Fail(Nil))
36-
3719
/** Warnings relating to upper approximations of capture sets with
3820
* existentially bound variables.
3921
*/

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

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@ object Capabilities:
5858
trait RootCapability extends Capability:
5959
val rootId = nextRootId
6060
nextRootId += 1
61+
def descr(using Context): String
6162

6263
/** The base trait of all capabilties represented as types */
6364
trait CoreCapability extends TypeProxy, Capability:
@@ -120,6 +121,7 @@ object Capabilities:
120121
*/
121122
@sharable // We override below all operations that access internal capability state
122123
object GlobalCap extends RootCapability:
124+
def descr(using Context) = "the universal root capability"
123125
override val maybe = Maybe(this)
124126
override val readOnly = ReadOnly(this)
125127
override def reach = unsupported("cap.reach")
@@ -136,13 +138,21 @@ object Capabilities:
136138
* for diagnostics
137139
*/
138140
case class FreshCap private (owner: Symbol, origin: Origin)(using @constructorOnly ctx: Context) extends RootCapability:
139-
val hiddenSet = CaptureSet.HiddenSet(owner)
140-
hiddenSet.owningCap = this
141+
val hiddenSet = CaptureSet.HiddenSet(owner, this: @unchecked)
142+
// fails initialization check without the @unchecked
141143

142144
override def equals(that: Any) = that match
143145
case that: FreshCap => this eq that
144146
case _ => false
145147

148+
def descr(using Context) =
149+
val originStr = origin match
150+
case Origin.InDecl(sym) if sym.exists =>
151+
origin.explanation
152+
case _ =>
153+
i" created in ${hiddenSet.owner.sanitizedDescription}${origin.explanation}"
154+
i"a fresh root capability$originStr"
155+
146156
object FreshCap:
147157
def apply(origin: Origin)(using Context): FreshCap | GlobalCap.type =
148158
if ccConfig.useSepChecks then FreshCap(ctx.owner, origin)
@@ -225,6 +235,9 @@ object Capabilities:
225235
rcap.myOrigin = primary
226236
primary.variants += rcap
227237
rcap
238+
239+
def descr(using Context) =
240+
i"a root capability associated with the result type of $binder"
228241
end ResultCap
229242

230243
/** A trait for references in CaptureSets. These can be NamedTypes, ThisTypes or ParamRefs,
@@ -545,7 +558,7 @@ object Capabilities:
545558
case y: ResultCap => vs.unify(x, y)
546559
case _ => y.derivesFromSharedCapability
547560
if !result then
548-
ccState.addNote(CaptureSet.ExistentialSubsumesFailure(x, y))
561+
TypeComparer.addErrorNote(CaptureSet.ExistentialSubsumesFailure(x, y))
549562
result
550563
case GlobalCap =>
551564
y match

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

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -41,9 +41,6 @@ def depFun(args: List[Type], resultType: Type, isContextual: Boolean, paramNames
4141
/** An exception thrown if a @retains argument is not syntactically a Capability */
4242
class IllegalCaptureRef(tpe: Type)(using Context) extends Exception(tpe.show)
4343

44-
/** A base trait for data producing addenda to error messages */
45-
trait ErrorNote
46-
4744
/** The currently valid CCState */
4845
def ccState(using Context): CCState =
4946
Phases.checkCapturesPhase.asInstanceOf[CheckCaptures].ccState1
@@ -157,7 +154,7 @@ extension (tp: Type)
157154
* the two capture sets are combined.
158155
*/
159156
def capturing(cs: CaptureSet)(using Context): Type =
160-
if (cs.isAlwaysEmpty || cs.isConst && cs.subCaptures(tp.captureSet, VarState.Separate).isOK)
157+
if (cs.isAlwaysEmpty || cs.isConst && cs.subCaptures(tp.captureSet, VarState.Separate))
161158
&& !cs.keepAlways
162159
then tp
163160
else tp match

0 commit comments

Comments
 (0)