Skip to content

Commit 4e6b82e

Browse files
committed
Always use the sealed policy
Drop the exception that held only in 3.5
1 parent aa06e07 commit 4e6b82e

File tree

6 files changed

+7
-135
lines changed

6 files changed

+7
-135
lines changed

compiler/src/dotty/tools/dotc/cc/CaptureOps.scala

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -43,15 +43,6 @@ object ccConfig:
4343
*/
4444
inline val deferredReaches = false
4545

46-
/** If true, use "sealed" as encapsulation mechanism, meaning that we
47-
* check that type variable instantiations don't have `cap` in any of
48-
* their capture sets. This is an alternative of the original restriction
49-
* that `cap` can't be boxed or unboxed. It is dropped in 3.5 but used
50-
* again in 3.6.
51-
*/
52-
def useSealed(using Context) =
53-
Feature.sourceVersion.stable != SourceVersion.`3.5`
54-
5546
/** If true, turn on separation checking */
5647
def useSepChecks(using Context): Boolean =
5748
Feature.sourceVersion.stable.isAtLeast(SourceVersion.`3.7`)

compiler/src/dotty/tools/dotc/cc/CheckCaptures.scala

Lines changed: 6 additions & 69 deletions
Original file line numberDiff line numberDiff line change
@@ -215,42 +215,9 @@ object CheckCaptures:
215215
finally openExistentialScopes = saved
216216
case t =>
217217
traverseChildren(t)
218-
if ccConfig.useSealed then check.traverse(tp)
218+
check.traverse(tp)
219219
end disallowRootCapabilitiesIn
220220

