@@ -777,7 +777,7 @@ object CaptureSet:
777
777
assert(elem.subsumes(elem1),
778
778
i " Skipped map ${tm.getClass} maps newly added $elem to $elem1 in $this" )
779
779
780
- protected def includeElem (elem : Capability )(using Context ): Unit =
780
+ protected def includeElem (elem : Capability )(using Context , VarState ): Unit =
781
781
if ! elems.contains(elem) then
782
782
if debugVars && id == debugTarget then
783
783
println(i " ###INCLUDE $elem in $this" )
@@ -803,7 +803,10 @@ object CaptureSet:
803
803
// id == 108 then assert(false, i"trying to add $elem to $this")
804
804
assert(elem.isWellformed, elem)
805
805
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
807
810
if isBadRoot(elem) then
808
811
rootAddedHandler()
809
812
val normElem = if isMaybeSet then elem else elem.stripMaybe
@@ -947,16 +950,66 @@ object CaptureSet:
947
950
override def toString = s " Var $id$elems"
948
951
end Var
949
952
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
956
954
957
955
/** 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
960
1013
961
1014
/** A variable that is derived from some other variable via a map or filter. */
962
1015
abstract class DerivedVar (owner : Symbol , initialElems : Refs )(using @ constructorOnly ctx : Context )
0 commit comments