@@ -18,7 +18,7 @@ import util.{SimpleIdentitySet, EqHashMap, EqHashSet, SrcPos, Property}
1818import transform .{Recheck , PreRecheck , CapturedVars }
1919import Recheck .*
2020import scala .collection .mutable
21- import CaptureSet .{withCaptureSetsExplained , IdempotentCaptRefMap , CompareResult }
21+ import CaptureSet .{withCaptureSetsExplained , IdempotentCaptRefMap , CompareResult , ExistentialSubsumesFailure }
2222import CCState .*
2323import StdNames .nme
2424import NameKinds .{DefaultGetterName , WildcardParamName , UniqueNameKind }
@@ -354,7 +354,7 @@ class CheckCaptures extends Recheck, SymTransformer:
354354 def checkOK (res : CompareResult , prefix : => String , added : CaptureRef | CaptureSet , pos : SrcPos , provenance : => String = " " )(using Context ): Unit =
355355 if ! res.isOK then
356356 inContext(root.printContext(added, res.blocking)):
357- def toAdd : String = CaptureSet .levelErrors .toAdd.mkString
357+ def toAdd : String = errorNotes(res.errorNotes) .toAdd.mkString
358358 def descr : String =
359359 val d = res.blocking.description
360360 if d.isEmpty then provenance else " "
@@ -363,15 +363,15 @@ class CheckCaptures extends Recheck, SymTransformer:
363363 /** Check subcapturing `{elem} <: cs`, report error on failure */
364364 def checkElem (elem : CaptureRef , cs : CaptureSet , pos : SrcPos , provenance : => String = " " )(using Context ) =
365365 checkOK(
366- elem.singletonCaptureSet.subCaptures(cs),
366+ ccState.test( elem.singletonCaptureSet.subCaptures(cs) ),
367367 i " $elem cannot be referenced here; it is not " ,
368368 elem, pos, provenance)
369369
370370 /** Check subcapturing `cs1 <: cs2`, report error on failure */
371371 def checkSubset (cs1 : CaptureSet , cs2 : CaptureSet , pos : SrcPos ,
372372 provenance : => String = " " , cs1description : String = " " )(using Context ) =
373373 checkOK(
374- cs1.subCaptures(cs2),
374+ ccState.test( cs1.subCaptures(cs2) ),
375375 if cs1.elems.size == 1 then i " reference ${cs1.elems.toList.head}$cs1description is not "
376376 else i " references $cs1$cs1description are not all " ,
377377 cs1, pos, provenance)
@@ -1210,27 +1210,29 @@ class CheckCaptures extends Recheck, SymTransformer:
12101210
12111211 type BoxErrors = mutable.ListBuffer [Message ] | Null
12121212
1213- private def boxErrorAddenda ( boxErrors : BoxErrors ) =
1214- if boxErrors == null then NothingToAdd
1213+ private def errorNotes ( notes : List [ ErrorNote ])( using Context ) : Addenda =
1214+ if notes.isEmpty then NothingToAdd
12151215 else new Addenda :
1216- override def toAdd (using Context ): List [ String ] =
1217- boxErrors.toList.map : msg =>
1218- i """
1219- |
1220- |Note that ${msg.toString} "" "
1221-
1222- private def existentialSubsumesFailureAddenda ( using Context ) : Addenda =
1223- ccState.existentialSubsumesFailure match
1224- case Some ((ex @ root. Result (binder), other)) =>
1225- new Addenda :
1226- override def toAdd ( using Context ) : List [ String ] =
1227- val ann = ex.rootAnnot
1228- i """
1229- |
1230- |Note that the existential capture root in ${ex.rootAnnot.originalBinder.resType}
1216+ override def toAdd (using Context ) = notes.map : note =>
1217+ val msg = note match
1218+ case CompareResult . LevelError (cs, ref) =>
1219+ if ref.stripReadOnly.isCapOrFresh then
1220+ def capStr = if ref.isReadOnly then " cap.rd " else " cap "
1221+ i """ the universal capability ` $capStr `
1222+ |cannot be included in capture set $cs """
1223+ else
1224+ val levelStr = ref match
1225+ case ref : TermRef => i " , defined in ${ref.symbol.maybeOwner} "
1226+ case _ => " "
1227+ i """ reference ${ref}$levelStr
1228+ |cannot be included in outer capture set $cs """
1229+ case ExistentialSubsumesFailure (ex, other) =>
1230+ i """ the existential capture root in ${ex.rootAnnot.originalBinder.resType}
12311231 |cannot subsume the capability $other"""
1232- :: Nil
1233- case _ => NothingToAdd
1232+ i """
1233+ |
1234+ |Note that ${msg.toString}"""
1235+
12341236
12351237 /** Addendas for error messages that show where we have under-approximated by
12361238 * mapping a a capture ref in contravariant position to the empty set because
@@ -1264,15 +1266,14 @@ class CheckCaptures extends Recheck, SymTransformer:
12641266 */
12651267 override def checkConformsExpr (actual : Type , expected : Type , tree : Tree , addenda : Addenda )(using Context ): Type =
12661268 var expected1 = alignDependentFunction(expected, actual.stripCapturing)
1267- val boxErrors = new mutable.ListBuffer [Message ]
1268- val actualBoxed = adapt(actual, expected1, tree, boxErrors)
1269+ val actualBoxed = adapt(actual, expected1, tree)
12691270 // println(i"check conforms $actualBoxed <<< $expected1")
12701271
12711272 if actualBoxed eq actual then
12721273 // Only `addOuterRefs` when there is no box adaptation
12731274 expected1 = addOuterRefs(expected1, actual, tree.srcPos)
1274- ccState.existentialSubsumesFailure = None
1275- if isCompatible(actualBoxed, expected1) then
1275+ val result = ccState.testOK(isCompatible(actualBoxed, expected1))
1276+ if result.isOK then
12761277 if debugSuccesses then tree match
12771278 case Ident (_) =>
12781279 println(i " SUCCESS $tree for $actual <:< $expected: \n ${TypeComparer .explained(_.isSubType(actualBoxed, expected1))}" )
@@ -1283,10 +1284,7 @@ class CheckCaptures extends Recheck, SymTransformer:
12831284 inContext(root.printContext(actualBoxed, expected1)):
12841285 err.typeMismatch(tree.withType(actualBoxed), expected1,
12851286 addApproxAddenda(
1286- addenda
1287- ++ CaptureSet .levelErrors
1288- ++ boxErrorAddenda(boxErrors)
1289- ++ existentialSubsumesFailureAddenda,
1287+ addenda ++ errorNotes(result.errorNotes),
12901288 expected1))
12911289 actual
12921290 end checkConformsExpr
@@ -1397,7 +1395,7 @@ class CheckCaptures extends Recheck, SymTransformer:
13971395 *
13981396 * @param alwaysConst always make capture set variables constant after adaptation
13991397 */
1400- def adaptBoxed (actual : Type , expected : Type , tree : Tree , covariant : Boolean , alwaysConst : Boolean , boxErrors : BoxErrors )(using Context ): Type =
1398+ def adaptBoxed (actual : Type , expected : Type , tree : Tree , covariant : Boolean , alwaysConst : Boolean )(using Context ): Type =
14011399
14021400 def recur (actual : Type , expected : Type , covariant : Boolean ): Type =
14031401
@@ -1551,15 +1549,15 @@ class CheckCaptures extends Recheck, SymTransformer:
15511549 * - narrow nested captures of `x`'s underlying type to `{x*}`
15521550 * - do box adaptation
15531551 */
1554- def adapt (actual : Type , expected : Type , tree : Tree , boxErrors : BoxErrors )(using Context ): Type =
1552+ def adapt (actual : Type , expected : Type , tree : Tree )(using Context ): Type =
15551553 if noWiden(actual, expected) then
15561554 actual
15571555 else
15581556 val improvedVAR = improveCaptures(actual.widen.dealiasKeepAnnots, actual)
15591557 val improved = improveReadOnly(improvedVAR, expected)
15601558 val adapted = adaptBoxed(
15611559 improved.withReachCaptures(actual), expected, tree,
1562- covariant = true , alwaysConst = false , boxErrors )
1560+ covariant = true , alwaysConst = false )
15631561 if adapted eq improvedVAR // no .rd improvement, no box-adaptation
15641562 then actual // might as well use actual instead of improved widened
15651563 else adapted.showing(i " adapt $actual vs $expected = $adapted" , capt)
@@ -1585,7 +1583,7 @@ class CheckCaptures extends Recheck, SymTransformer:
15851583 try
15861584 curEnv = Env (clazz, EnvKind .NestedInOwner , capturedVars(clazz), outer0 = curEnv)
15871585 val adapted =
1588- adaptBoxed(actual, expected1, tree, covariant = true , alwaysConst = true , null )
1586+ adaptBoxed(actual, expected1, tree, covariant = true , alwaysConst = true )
15891587 actual match
15901588 case _ : MethodType =>
15911589 // We remove the capture set resulted from box adaptation for method types,
0 commit comments