Skip to content

Change cc syntax #17377

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 16 commits into from
May 10, 2023
Merged
Show file tree
Hide file tree
Changes from 15 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 1 addition & 13 deletions compiler/src/dotty/tools/dotc/ast/Desugar.scala
Original file line number Diff line number Diff line change
Expand Up @@ -1824,16 +1824,6 @@ object desugar {
flatTree(pats1 map (makePatDef(tree, mods, _, rhs)))
case ext: ExtMethods =>
Block(List(ext), Literal(Constant(())).withSpan(ext.span))
case CapturingTypeTree(refs, parent) =>
// convert `{refs} T` to `T @retains refs`
// `{refs}-> T` to `-> (T @retainsByName refs)`
def annotate(annotName: TypeName, tp: Tree) =
Annotated(tp, New(scalaAnnotationDot(annotName), List(refs)))
parent match
case ByNameTypeTree(restpt) =>
cpy.ByNameTypeTree(parent)(annotate(tpnme.retainsByName, restpt))
case _ =>
annotate(tpnme.retains, parent)
case f: FunctionWithMods if f.hasErasedParams => makeFunctionWithValDefs(f, pt)
}
desugared.withSpan(tree.span)
Expand Down Expand Up @@ -1927,7 +1917,7 @@ object desugar {
}
tree match
case tree: FunctionWithMods =>
untpd.FunctionWithMods(applyVParams, tree.body, tree.mods, tree.erasedParams)
untpd.FunctionWithMods(applyVParams, result, tree.mods, tree.erasedParams)
case _ => untpd.Function(applyVParams, result)
}
}
Expand Down Expand Up @@ -1993,8 +1983,6 @@ object desugar {
case _ => traverseChildren(tree)
}
}.traverse(body)
case CapturingTypeTree(refs, parent) =>
collect(parent)
case _ =>
}
collect(tree)
Expand Down
17 changes: 8 additions & 9 deletions compiler/src/dotty/tools/dotc/ast/TreeInfo.scala
Original file line number Diff line number Diff line change
Expand Up @@ -223,9 +223,6 @@ trait TreeInfo[T <: Untyped] { self: Trees.Instance[T] =>
/** Strip `=> T` to `T` and (under pureFunctions) `{refs}-> T` to `T` */
def stripByNameType(tree: Tree)(using Context): Tree = unsplice(tree) match
case ByNameTypeTree(t1) => t1
case untpd.CapturingTypeTree(_, parent) =>
val parent1 = stripByNameType(parent)
if parent1 eq parent then tree else parent1
case _ => tree

/** All type and value parameter symbols of this DefDef */
Expand Down Expand Up @@ -473,13 +470,15 @@ trait UntypedTreeInfo extends TreeInfo[Untyped] { self: Trees.Instance[Untyped]
*/
object ImpureByNameTypeTree:

def apply(tp: ByNameTypeTree)(using Context): untpd.CapturingTypeTree =
untpd.CapturingTypeTree(
untpd.captureRoot.withSpan(tp.span.startPos) :: Nil, tp)
def apply(tp: Tree)(using Context): untpd.ByNameTypeTree =
untpd.ByNameTypeTree(
untpd.CapturesAndResult(
untpd.captureRoot.withSpan(tp.span.startPos) :: Nil, tp))

def unapply(tp: Tree)(using Context): Option[ByNameTypeTree] = tp match
case untpd.CapturingTypeTree(id @ Select(_, nme.CAPTURE_ROOT) :: Nil, bntp: ByNameTypeTree)
if id.span == bntp.span.startPos => Some(bntp)
def unapply(tp: Tree)(using Context): Option[Tree] = tp match
case untpd.ByNameTypeTree(
untpd.CapturesAndResult(id @ Select(_, nme.CAPTURE_ROOT) :: Nil, result))
if id.span == result.span.startPos => Some(result)
case _ => None
end ImpureByNameTypeTree
}
Expand Down
17 changes: 10 additions & 7 deletions compiler/src/dotty/tools/dotc/ast/untpd.scala
Original file line number Diff line number Diff line change
Expand Up @@ -148,7 +148,7 @@ object untpd extends Trees.Instance[Untyped] with UntypedTreeInfo {
}

/** {x1, ..., xN} T (only relevant under captureChecking) */
case class CapturingTypeTree(refs: List[Tree], parent: Tree)(implicit @constructorOnly src: SourceFile) extends TypTree
case class CapturesAndResult(refs: List[Tree], parent: Tree)(implicit @constructorOnly src: SourceFile) extends TypTree

/** Short-lived usage in typer, does not need copy/transform/fold infrastructure */
case class DependentTypeTree(tp: List[Symbol] => Type)(implicit @constructorOnly src: SourceFile) extends Tree
Expand Down Expand Up @@ -501,6 +501,9 @@ object untpd extends Trees.Instance[Untyped] with UntypedTreeInfo {
def captureRoot(using Context): Select =
Select(scalaDot(nme.caps), nme.CAPTURE_ROOT)

def makeRetaining(parent: Tree, refs: List[Tree], annotName: TypeName)(using Context): Annotated =
Annotated(parent, New(scalaAnnotationDot(annotName), List(refs)))

def makeConstructor(tparams: List[TypeDef], vparamss: List[List[ValDef]], rhs: Tree = EmptyTree)(using Context): DefDef =
DefDef(nme.CONSTRUCTOR, joinParams(tparams, vparamss), TypeTree(), rhs)

Expand Down Expand Up @@ -658,9 +661,9 @@ object untpd extends Trees.Instance[Untyped] with UntypedTreeInfo {
case tree: Number if (digits == tree.digits) && (kind == tree.kind) => tree
case _ => finalize(tree, untpd.Number(digits, kind))
}
def CapturingTypeTree(tree: Tree)(refs: List[Tree], parent: Tree)(using Context): Tree = tree match
case tree: CapturingTypeTree if (refs eq tree.refs) && (parent eq tree.parent) => tree
case _ => finalize(tree, untpd.CapturingTypeTree(refs, parent))
def CapturesAndResult(tree: Tree)(refs: List[Tree], parent: Tree)(using Context): Tree = tree match
case tree: CapturesAndResult if (refs eq tree.refs) && (parent eq tree.parent) => tree
case _ => finalize(tree, untpd.CapturesAndResult(refs, parent))

def TypedSplice(tree: Tree)(splice: tpd.Tree)(using Context): ProxyTree = tree match {
case tree: TypedSplice if splice `eq` tree.splice => tree
Expand Down Expand Up @@ -723,8 +726,8 @@ object untpd extends Trees.Instance[Untyped] with UntypedTreeInfo {
tree
case MacroTree(expr) =>
cpy.MacroTree(tree)(transform(expr))
case CapturingTypeTree(refs, parent) =>
cpy.CapturingTypeTree(tree)(transform(refs), transform(parent))
case CapturesAndResult(refs, parent) =>
cpy.CapturesAndResult(tree)(transform(refs), transform(parent))
case _ =>
super.transformMoreCases(tree)
}
Expand Down Expand Up @@ -782,7 +785,7 @@ object untpd extends Trees.Instance[Untyped] with UntypedTreeInfo {
this(x, splice)
case MacroTree(expr) =>
this(x, expr)
case CapturingTypeTree(refs, parent) =>
case CapturesAndResult(refs, parent) =>
this(this(x, refs), parent)
case _ =>
super.foldMoreCases(x, tree)
Expand Down
8 changes: 4 additions & 4 deletions compiler/src/dotty/tools/dotc/cc/CaptureSet.scala
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ sealed abstract class CaptureSet extends Showable:
assert(!isConst)
asInstanceOf[Var]

/** Does this capture set contain the root reference `*` as element? */
/** Does this capture set contain the root reference `cap` as element? */
final def isUniversal(using Context) =
elems.exists {
case ref: TermRef => ref.symbol == defn.captureRoot
Expand Down Expand Up @@ -133,7 +133,7 @@ sealed abstract class CaptureSet extends Showable:
* for `x` in a state where we assume all supersets of `x` have just the elements
* known at this point. On the other hand if x's capture set has no known elements,
* a set `cs` might account for `x` only if it subsumes `x` or it contains the
* root capability `*`.
* root capability `cap`.
*/
def mightAccountFor(x: CaptureRef)(using Context): Boolean =
reporting.trace(i"$this mightAccountFor $x, ${x.captureSetOfInfo}?", show = true) {
Expand Down Expand Up @@ -270,7 +270,7 @@ sealed abstract class CaptureSet extends Showable:
def substParams(tl: BindingType, to: List[Type])(using Context) =
map(Substituters.SubstParamsMap(tl, to))

/** Invoke handler if this set has (or later aquires) the root capability `*` */
/** Invoke handler if this set has (or later aquires) the root capability `cap` */
def disallowRootCapability(handler: () => Context ?=> Unit)(using Context): this.type =
if isUniversal then handler()
this
Expand Down Expand Up @@ -372,7 +372,7 @@ object CaptureSet:
def isConst = isSolved
def isAlwaysEmpty = false

/** A handler to be invoked if the root reference `*` is added to this set */
/** A handler to be invoked if the root reference `cap` is added to this set */
var rootAddedHandler: () => Context ?=> Unit = () => ()

var description: String = ""
Expand Down
30 changes: 15 additions & 15 deletions compiler/src/dotty/tools/dotc/cc/CheckCaptures.scala
Original file line number Diff line number Diff line change
Expand Up @@ -52,12 +52,12 @@ object CheckCaptures:
* @param outer0 the next enclosing environment
*/
case class Env(
owner: Symbol,
nestedInOwner: Boolean,
captured: CaptureSet,
isBoxed: Boolean,
outer0: Env | Null
):
owner: Symbol,
nestedInOwner: Boolean,
captured: CaptureSet,
isBoxed: Boolean,
outer0: Env | Null):

def outer = outer0.nn

def isOutermost = outer0 == null
Expand Down Expand Up @@ -433,7 +433,7 @@ class CheckCaptures extends Recheck, SymTransformer:
case defn.FunctionOf(ptformals, _, _)
if ptformals.nonEmpty && ptformals.forall(_.captureSet.isAlwaysEmpty) =>
// Redo setup of the anonymous function so that formal parameters don't
// get capture sets. This is important to avoid false widenings to `*`
// get capture sets. This is important to avoid false widenings to `cap`
// when taking the base type of the actual closures's dependent function
// type so that it conforms to the expected non-dependent function type.
// See withLogFile.scala for a test case.
Expand Down Expand Up @@ -582,7 +582,7 @@ class CheckCaptures extends Recheck, SymTransformer:
refs.disallowRootCapability { () =>
val kind = if tree.isInstanceOf[ValDef] then "mutable variable" else "expression"
report.error(
em"""The $kind's type $wtp is not allowed to capture the root capability `*`.
em"""The $kind's type $wtp is not allowed to capture the root capability `cap`.
|This usually means that a capability persists longer than its allowed lifetime.""",
tree.srcPos)
}
Expand Down Expand Up @@ -768,9 +768,9 @@ class CheckCaptures extends Recheck, SymTransformer:
styp1.capturing(if alwaysConst then CaptureSet(cs1.elems) else cs1).forceBoxStatus(resultBoxed)

if needsAdaptation then
val criticalSet = // the set which is not allowed to have `*`
if covariant then cs1 // can't box with `*`
else expected.captureSet // can't unbox with `*`
val criticalSet = // the set which is not allowed to have `cap`
if covariant then cs1 // can't box with `cap`
else expected.captureSet // can't unbox with `cap`
if criticalSet.isUniversal && expected.isValueType then
// We can't box/unbox the universal capability. Leave `actual` as it is
// so we get an error in checkConforms. This tends to give better error
Expand All @@ -779,11 +779,11 @@ class CheckCaptures extends Recheck, SymTransformer:
println(i"cannot box/unbox $actual vs $expected")
actual
else
// Disallow future addition of `*` to `criticalSet`.
// Disallow future addition of `cap` to `criticalSet`.
criticalSet.disallowRootCapability { () =>
report.error(
em"""$actual cannot be box-converted to $expected
|since one of their capture sets contains the root capability `*`""",
|since one of their capture sets contains the root capability `cap`""",
pos)
}
if !insertBox then // unboxing
Expand Down Expand Up @@ -922,8 +922,8 @@ class CheckCaptures extends Recheck, SymTransformer:
* usingLogFile[box ?1 () -> Unit] { (f: {*} File) => () => { f.write(0) } }
*
* We may propagate `f` into ?1, making ?1 ill-formed.
* This also causes soundness issues, since `f` in ?1 should be widened to `*`,
* giving rise to an error that `*` cannot be included in a boxed capture set.
* This also causes soundness issues, since `f` in ?1 should be widened to `cap`,
* giving rise to an error that `cap` cannot be included in a boxed capture set.
*
* To solve this, we still allow ?1 to capture parameter refs like `f`, but
* compensate this by pushing the widened capture set of `f` into ?1.
Expand Down
2 changes: 1 addition & 1 deletion compiler/src/dotty/tools/dotc/core/Definitions.scala
Original file line number Diff line number Diff line change
Expand Up @@ -968,7 +968,7 @@ class Definitions {
@tu lazy val BreakClass: Symbol = requiredClass("scala.util.boundary.Break")

@tu lazy val CapsModule: Symbol = requiredModule("scala.caps")
@tu lazy val captureRoot: TermSymbol = CapsModule.requiredValue("*")
@tu lazy val captureRoot: TermSymbol = CapsModule.requiredValue("cap")
@tu lazy val CapsUnsafeModule: Symbol = requiredModule("scala.caps.unsafe")
@tu lazy val Caps_unsafeBox: Symbol = CapsUnsafeModule.requiredMethod("unsafeBox")
@tu lazy val Caps_unsafeUnbox: Symbol = CapsUnsafeModule.requiredMethod("unsafeUnbox")
Expand Down
3 changes: 2 additions & 1 deletion compiler/src/dotty/tools/dotc/core/StdNames.scala
Original file line number Diff line number Diff line change
Expand Up @@ -286,7 +286,7 @@ object StdNames {
// ----- Term names -----------------------------------------

// Compiler-internal
val CAPTURE_ROOT: N = "*"
val CAPTURE_ROOT: N = "cap"
val CONSTRUCTOR: N = "<init>"
val STATIC_CONSTRUCTOR: N = "<clinit>"
val EVT2U: N = "evt2u$"
Expand All @@ -301,6 +301,7 @@ object StdNames {
val THROWS: N = "$throws"
val U2EVT: N = "u2evt$"
val ALLARGS: N = "$allArgs"
val UPARROW: N = "^"

final val Nil: N = "Nil"
final val Predef: N = "Predef"
Expand Down
8 changes: 4 additions & 4 deletions compiler/src/dotty/tools/dotc/core/Types.scala
Original file line number Diff line number Diff line change
Expand Up @@ -2102,7 +2102,7 @@ object Types {
*/
final def isTracked(using Context): Boolean = canBeTracked && !captureSetOfInfo.isAlwaysEmpty

/** Is this reference the root capability `*` ? */
/** Is this reference the root capability `cap` ? */
def isRootCapability(using Context): Boolean = false

/** Normalize reference so that it can be compared with `eq` for equality */
Expand Down Expand Up @@ -4999,9 +4999,9 @@ object Types {
if (!givenSelf.isValueType) appliedRef
else if (clsd.is(Module)) givenSelf
else if (ctx.erasedTypes) appliedRef
else givenSelf match
case givenSelf @ EventuallyCapturingType(tp, _) =>
givenSelf.derivedAnnotatedType(tp & appliedRef, givenSelf.annot)
else givenSelf.dealiasKeepAnnots match
case givenSelf1 @ EventuallyCapturingType(tp, _) =>
givenSelf1.derivedAnnotatedType(tp & appliedRef, givenSelf1.annot)
case _ =>
AndType(givenSelf, appliedRef)
}
Expand Down
Loading