File tree Expand file tree Collapse file tree 6 files changed +24
-10
lines changed
compiler/src/dotty/tools/dotc Expand file tree Collapse file tree 6 files changed +24
-10
lines changed Original file line number Diff line number Diff line change @@ -495,15 +495,13 @@ extension (sym: Symbol)
495495
496496 /** Does this symbol allow results carrying the universal capability?
497497 * Currently this is true only for function type applies (since their
498- * results are unboxed) and `erasedValue` since this function is magic in
499- * that is allows to conjure global capabilies from nothing (aside: can we find a
500- * more controlled way to achieve this?).
498+ * results are unboxed) and `caps.{$internal,unsafe}.erasedValue` since
499+ * these function are magic in that they allow to conjure global capabilies from nothing.
501500 * But it could be generalized to other functions that so that they can take capability
502501 * classes as arguments.
503502 */
504503 def allowsRootCapture (using Context ): Boolean =
505- sym == defn.Compiletime_erasedValue
506- || defn.isFunctionClass(sym.maybeOwner)
504+ defn.capsErasedValueMethods.contains(sym) || defn.isFunctionClass(sym.maybeOwner)
507505
508506 /** When applying `sym`, would the result type be unboxed?
509507 * This is the case if the result type contains a top-level reference to an enclosing
Original file line number Diff line number Diff line change @@ -576,7 +576,7 @@ class CheckCaptures extends Recheck, SymTransformer:
576576 * @param args the type arguments
577577 */
578578 def disallowCapInTypeArgs (fn : Tree , sym : Symbol , args : List [Tree ])(using Context ): Unit =
579- def isExempt = sym.isTypeTestOrCast || sym == defn.Compiletime_erasedValue
579+ def isExempt = sym.isTypeTestOrCast || defn.capsErasedValueMethods.contains(sym)
580580 if ! isExempt then
581581 val paramNames = atPhase(thisPhase.prev):
582582 fn.tpe.widenDealias match
Original file line number Diff line number Diff line change @@ -1004,9 +1004,11 @@ class Definitions {
10041004 @ tu lazy val Caps_Capability : ClassSymbol = requiredClass(" scala.caps.Capability" )
10051005 @ tu lazy val Caps_CapSet : ClassSymbol = requiredClass(" scala.caps.CapSet" )
10061006 @ tu lazy val CapsInternalModule : Symbol = requiredModule(" scala.caps.internal" )
1007+ @ tu lazy val Caps_erasedValue : Symbol = CapsInternalModule .requiredMethod(" erasedValue" )
10071008 @ tu lazy val CapsUnsafeModule : Symbol = requiredModule(" scala.caps.unsafe" )
10081009 @ tu lazy val Caps_unsafeAssumePure : Symbol = CapsUnsafeModule .requiredMethod(" unsafeAssumePure" )
10091010 @ tu lazy val Caps_unsafeAssumeSeparate : Symbol = CapsUnsafeModule .requiredMethod(" unsafeAssumeSeparate" )
1011+ @ tu lazy val Caps_unsafeErasedValue : Symbol = CapsUnsafeModule .requiredMethod(" unsafeErasedValue" )
10101012 @ tu lazy val Caps_ContainsTrait : TypeSymbol = CapsModule .requiredType(" Contains" )
10111013 @ tu lazy val Caps_ContainsModule : Symbol = requiredModule(" scala.caps.Contains" )
10121014 @ tu lazy val Caps_containsImpl : TermSymbol = Caps_ContainsModule .requiredMethod(" containsImpl" )
@@ -1559,7 +1561,7 @@ class Definitions {
15591561 Set (StringClass , NothingClass , NullClass ) ++ ScalaValueClasses ()
15601562
15611563 @ tu lazy val capsErasedValueMethods =
1562- Set [ Symbol ]( )
1564+ Set ( Caps_erasedValue , Caps_unsafeErasedValue )
15631565 @ tu lazy val erasedValueMethods =
15641566 capsErasedValueMethods + Compiletime_erasedValue
15651567
Original file line number Diff line number Diff line change @@ -231,7 +231,7 @@ class Synthesizer(typer: Typer)(using @constructorOnly c: Context):
231231 case PreciseConstrained (tp, true ) =>
232232 if tp.isSingletonBounded(frozen = false ) then
233233 withNoErrors :
234- ref(defn.Compiletime_erasedValue ).appliedToType(formal).withSpan(span)
234+ ref(defn.Caps_erasedValue ).appliedToType(formal).withSpan(span)
235235 else
236236 withErrors(i " $tp is not a singleton " )
237237 case _ =>
@@ -240,7 +240,7 @@ class Synthesizer(typer: Typer)(using @constructorOnly c: Context):
240240 val synthesizedPrecise : SpecialHandler = (formal, span) => formal match
241241 case PreciseConstrained (tp, false ) =>
242242 withNoErrors :
243- ref(defn.Compiletime_erasedValue ).appliedToType(formal).withSpan(span)
243+ ref(defn.Caps_erasedValue ).appliedToType(formal).withSpan(span)
244244 case _ =>
245245 EmptyTreeNoError
246246
Original file line number Diff line number Diff line change @@ -2392,7 +2392,7 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer
23922392 untpd.ValDef (
23932393 CanThrowEvidenceName .fresh(),
23942394 untpd.TypeTree (defn.CanThrowClass .typeRef.appliedTo(tp)),
2395- untpd.ref(defn.Compiletime_erasedValue ))
2395+ untpd.ref(defn.Caps_erasedValue ))
23962396 .withFlags(Given | Final | Erased )
23972397 .withSpan(expr.span)
23982398 val caughtExceptions =
Original file line number Diff line number Diff line change @@ -110,6 +110,13 @@ object internal:
110110 */
111111 final class inferredDepFun extends annotation.StaticAnnotation
112112
113+ /** An erasedValue issued internally by the compiler. Unlike the
114+ * user-accessible compiletime.erasedValue, this version is assumed
115+ * to be a pure expression, hence capability safe. The compiler generates this
116+ * version only where it is known that a value can be generated.
117+ */
118+ def erasedValue [T ]: T = ???
119+
113120end internal
114121
115122@ experimental
@@ -135,4 +142,11 @@ object unsafe:
135142 */
136143 def unsafeAssumeSeparate (op : Any ): op.type = op
137144
145+ /** An unsafe variant of erasedValue that can be used as an escape hatch. Unlike the
146+ * user-accessible compiletime.erasedValue, this version is assumed
147+ * to be a pure expression, hence capability safe. But there is no proof
148+ * of realizability, hence it is unsafe.
149+ */
150+ def unsafeErasedValue [T ]: T = ???
151+
138152end unsafe
You can’t perform that action at this time.
0 commit comments