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 @@ -462,15 +462,13 @@ extension (sym: Symbol)
462
462
463
463
/** Does this symbol allow results carrying the universal capability?
464
464
* Currently this is true only for function type applies (since their
465
- * results are unboxed) and `erasedValue` since this function is magic in
466
- * that is allows to conjure global capabilies from nothing (aside: can we find a
467
- * more controlled way to achieve this?).
465
+ * results are unboxed) and `caps.{$internal,unsafe}.erasedValue` since
466
+ * these function are magic in that they allow to conjure global capabilies from nothing.
468
467
* But it could be generalized to other functions that so that they can take capability
469
468
* classes as arguments.
470
469
*/
471
470
def allowsRootCapture (using Context ): Boolean =
472
- sym == defn.Compiletime_erasedValue
473
- || defn.isFunctionClass(sym.maybeOwner)
471
+ defn.capsErasedValueMethods.contains(sym) || defn.isFunctionClass(sym.maybeOwner)
474
472
475
473
/** When applying `sym`, would the result type be unboxed?
476
474
* 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:
576
576
* @param args the type arguments
577
577
*/
578
578
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)
580
580
if ! isExempt then
581
581
val paramNames = atPhase(thisPhase.prev):
582
582
fn.tpe.widenDealias match
Original file line number Diff line number Diff line change @@ -1004,9 +1004,11 @@ class Definitions {
1004
1004
@ tu lazy val Caps_Capability : ClassSymbol = requiredClass(" scala.caps.Capability" )
1005
1005
@ tu lazy val Caps_CapSet : ClassSymbol = requiredClass(" scala.caps.CapSet" )
1006
1006
@ tu lazy val CapsInternalModule : Symbol = requiredModule(" scala.caps.internal" )
1007
+ @ tu lazy val Caps_erasedValue : Symbol = CapsInternalModule .requiredMethod(" erasedValue" )
1007
1008
@ tu lazy val CapsUnsafeModule : Symbol = requiredModule(" scala.caps.unsafe" )
1008
1009
@ tu lazy val Caps_unsafeAssumePure : Symbol = CapsUnsafeModule .requiredMethod(" unsafeAssumePure" )
1009
1010
@ tu lazy val Caps_unsafeAssumeSeparate : Symbol = CapsUnsafeModule .requiredMethod(" unsafeAssumeSeparate" )
1011
+ @ tu lazy val Caps_unsafeErasedValue : Symbol = CapsUnsafeModule .requiredMethod(" unsafeErasedValue" )
1010
1012
@ tu lazy val Caps_ContainsTrait : TypeSymbol = CapsModule .requiredType(" Contains" )
1011
1013
@ tu lazy val Caps_ContainsModule : Symbol = requiredModule(" scala.caps.Contains" )
1012
1014
@ tu lazy val Caps_containsImpl : TermSymbol = Caps_ContainsModule .requiredMethod(" containsImpl" )
@@ -1559,7 +1561,7 @@ class Definitions {
1559
1561
Set (StringClass , NothingClass , NullClass ) ++ ScalaValueClasses ()
1560
1562
1561
1563
@ tu lazy val capsErasedValueMethods =
1562
- Set [ Symbol ]( )
1564
+ Set ( Caps_erasedValue , Caps_unsafeErasedValue )
1563
1565
@ tu lazy val erasedValueMethods =
1564
1566
capsErasedValueMethods + Compiletime_erasedValue
1565
1567
Original file line number Diff line number Diff line change @@ -231,7 +231,7 @@ class Synthesizer(typer: Typer)(using @constructorOnly c: Context):
231
231
case PreciseConstrained (tp, true ) =>
232
232
if tp.isSingletonBounded(frozen = false ) then
233
233
withNoErrors :
234
- ref(defn.Compiletime_erasedValue ).appliedToType(formal).withSpan(span)
234
+ ref(defn.Caps_erasedValue ).appliedToType(formal).withSpan(span)
235
235
else
236
236
withErrors(i " $tp is not a singleton " )
237
237
case _ =>
@@ -240,7 +240,7 @@ class Synthesizer(typer: Typer)(using @constructorOnly c: Context):
240
240
val synthesizedPrecise : SpecialHandler = (formal, span) => formal match
241
241
case PreciseConstrained (tp, false ) =>
242
242
withNoErrors :
243
- ref(defn.Compiletime_erasedValue ).appliedToType(formal).withSpan(span)
243
+ ref(defn.Caps_erasedValue ).appliedToType(formal).withSpan(span)
244
244
case _ =>
245
245
EmptyTreeNoError
246
246
Original file line number Diff line number Diff line change @@ -2384,7 +2384,7 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer
2384
2384
untpd.ValDef (
2385
2385
CanThrowEvidenceName .fresh(),
2386
2386
untpd.TypeTree (defn.CanThrowClass .typeRef.appliedTo(tp)),
2387
- untpd.ref(defn.Compiletime_erasedValue ))
2387
+ untpd.ref(defn.Caps_erasedValue ))
2388
2388
.withFlags(Given | Final | Erased )
2389
2389
.withSpan(expr.span)
2390
2390
val caughtExceptions =
Original file line number Diff line number Diff line change @@ -110,6 +110,13 @@ object internal:
110
110
*/
111
111
final class inferredDepFun extends annotation.StaticAnnotation
112
112
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
+
113
120
end internal
114
121
115
122
@ experimental
@@ -135,4 +142,11 @@ object unsafe:
135
142
*/
136
143
def unsafeAssumeSeparate (op : Any ): op.type = op
137
144
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
+
138
152
end unsafe
You can’t perform that action at this time.
0 commit comments