@@ -777,7 +777,7 @@ object CaptureSet:
777777 assert(elem.subsumes(elem1),
778778 i " Skipped map ${tm.getClass} maps newly added $elem to $elem1 in $this" )
779779
780- protected def includeElem (elem : Capability )(using Context ): Unit =
780+ protected def includeElem (elem : Capability )(using Context , VarState ): Unit =
781781 if ! elems.contains(elem) then
782782 if debugVars && id == debugTarget then
783783 println(i " ###INCLUDE $elem in $this" )
@@ -803,7 +803,10 @@ object CaptureSet:
803803 // id == 108 then assert(false, i"trying to add $elem to $this")
804804 assert(elem.isWellformed, elem)
805805 assert(! this .isInstanceOf [HiddenSet ] || summon[VarState ].isSeparating, summon[VarState ])
806- includeElem(elem)
806+ try includeElem(elem)
807+ catch case ex : AssertionError =>
808+ println(i " error for incl $elem in $this, ${summon[VarState ].toString}" )
809+ throw ex
807810 if isBadRoot(elem) then
808811 rootAddedHandler()
809812 val normElem = if isMaybeSet then elem else elem.stripMaybe
@@ -947,16 +950,66 @@ object CaptureSet:
947950 override def toString = s " Var $id$elems"
948951 end Var
949952
950- /** Variables that represent refinements of class parameters can have the universal
951- * capture set, since they represent only what is the result of the constructor.
952- * Test case: Without that tweak, logger.scala would not compile.
953- */
954- class RefiningVar (owner : Symbol )(using Context ) extends Var (owner):
955- override def disallowBadRoots (upto : Symbol )(handler : () => Context ?=> Unit )(using Context ) = this
953+ inline val strictFreshLevels = true
956954
957955 /** Variables created in types of inferred type trees */
958- class ProperVar (override val owner : Symbol , initialElems : Refs , nestedOK : Boolean )(using /* @constructorOnly*/ ictx : Context )
959- extends Var (owner, initialElems, nestedOK)
956+ class ProperVar (override val owner : Symbol , initialElems : Refs = emptyRefs, nestedOK : Boolean = true , isRefining : Boolean )(using /* @constructorOnly*/ ictx : Context )
957+ extends Var (owner, initialElems, nestedOK):
958+
959+ /** Make sure that capset variables in types of vals and result types of
960+ * non-anonymous functions contain only a single FreshCap, and furthermore
961+ * that that FreshCap has as origin InDecl(owner), where owner is the val
962+ * or def for which the type is defined.
963+ * Note: This currently does not apply to classified or read-only fresh caps.
964+ */
965+ override def includeElem (elem : Capability )(using ctx : Context , vs : VarState ): Unit = elem match
966+ case elem : FreshCap
967+ if ! nestedOK
968+ && ! elems.contains(elem)
969+ && ! owner.isAnonymousFunction
970+ && ccConfig.newScheme =>
971+ def fail = i " attempting to add $elem to $this"
972+ def hideIn (fc : FreshCap ): Unit =
973+ assert(elem.tryClassifyAs(fc.hiddenSet.classifier), fail)
974+ if strictFreshLevels && ! isRefining then
975+ // If a variable is added by addCaptureRefinements in a synthetic
976+ // refinement of a class type, don't do level checking. The problem is
977+ // that the variable might be matched against a type that does not have
978+ // a refinement, in which case FreshCaps of the class definition would
979+ // leak out in the corresponding places. This will fail level checking.
980+ // The disallowBadRoots override below has a similar reason.
981+ // TODO: We should instead mark the variable as impossible to instantiate
982+ // and drop the refinement later in the inferred type.
983+ // Test case is drop-refinement.scala.
984+ assert(fc.acceptsLevelOf(elem),
985+ i " level failure, cannot add $elem with ${elem.levelOwner} to $owner / $getClass / $fail" )
986+ fc.hiddenSet.add(elem)
987+ val isSubsumed = (false /: elems): (isSubsumed, prev) =>
988+ prev match
989+ case prev : FreshCap =>
990+ hideIn(prev)
991+ true
992+ case _ => isSubsumed
993+ if ! isSubsumed then
994+ if elem.origin != Origin .InDecl (owner) || elem.hiddenSet.isConst then
995+ val fc = new FreshCap (owner, Origin .InDecl (owner))
996+ assert(fc.tryClassifyAs(elem.hiddenSet.classifier), fail)
997+ hideIn(fc)
998+ super .includeElem(fc)
999+ else
1000+ super .includeElem(elem)
1001+ case _ =>
1002+ super .includeElem(elem)
1003+
1004+ /** Variables that represent refinements of class parameters can have the universal
1005+ * capture set, since they represent only what is the result of the constructor.
1006+ * Test case: Without that tweak, logger.scala would not compile.
1007+ */
1008+ override def disallowBadRoots (upto : Symbol )(handler : () => Context ?=> Unit )(using Context ) =
1009+ if isRefining then this
1010+ else super .disallowBadRoots(upto)(handler)
1011+
1012+ end ProperVar
9601013
9611014 /** A variable that is derived from some other variable via a map or filter. */
9621015 abstract class DerivedVar (owner : Symbol , initialElems : Refs )(using @ constructorOnly ctx : Context )
0 commit comments