221-
/** If we are not under the sealed policy, and a tree is an application that unboxes
222-
* its result or is a try, check that the tree's type does not have covariant universal
223-
* capabilities.
224-
*/
225-
private def checkNotUniversalInUnboxedResult(tpe: Type, tree: Tree)(using Context): Unit =
226-
def needsUniversalCheck = tree match
227-
case _: RefTree | _: Apply | _: TypeApply => tree.symbol.unboxesResult
228-
case _: Try => true
229-
case _ => false
230-
231-
object checkNotUniversal extends TypeTraverser:
232-
def traverse(tp: Type) =
233-
tp.dealias match
234-
case wtp @ CapturingType(parent, refs) =>
235-
if variance > 0 then
236-
refs.disallowRootCapability: () =>
237-
def part = if wtp eq tpe.widen then "" else i" in its part $wtp"
238-
report.error(
239-
em"""The expression's type ${tpe.widen} is not allowed to capture the root capability `cap`$part.
240-
|This usually means that a capability persists longer than its allowed lifetime.""",
241-
tree.srcPos)
242-
if !wtp.isBoxed then traverse(parent)
243-
case tp =>
244-
traverseChildren(tp)
245-
246-
if !ccConfig.useSealed
247-
&& !tpe.hasAnnotation(defn.UncheckedCapturesAnnot)
248-
&& needsUniversalCheck
249-
&& tpe.widen.isValueType
250-
then
251-
checkNotUniversal.traverse(tpe.widen)
252-
end checkNotUniversalInUnboxedResult
253-
254221
trait CheckerAPI:
255222
/** Complete symbol info of a val or a def */
256223
def completeDef(tree: ValOrDefDef, sym: Symbol)(using Context): Type
@@ -584,7 +551,7 @@ class CheckCaptures extends Recheck, SymTransformer:
584551
*/
585552
def disallowCapInTypeArgs(fn: Tree, sym: Symbol, args: List[Tree])(using Context): Unit =
586553
def isExempt = sym.isTypeTestOrCast || sym == defn.Compiletime_erasedValue
587-
if ccConfig.useSealed && !isExempt then
554+
if !isExempt then
588555
val paramNames = atPhase(thisPhase.prev):
589556
fn.tpe.widenDealias match
590557
case tl: TypeLambda => tl.paramNames
@@ -1178,7 +1145,7 @@ class CheckCaptures extends Recheck, SymTransformer:
11781145
*/
11791146
override def recheckTry(tree: Try, pt: Type)(using Context): Type =
11801147
val tp = super.recheckTry(tree, pt)
1181-
if ccConfig.useSealed && Feature.enabled(Feature.saferExceptions) then
1148+
if Feature.enabled(Feature.saferExceptions) then
11821149
disallowRootCapabilitiesIn(tp, ctx.owner,
11831150
"The result of `try`", "have type",
11841151
"\nThis is often caused by a locally generated exception capability leaking as part of its result.",
@@ -1227,12 +1194,6 @@ class CheckCaptures extends Recheck, SymTransformer:
12271194
res
12281195
end recheck
12291196

1230-
/** Under the old unsealed policy: check that cap is ot unboxed */
1231-
override def recheckFinish(tpe: Type, tree: Tree, pt: Type)(using Context): Type =
1232-
checkNotUniversalInUnboxedResult(tpe, tree)
1233-
super.recheckFinish(tpe, tree, pt)
1234-
end recheckFinish
1235-
12361197
// ------------------ Adaptation -------------------------------------
12371198
//
12381199
// Adaptations before checking conformance of actual vs expected:
@@ -1487,34 +1448,12 @@ class CheckCaptures extends Recheck, SymTransformer:
14871448
.capturing(if alwaysConst then CaptureSet(captures.elems) else captures)
14881449
.forceBoxStatus(resultBoxed)
14891450

1490-
if needsAdaptation then
1491-
val criticalSet = // the set with which we box or unbox
1451+
if needsAdaptation && !insertBox then // we are unboxing
1452+
val criticalSet = // the set with which we unbox
14921453
if covariant then captures // covariant: we box with captures of actual type plus captures leaked by inner adapation
14931454
else expected.captureSet // contravarant: we unbox with captures of epected type
1494-
def msg = em"""$actual cannot be box-converted to $expected
1495-
|since at least one of their capture sets contains the root capability `cap`"""
1496-
def allowUniversalInBoxed =
1497-
ccConfig.useSealed
1498-
|| expected.hasAnnotation(defn.UncheckedCapturesAnnot)
1499-
|| actual.widen.hasAnnotation(defn.UncheckedCapturesAnnot)
1500-
if !allowUniversalInBoxed then
1501-
if criticalSet.isUnboxable && expected.isValueType then
1502-
// We can't box/unbox the universal capability. Leave `actual` as it is
1503-
// so we get an error in checkConforms. Add the error message generated
1504-
// from boxing as an addendum. This tends to give better error
1505-
// messages than disallowing the root capability in `criticalSet`.
1506-
if boxErrors != null then boxErrors += msg
1507-
if ctx.settings.YccDebug.value then
1508-
println(i"cannot box/unbox $actual vs $expected")
1509-
return actual
1510-
// Disallow future addition of `cap` to `criticalSet`.
1511-
criticalSet.disallowRootCapability: () =>
1512-
report.error(msg, tree.srcPos)
1513-
1514-
if !insertBox then // we are unboxing
15151455
//debugShowEnvs()
1516-
markFree(criticalSet, tree)
1517-
end if
1456+
markFree(criticalSet, tree)
15181457

15191458
// Compute the adapted type.
15201459
// The result is boxed if actual is boxed and we don't need to adapt,
@@ -1901,8 +1840,6 @@ class CheckCaptures extends Recheck, SymTransformer:
19011840
checkBounds(normArgs, tl)
19021841
args.lazyZip(tl.paramNames).foreach(healTypeParam(_, _, fun.symbol))
19031842
case _ =>
1904-
case tree: TypeTree if !ccConfig.useSealed =>
1905-
checkArraysAreSealedIn(tree.tpe, tree.srcPos)
19061843
case _ =>
19071844
end check
19081845
end checker

compiler/src/dotty/tools/dotc/cc/Setup.scala

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -553,14 +553,7 @@ class Setup extends PreRecheck, SymTransformer, SetupAPI:
553553
def transformResultType(tpt: TypeTree, sym: Symbol)(using Context): Unit =
554554
// First step: Transform the type and record it as knownType of tpt.
555555
try
556-
transformTT(tpt, sym,
557-
boxed =
558-
sym.isMutableVar
559-
&& !ccConfig.useSealed
560-
&& !sym.hasAnnotation(defn.UncheckedCapturesAnnot),
561-
// Under the sealed policy, we disallow root capabilities in the type of mutable
562-
// variables, no need to box them here.
563-
)
556+
transformTT(tpt, sym, boxed = false)
564557
catch case ex: IllegalCaptureRef =>
565558
capt.println(i"fail while transforming result type $tpt of $sym")
566559
throw ex

tests/neg-custom-args/captures/unbox.scala

Lines changed: 0 additions & 6 deletions
This file was deleted.

tests/pos-custom-args/captures/hk-param.scala

Lines changed: 0 additions & 18 deletions
This file was deleted.

tests/pos-custom-args/captures/levels.scala

Lines changed: 0 additions & 25 deletions
This file was deleted.

0 commit comments

Comments
 (0)