Skip to content

Commit

Permalink
Polishing and change printing options
Browse files Browse the repository at this point in the history
  • Loading branch information
odersky committed Oct 18, 2023
1 parent c3b2f8a commit a6624de
Show file tree
Hide file tree
Showing 11 changed files with 124 additions and 117 deletions.
2 changes: 1 addition & 1 deletion compiler/src/dotty/tools/dotc/ast/TreeInfo.scala
Original file line number Diff line number Diff line change
Expand Up @@ -810,7 +810,7 @@ trait TypedTreeInfo extends TreeInfo[Type] { self: Trees.Instance[Type] =>
}
}

/** An extractor for def of a closure contained the block of the closure,
/** An extractor for the method of a closure contained the block of the closure,
* possibly with type ascriptions.
*/
object possiblyTypedClosureDef:
Expand Down
34 changes: 19 additions & 15 deletions compiler/src/dotty/tools/dotc/cc/CaptureOps.scala
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import Types.*, Symbols.*, Contexts.*, Annotations.*, Flags.*
import ast.{tpd, untpd}
import Decorators.*, NameOps.*
import config.SourceVersion
import config.Printers.{capt, ccSetup}
import config.Printers.capt
import util.Property.Key
import tpd.*
import StdNames.nme
Expand All @@ -24,10 +24,13 @@ object ccConfig:
*/
private[cc] val adaptUnpickledFunctionTypes = false

/** If true, use `sealed` as encapsulation mechanism instead of the
* previous global retriction that `cap` can't be boxed or unboxed.
*/
def allowUniversalInBoxed(using Context) =
Feature.sourceVersion.isAtLeast(SourceVersion.`3.3`)
end ccConfig

def allowUniversalInBoxed(using Context) =
Feature.sourceVersion.isAtLeast(SourceVersion.`3.3`)

/** Are we at checkCaptures phase? */
def isCaptureChecking(using Context): Boolean =
Expand Down Expand Up @@ -251,13 +254,12 @@ extension (tp: Type)
extension (cls: ClassSymbol)

def pureBaseClass(using Context): Option[Symbol] =
if cls.isClass then cls.asClass.baseClasses.find: bc =>
cls.baseClasses.find: bc =>
defn.pureBaseClasses.contains(bc)
|| bc.givenSelfType.dealiasKeepAnnots.match
case CapturingType(_, refs) => refs.isAlwaysEmpty
case RetainingType(_, refs) => refs.isEmpty
case selfType => selfType.exists && selfType.captureSet.isAlwaysEmpty
else None

extension (sym: Symbol)

Expand Down Expand Up @@ -303,19 +305,15 @@ extension (sym: Symbol)
&& sym != defn.Caps_unsafeBox
&& sym != defn.Caps_unsafeUnbox

def isTrackedSomewhere(using Context): Boolean =
val search = new TypeAccumulator[Boolean]:
def apply(found: Boolean, tp: Type) =
def isTrackedHere = variance >= 0 && !tp.captureSet.isAlwaysEmpty
found || isTrackedHere || foldOver(found, tp)
search(false, sym.info)

// TODO Also include vals (right now they are manually entered in levelOwners by Setup)
/** Can this symbol possibly own a local root?
* TODO: Disallow anonymous functions?
*/
def isLevelOwner(using Context): Boolean =
sym.isClass
|| sym.is(Method, butNot = Accessor)// && !sym.isAnonymousFunction // TODO enable?
|| sym.is(Method, butNot = Accessor)

/** The level owner enclosing `sym` which has the given name, or NoSymbol if none exists.
/** The level owner enclosing `sym` which has the given name, or NoSymbol
* if none exists.
*/
def levelOwnerNamed(name: String)(using Context): Symbol =
def recur(sym: Symbol): Symbol =
Expand Down Expand Up @@ -347,11 +345,17 @@ extension (sym: Symbol)
nme.LOCAL_CAPTURE_ROOT, Synthetic, defn.Caps_Cap.typeRef)
ccState.localRoots.getOrElseUpdate(owner, newRoot)

/** The outermost symbol owned by both `sym` and `other`. if none exists
* since the owning scopes of `sym` and `other` are not nested, invoke
* `onConflict` to return a symbol.
*/
def maxNested(other: Symbol, onConflict: (Symbol, Symbol) => Context ?=> Symbol)(using Context): Symbol =
if !sym.exists || other.isContainedIn(sym) then other
else if !other.exists || sym.isContainedIn(other) then sym
else onConflict(sym, other)

