@@ -11,6 +11,7 @@ import CaptureSet.{Refs, emptySet, HiddenSet}
1111import config .Printers .capt
1212import StdNames .nme
1313import util .{SimpleIdentitySet , EqHashMap , SrcPos }
14+ import tpd .*
1415
1516object SepChecker :
1617
@@ -31,15 +32,14 @@ object SepChecker:
3132 /** The kind of checked type, used for composing error messages */
3233 enum TypeKind :
3334 case Result (sym : Symbol , inferred : Boolean )
34- case Argument
35+ case Argument ( arg : Tree )
3536
3637 def dclSym = this match
3738 case Result (sym, _) => sym
3839 case _ => NoSymbol
3940 end TypeKind
4041
4142class SepChecker (checker : CheckCaptures .CheckerAPI ) extends tpd.TreeTraverser :
42- import tpd .*
4343 import checker .*
4444 import SepChecker .*
4545
@@ -214,7 +214,7 @@ class SepChecker(checker: CheckCaptures.CheckerAPI) extends tpd.TreeTraverser:
214214 for (arg, idx) <- indexedArgs do
215215 if arg.needsSepCheck then
216216 val ac = formalCaptures(arg)
217- checkType(arg.formalType, arg.srcPos, TypeKind .Argument )
217+ checkType(arg.formalType, arg.srcPos, TypeKind .Argument (arg) )
218218 val hiddenInArg = ac.hidden.footprint
219219 // println(i"check sep $arg: $ac, footprint so far = $footprint, hidden = $hiddenInArg")
220220 val overlap = hiddenInArg.overlapWith(footprint).deductCapturesOf(deps(arg))
@@ -252,9 +252,9 @@ class SepChecker(checker: CheckCaptures.CheckerAPI) extends tpd.TreeTraverser:
252252 case TypeKind .Result (sym, inferred) =>
253253 def inferredStr = if inferred then " inferred" else " "
254254 def resultStr = if sym.info.isInstanceOf [MethodicType ] then " result" else " "
255- i " $sym's $inferredStr$resultStr"
256- case TypeKind .Argument =>
257- " the argument's adapted type "
255+ i " $sym's $inferredStr$resultStr"
256+ case TypeKind .Argument (_) =>
257+ " the argument's adapted"
258258
259259 def explicitRefs (tp : Type ): Refs = tp match
260260 case tp : (TermRef | ThisType ) => SimpleIdentitySet (tp)
@@ -292,7 +292,7 @@ class SepChecker(checker: CheckCaptures.CheckerAPI) extends tpd.TreeTraverser:
292292 .nextOption
293293 .getOrElse((" " , current, globalOverlap))
294294 report.error(
295- em """ Separation failure in $typeDescr type $tpe.
295+ em """ Separation failure in $typeDescr type $tpe.
296296 |One part, $part , $nextRel ${CaptureSet (next)}.
297297 |A previous part $prevStr $prevRel ${CaptureSet (prevRefs)}.
298298 |The two sets overlap at ${CaptureSet (overlap)}. """ ,
@@ -346,10 +346,10 @@ class SepChecker(checker: CheckCaptures.CheckerAPI) extends tpd.TreeTraverser:
346346 case t =>
347347 foldOver(c, t)
348348
349- def checkParameters ( ) =
349+ def checkParams ( refsToCheck : Refs , descr : => String ) =
350350 val badParams = mutable.ListBuffer [Symbol ]()
351351 def currentOwner = kind.dclSym.orElse(ctx.owner)
352- for hiddenRef <- prune(tpe.deepCaptureSet.elems.hidden .footprint) do
352+ for hiddenRef <- prune(refsToCheck .footprint) do
353353 val refSym = hiddenRef.termSymbol
354354 if refSym.is(TermParam )
355355 && ! refSym.hasAnnotation(defn.ConsumeAnnot )
@@ -364,25 +364,29 @@ class SepChecker(checker: CheckCaptures.CheckerAPI) extends tpd.TreeTraverser:
364364 case p :: ps => i " ${p.name}, ${paramsStr(ps)}"
365365 val (pluralS, singleS) = if badParams.tail.isEmpty then (" " , " s" ) else (" s" , " " )
366366 report.error(
367- em """ Separation failure: $typeDescr type $tpe hides parameter $pluralS ${paramsStr(badParams.toList)}
367+ em """ Separation failure: $descr parameter $pluralS ${paramsStr(badParams.toList)}.
368368 |The parameter $pluralS need $singleS to be annotated with @consume to allow this. """ ,
369369 pos)
370370
371- def flagHiddenParams =
372- kind match
373- case TypeKind .Result (sym, _) =>
374- ! sym.isAnonymousFunction // we don't check return types of anonymous functions
375- && ! sym.is(Case ) // We don't check so far binders in patterns since they
376- // have inferred universal types. TODO come back to this;
377- // either infer more precise types for such binders or
378- // "see through them" when we look at hidden sets.
379- case TypeKind .Argument =>
380- false
371+ def checkParameters () = kind match
372+ case TypeKind .Result (sym, _) =>
373+ if ! sym.isAnonymousFunction // we don't check return types of anonymous functions
374+ && ! sym.is(Case ) // We don't check so far binders in patterns since they
375+ // have inferred universal types. TODO come back to this;
376+ // either infer more precise types for such binders or
377+ // "see through them" when we look at hidden sets.
378+ then checkParams(tpe.deepCaptureSet.elems.hidden, i " $typeDescr type $tpe hides " )
379+ case TypeKind .Argument (arg) =>
380+ if tpe.hasAnnotation(defn.ConsumeAnnot ) then
381+ val capts = captures(arg)
382+ def descr (verb : String ) = i " argument to @consume parameter with type ${arg.nuType} $verb"
383+ checkParams(capts, descr(" refers to" ))
384+ checkParams(capts.hidden, descr(" hides" ))
381385
382386 if ! tpe.hasAnnotation(defn.UntrackedCapturesAnnot ) then
383387 traverse(Captures .None , tpe)
384388 traverse.toCheck.foreach(checkParts)
385- if flagHiddenParams then checkParameters()
389+ checkParameters()
386390 end checkType
387391
388392 private def collectMethodTypes (tp : Type ): List [TermLambda ] = tp match
0 commit comments