Skip to content

Commit 6cb97ff

Browse files
committed
Also treat explicit capturing type arguments as boxed
1 parent a24fb91 commit 6cb97ff

File tree

4 files changed

+47
-25
lines changed

4 files changed

+47
-25
lines changed

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

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,9 +30,12 @@ extension (tree: Tree)
3030
tree.putAttachment(Captures, refs)
3131
refs
3232

33-
def isBoxedCapturing(using Context) =
33+
def isBoxedCapturing(using Context): Boolean =
3434
tree.hasAttachment(IsBoxed)
3535

36+
def setBoxedCapturing()(using Context): Unit =
37+
tree.putAttachment(IsBoxed, ())
38+
3639
extension (tp: Type)
3740

3841
def derivedCapturingType(parent: Type, refs: CaptureSet)(using Context): Type = tp match

compiler/src/dotty/tools/dotc/transform/Recheck.scala

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ abstract class Recheck extends Phase, IdentityDenotTransformer:
4444

4545
def run(using Context): Unit =
4646
val rechecker = newRechecker()
47-
rechecker.reinferAll.traverse(ctx.compilationUnit.tpdTree)
47+
rechecker.transformTypes.traverse(ctx.compilationUnit.tpdTree)
4848
rechecker.checkUnit(ctx.compilationUnit)
4949

5050
def newRechecker()(using Context): Rechecker
@@ -72,15 +72,15 @@ abstract class Recheck extends Phase, IdentityDenotTransformer:
7272
def knownType(tree: Tree) =
7373
tree.attachmentOrElse(RecheckedType, tree.tpe)
7474

75-
def reinfer(tp: Type)(using Context): Type = tp
75+
def transformType(tp: Type, inferred: Boolean)(using Context): Type = tp
7676

77-
object reinferAll extends TreeTraverser:
77+
object transformTypes extends TreeTraverser:
7878
def traverse(tree: Tree)(using Context) =
7979
traverseChildren(tree)
8080
tree match
81-
case tree: InferredTypeTree =>
82-
reinfer(tree.tpe).rememberFor(tree)
83-
case tree: ValOrDefDef if tree.tpt.isInstanceOf[InferredTypeTree] =>
81+
case tree: TypeTree =>
82+
transformType(tree.tpe, tree.isInstanceOf[InferredTypeTree]).rememberFor(tree)
83+
case tree: ValOrDefDef if tree.tpt.hasAttachment(RecheckedType) =>
8484
val sym = tree.symbol
8585
def integrateRT(restp: Type, info: Type, psymss: List[List[Symbol]]): Type = info match
8686
case info: MethodOrPoly =>
@@ -96,9 +96,9 @@ abstract class Recheck extends Phase, IdentityDenotTransformer:
9696
sym.updateInfo(info1)
9797
case tree: Bind =>
9898
val sym = tree.symbol
99-
sym.updateInfo(reinfer(sym.info))
99+
sym.updateInfo(transformType(sym.info, inferred = true))
100100
case _ =>
101-
end reinferAll
101+
end transformTypes
102102

103103
def constFold(tree: Tree, tp: Type)(using Context): Type =
104104
val tree1 = tree.withType(tp)

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

Lines changed: 30 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -99,17 +99,17 @@ class CheckCaptures extends Recheck:
9999
class CaptureChecker(ictx: Context) extends Rechecker(ictx):
100100
import ast.tpd.*
101101

102-
override def reinfer(tp: Type)(using Context): Type =
102+
override def transformType(tp: Type, inferred: Boolean)(using Context): Type =
103103

104-
def mapRefined(tp: RefinedType, core1: Type, rinfo1: Type): Type =
105-
if (rinfo1 ne tp.refinedInfo) && defn.isFunctionType(tp)
106-
then rinfo1.toFunctionType(isJava = false, alwaysDependent = true)
107-
else tp.derivedRefinedType(core1, tp.refinedName, rinfo1)
108-
109-
val cleanType = new TypeMap:
104+
val prepare = new TypeMap:
110105
def apply(t: Type) = t match
111-
case AnnotatedType(parent, annot) if annot.symbol == defn.RetainsAnnot =>
106+
case AnnotatedType(parent, annot) if inferred && annot.symbol == defn.RetainsAnnot =>
112107
apply(parent)
108+
case AppliedType(tycon, args) if false && !inferred && !defn.isNonRefinedFunction(t) =>
109+
for case AnnotatedType(parent, annot) <- args do
110+
if annot.symbol == defn.RetainsAnnot then
111+
annot.tree.setBoxedCapturing()
112+
mapOver(t)
113113
case _ =>
114114
mapOver(t)
115115

@@ -180,9 +180,28 @@ class CheckCaptures extends Recheck:
180180
then CapturingType(tp2, CaptureSet.Var(), boxed)
181181
else tp2
182182

183-
addVars(addFunctionRefinements(cleanType(tp)))
184-
.showing(i"reinfer $tp --> $result", capt)
185-
end reinfer
183+
if inferred then
184+
val cleanup = new TypeMap:
185+
def apply(t: Type) = t match
186+
case AnnotatedType(parent, annot) if annot.symbol == defn.RetainsAnnot =>
187+
apply(parent)
188+
case _ =>
189+
mapOver(t)
190+
addVars(addFunctionRefinements(cleanup(tp)))
191+
.showing(i"reinfer $tp --> $result", capt)
192+
else
193+
val addBoxes = new TypeTraverser:
194+
def traverse(t: Type) =
195+
t match
196+
case AppliedType(tycon, args) if !defn.isNonRefinedFunction(t) =>
197+
for case AnnotatedType(parent, annot) <- args do
198+
if annot.symbol == defn.RetainsAnnot then
199+
annot.tree.setBoxedCapturing()
200+
case _ =>
201+
traverseChildren(t)
202+
addBoxes.traverse(tp)
203+
tp
204+
end transformType
186205

187206
private var curEnv: Env = Env(NoSymbol, CaptureSet.empty, false, null)
188207

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

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -47,9 +47,9 @@ def test(c: Cap, d: Cap) =
4747

4848
val a0 = identity[{d, y} Cap => Unit]
4949
val a1 = zs.map[{d, y} Cap => Unit](a0)
50-
// val a2 = zs.map[{d, y} Cap => Unit](identity[{d, y} Cap => Unit])
51-
// val a3 = zs.map(identity[{d, y} Cap => Unit])
52-
// val a4 = zs.map(identity)
53-
// val a2 = map(identity)(zs)
54-
// val a3 = m1(identity)(zs)
50+
//val a2 = zs.map[{d, y} Cap => Unit](identity[{d, y} Cap => Unit]) // fails
51+
val a3 = zs.map(identity[{d, y} Cap => Unit])
52+
//val a4 = zs.map(identity) // fails
53+
val a5 = map(identity)(zs)
54+
val a6 = m1(identity)(zs)
5555

0 commit comments

Comments
 (0)