/** The innermost symbol owning both `sym` and `other`.
*/
def minNested(other: Symbol)(using Context): Symbol =
if !other.exists || other.isContainedIn(sym) then sym
else if !sym.exists || sym.isContainedIn(other) then other
Expand Down
96 changes: 38 additions & 58 deletions compiler/src/dotty/tools/dotc/cc/CaptureSet.scala
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,15 @@ package cc

import core.*
import Types.*, Symbols.*, Flags.*, Contexts.*, Decorators.*
import config.Printers.{capt, ccSetup}
import config.Printers.capt
import Annotations.Annotation
import annotation.threadUnsafe
import annotation.constructorOnly
import annotation.internal.sharable
import reporting.trace
import printing.{Showable, Printer}
import printing.Texts.*
import util.{SimpleIdentitySet, Property, optional}, optional.{break, ?}
import util.{SimpleIdentitySet, Property}
import typer.ErrorReporting.Addenda
import util.common.alwaysTrue
import scala.collection.mutable
Expand Down Expand Up @@ -84,23 +84,13 @@ sealed abstract class CaptureSet extends Showable:
final def containsRoot(using Context) =
elems.exists(_.isRootCapability)

/** Does this capture set disallow an addiiton of `cap`, whereas it
* might allow an addition of a local root?
*/
final def disallowsUniversal(using Context) =
if isConst then !isUniversal && elems.exists(_.isLocalRootCapability)
else asVar.noUniversal

/** Add new elements to this capture set if allowed.
* @pre `newElems` is not empty and does not overlap with `this.elems`.
* Constant capture sets never allow to add new elements.
* Variables allow it if and only if the new elements can be included
* in all their dependent sets.
* @param origin The set where the elements come from, or `empty` if not known.
* @return CompareResult.OK if elements were added, or a conflicting
* capture set that prevents addition otherwise.
*/
protected final def tryInclude(newElems: Refs, origin: CaptureSet)(using Context, VarState): CompareResult =
(CompareResult.OK /: newElems): (r, elem) =>
r.andAlso(tryInclude(elem, origin))

/** Try to include an element in this capture set.
* @param elem The element to be added
* @param origin The set that originated the request, or `empty` if the request came from outside.
Expand All @@ -124,6 +114,11 @@ sealed abstract class CaptureSet extends Showable:
if accountsFor(elem) then CompareResult.OK
else addNewElem(elem)

/** Try to include all element in `refs` to this capture set. */
protected final def tryInclude(newElems: Refs, origin: CaptureSet)(using Context, VarState): CompareResult =
(CompareResult.OK /: newElems): (r, elem) =>
r.andAlso(tryInclude(elem, origin))

/** Add an element to this capture set, assuming it is not already accounted for,
* and omitting any mapping or filtering.
*
Expand All @@ -132,12 +127,14 @@ sealed abstract class CaptureSet extends Showable:
* capture set.
*/
protected final def addNewElem(elem: CaptureRef)(using Context, VarState): CompareResult =
if elem.isRootCapability || summon[VarState] == FrozenState then addThisElem(elem)
else addThisElem(elem).orElse:
val underlying = elem.captureSetOfInfo
tryInclude(underlying.elems, this).andAlso:
underlying.addDependent(this)
CompareResult.OK
if elem.isRootCapability || summon[VarState] == FrozenState then
addThisElem(elem)
else
addThisElem(elem).orElse:
val underlying = elem.captureSetOfInfo
tryInclude(underlying.elems, this).andAlso:
underlying.addDependent(this)
CompareResult.OK

/** Add new elements one by one using `addNewElem`, abort on first failure */
protected final def addNewElems(newElems: Refs)(using Context, VarState): CompareResult =
Expand All @@ -146,7 +143,7 @@ sealed abstract class CaptureSet extends Showable:

/** Add a specific element, assuming it is not already accounted for,
* and omitting any mapping or filtering, without possibility to backtrack
* to underlying capture set
* to the underlying capture set.
*/
protected def addThisElem(elem: CaptureRef)(using Context, VarState): CompareResult

