Skip to content

Commit a909249

Browse files
committed
Make static TermRefs trackable capabilities
Also: - Add interpolation of types of module vals, so that we can decide whether they are tracked or not - Treat non-capture checked global refs as non-trackable
1 parent 5676b7e commit a909249

File tree

8 files changed

+35
-5
lines changed

8 files changed

+35
-5
lines changed

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

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -432,11 +432,18 @@ object Capabilities:
432432
core.isInstanceOf[RootCapability]
433433

434434
/** Is the reference tracked? This is true if it can be tracked and the capture
435-
* set of the underlying type is not always empty.
435+
* set of the underlying type is not always empty. Also excluded are references
436+
* that come from source files that were not capture checked and that have
437+
* `Fluid` capture sets.
436438
*/
437439
final def isTracked(using Context): Boolean = this.core match
438440
case _: RootCapability => true
439-
case tp: CoreCapability => tp.isTrackableRef && !captureSetOfInfo.isAlwaysEmpty
441+
case tp: CoreCapability =>
442+
tp.isTrackableRef
443+
&& {
444+
val cs = captureSetOfInfo
445+
!cs.isAlwaysEmpty && cs != CaptureSet.Fluid
446+
}
440447

441448
/** An exclusive capability is a capability that derives
442449
* indirectly from a maximal capability without going through

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -117,7 +117,7 @@ extension (tp: Type)
117117
!tp.underlying.exists // might happen during construction of lambdas with annotations on parameters
118118
||
119119
((tp.prefix eq NoPrefix)
120-
|| tp.symbol.isField && !tp.symbol.isStatic && tp.prefix.isTrackableRef
120+
|| tp.symbol.isField && tp.prefix.isTrackableRef
121121
) && !tp.symbol.isOneOf(UnstableValueFlags)
122122
case tp: TypeRef =>
123123
tp.symbol.isType && tp.derivesFrom(defn.Caps_CapSet)

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

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -389,6 +389,9 @@ class CheckCaptures extends Recheck, SymTransformer:
389389

390390
/** If `tpt` is an inferred type, interpolate capture set variables appearing contra-
391391
* variantly in it. Also anchor Fresh instances with anchorCaps.
392+
* Note: module vals don't have inferred types but still hold capture set variables.
393+
* These capture set variables are interpolated after the associated module class
394+
* has been rechecked.
392395
*/
393396
private def interpolateIfInferred(tpt: Tree, sym: Symbol)(using Context): Unit =
394397
if tpt.isInstanceOf[InferredTypeTree] then
@@ -1517,6 +1520,8 @@ class CheckCaptures extends Recheck, SymTransformer:
15171520
finally
15181521
checkExplicitUses(cls)
15191522
checkExplicitUses(cls.primaryConstructor)
1523+
if cls.is(ModuleClass) then
1524+
interpolate(cls.sourceModule.info, cls.sourceModule)
15201525
completed += cls
15211526
curEnv = saved
15221527
end recheckClassDef

compiler/src/dotty/tools/dotc/core/SymUtils.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -313,7 +313,7 @@ class SymUtils:
313313
}
314314

315315
def isField(using Context): Boolean =
316-
self.isTerm && !self.isOneOf(Method | PhantomSymbol | NonMember)
316+
self.isTerm && !self.isOneOf(Method | PhantomSymbol | NonMember | Package)
317317

318318
def isEnumCase(using Context): Boolean =
319319
self.isAllOf(EnumCase, butNot = JavaDefined)

library/src/scala/collection/mutable/LongMap.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -594,7 +594,7 @@ object LongMap {
594594
private final val VacantBit = 0x4000_0000
595595
private final val MissVacant = 0xC000_0000
596596

597-
private val exceptionDefault: Long => Nothing = (k: Long) => throw new NoSuchElementException(k.toString)
597+
private val exceptionDefault: Long -> Nothing = (k: Long) => throw new NoSuchElementException(k.toString)
598598

599599
/** A builder for instances of `LongMap`.
600600
*

tests/neg/mixed_cc.check

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
-- Warning: tests/neg/mixed_cc/B.scala:4:4 -----------------------------------------------------------------------------
2+
4 |val x: Object^{A.B} = ??? // error
3+
| ^
4+
| value x has a non-empty capture set but will not be added as
5+
| a capability to computed capture sets since it is globally accessible
6+
| as a top-level definition. Global values cannot be capabilities.
7+
-- Error: tests/neg/mixed_cc/B.scala:4:7 -------------------------------------------------------------------------------
8+
4 |val x: Object^{A.B} = ??? // error
9+
| ^^^^^^^^^^^^
10+
| mixed_cc.A.B.type cannot be tracked since its capture set is empty

tests/neg/mixed_cc/A.scala

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
package mixed_cc
2+
3+
object A:
4+
object B

tests/neg/mixed_cc/B.scala

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
package mixed_cc
2+
import language.experimental.captureChecking
3+
4+
val x: Object^{A.B} = ??? // error

0 commit comments

Comments
 (0)