Skip to content

Commit

Permalink
Change cc syntax (#17377)
Browse files Browse the repository at this point in the history
Trial: change cc syntax 


    From            To

    {xs} T          T^{xs}
    {*} T           T^
    (xs) A -> B     A ->{xs} B
  • Loading branch information
odersky authored May 10, 2023
2 parents 82efd33 + 156ec83 commit e614f23
Show file tree
Hide file tree
Showing 162 changed files with 1,082 additions and 1,055 deletions.
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
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 @@ -2093,7 +2093,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 @@ -4989,9 +4989,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

0 comments on commit e614f23

Please sign in to comment.