Expand All @@ -157,29 +154,14 @@ sealed abstract class CaptureSet extends Showable:
protected def addAsDependentTo(cs: CaptureSet)(using Context): this.type =
cs.addDependent(this)(using ctx, UnrecordedState)
this
/*
/** Try to include all references of `elems` that are not yet accounted for by this
* capture set. Inclusion is via `addNewElems`.
* @param origin The set where the elements come from, or `empty` if not known.
* @return CompareResult.OK if all unaccounted elements could be added,
* capture set that prevents addition otherwise.
*/
protected final def tryInclude(elems: Refs, origin: CaptureSet)(using Context, VarState): CompareResult =
val unaccounted = elems.filter(!accountsFor(_))
if unaccounted.isEmpty then CompareResult.OK
else tryInclude(unaccounted, origin)

/** Equivalent to `tryInclude({elem}, origin)`, but more efficient */
protected final def tryInclude(elem: CaptureRef, origin: CaptureSet)(using Context, VarState): CompareResult =
if accountsFor(elem) then CompareResult.OK
else tryInclude(elem, origin)
*/
/* x subsumes y if one of the following is true:
* - x is the same as y,
* - x is a this reference and y refers to a field of x
* - x and y are local roots and y is an enclosing root of x
*/
extension (x: CaptureRef)(using Context)

/* x subsumes y if one of the following is true:
* - x is the same as y,
* - x is a this reference and y refers to a field of x
* - x is a super root of y
*/
private def subsumes(y: CaptureRef) =
(x eq y)
|| x.isSuperRootOf(y)
Expand All @@ -193,8 +175,8 @@ sealed abstract class CaptureSet extends Showable:
*/
private def isSuperRootOf(y: CaptureRef): Boolean = x match
case x: TermRef =>
if x.isUniversalRootCapability then true
else if x.isLocalRootCapability && !y.isUniversalRootCapability then
x.isUniversalRootCapability
|| x.isLocalRootCapability && !y.isUniversalRootCapability && {
val xowner = x.localRootOwner
y match
case y: TermRef =>
Expand All @@ -203,7 +185,7 @@ sealed abstract class CaptureSet extends Showable:
xowner.isContainedIn(y.cls)
case _ =>
false
else false
}
case _ => false
end extension

Expand Down Expand Up @@ -548,14 +530,14 @@ object CaptureSet:
private def levelOK(elem: CaptureRef)(using Context): Boolean =
if elem.isUniversalRootCapability then !noUniversal
else !levelLimit.exists
|| elem.match
case elem: TermRef =>
var sym = elem.symbol
if sym.isLevelOwner then sym = sym.owner
levelLimit.isContainedIn(sym.levelOwner)
case elem: ThisType =>
levelLimit.isContainedIn(elem.cls.levelOwner)
case _ => true
|| elem.match
case elem: TermRef =>
var sym = elem.symbol
if sym.isLevelOwner then sym = sym.owner
levelLimit.isContainedIn(sym.levelOwner)
case elem: ThisType =>
levelLimit.isContainedIn(elem.cls.levelOwner)
case _ => true

def addDependent(cs: CaptureSet)(using Context, VarState): CompareResult =
if (cs eq this) || cs.isUniversal || isConst then
Expand Down Expand Up @@ -1015,10 +997,8 @@ object CaptureSet:

/** The capture set of the type underlying CaptureRef */
def ofInfo(ref: CaptureRef)(using Context): CaptureSet = ref match
case ref: TermRef if ref.isRootCapability =>
ref.singletonCaptureSet
case _ =>
ofType(ref.underlying, followResult = true)
case ref: TermRef if ref.isRootCapability => ref.singletonCaptureSet
case _ => ofType(ref.underlying, followResult = true)

/** Capture set of a type */
def ofType(tp: Type, followResult: Boolean)(using Context): CaptureSet =
Expand Down
2 changes: 1 addition & 1 deletion compiler/src/dotty/tools/dotc/cc/CapturingType.scala
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ object CapturingType:
/** Smart constructor that
* - drops empty capture sets
* - drops a capability class expansion if it is further refined with another capturing type
* - fuses compatible capturiong types.
* - fuses compatible capturing types.
* An outer type capturing type A can be fused with an inner capturing type B if their
* boxing status is the same or if A is boxed.
*/
Expand Down
Loading

0 comments on commit a6624de

Please sign in to comment.