Skip to content

Commit dccadb9

Browse files
committed
Don't recheck inherited trait parameters during capture checking
The logic gets confused by the added capture refinements.
1 parent d4c084c commit dccadb9

File tree

4 files changed

+38
-36
lines changed

4 files changed

+38
-36
lines changed

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

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1190,6 +1190,8 @@ class CheckCaptures extends Recheck, SymTransformer:
11901190

11911191
override def needsCheck(overriding: Symbol, overridden: Symbol)(using Context): Boolean =
11921192
!setup.isPreCC(overriding) && !setup.isPreCC(overridden)
1193+
1194+
override def checkInheritedTraitParameters: Boolean = false
11931195
end OverridingPairsCheckerCC
11941196

11951197
def traverse(t: Tree)(using Context) =

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

Lines changed: 20 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -13,25 +13,20 @@ import core.NameKinds.TempResultName
1313
import core.Constants._
1414
import util.Store
1515
import dotty.tools.uncheckedNN
16-
17-
import scala.compiletime.uninitialized
16+
import ast.tpd.*
17+
import compiletime.uninitialized
1818

1919
/** This phase translates variables that are captured in closures to
2020
* heap-allocated refs.
2121
*/
2222
class CapturedVars extends MiniPhase with IdentityDenotTransformer:
2323
thisPhase =>
24-
import ast.tpd._
2524

2625
override def phaseName: String = CapturedVars.name
2726

2827
override def description: String = CapturedVars.description
2928

30-
private[this] var Captured: Store.Location[util.ReadOnlySet[Symbol]] = uninitialized
31-
private def captured(using Context) = ctx.store(Captured)
32-
33-
override def initContext(ctx: FreshContext): Unit =
34-
Captured = ctx.addLocation(util.ReadOnlySet.empty)
29+
private val captured = util.HashSet[Symbol]()
3530

3631
private class RefInfo(using Context) {
3732
/** The classes for which a Ref type exists. */
@@ -57,33 +52,10 @@ class CapturedVars extends MiniPhase with IdentityDenotTransformer:
5752
myRefInfo.uncheckedNN
5853
}
5954

60-
private class CollectCaptured extends TreeTraverser {
61-
private val captured = util.HashSet[Symbol]()
62-
def traverse(tree: Tree)(using Context) = tree match {
63-
case id: Ident =>
64-
val sym = id.symbol
65-
if (sym.is(Mutable, butNot = Method) && sym.owner.isTerm) {
66-
val enclMeth = ctx.owner.enclosingMethod
67-
if (sym.enclosingMethod != enclMeth) {
68-
report.log(i"capturing $sym in ${sym.enclosingMethod}, referenced from $enclMeth")
69-
captured += sym
70-
}
71-
}
72-
case _ =>
73-
traverseChildren(tree)
74-
}
75-
def runOver(tree: Tree)(using Context): util.ReadOnlySet[Symbol] = {
76-
traverse(tree)
77-
captured
78-
}
79-
}
80-
81-
override def prepareForUnit(tree: Tree)(using Context): Context = {
82-
val captured = atPhase(thisPhase) {
83-
CollectCaptured().runOver(ctx.compilationUnit.tpdTree)
84-
}
85-
ctx.fresh.updateStore(Captured, captured)
86-
}
55+
override def prepareForUnit(tree: Tree)(using Context): Context =
56+
captured.clear()
57+
atPhase(thisPhase)(CapturedVars.collect(captured)).traverse(tree)
58+
ctx
8759

8860
/** The {Volatile|}{Int|Double|...|Object}Ref class corresponding to the class `cls`,
8961
* depending on whether the reference should be @volatile
@@ -143,3 +115,16 @@ class CapturedVars extends MiniPhase with IdentityDenotTransformer:
143115
object CapturedVars:
144116
val name: String = "capturedVars"
145117
val description: String = "represent vars captured by closures as heap objects"
118+
119+
def collect(captured: util.HashSet[Symbol]): TreeTraverser = new:
120+
def traverse(tree: Tree)(using Context) = tree match
121+
case id: Ident =>
122+
val sym = id.symbol
123+
if sym.is(Mutable, butNot = Method) && sym.owner.isTerm then
124+
val enclMeth = ctx.owner.enclosingMethod
125+
if sym.enclosingMethod != enclMeth then
126+
report.log(i"capturing $sym in ${sym.enclosingMethod}, referenced from $enclMeth")
127+
captured += sym
128+
case _ =>
129+
traverseChildren(tree)
130+
end CapturedVars

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

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -267,6 +267,9 @@ object RefChecks {
267267
if !other.is(Deferred) then
268268
checkOverride(subtypeChecker, dcl, other)
269269
end checkAll
270+
271+
// Disabled for capture checking since traits can get different parameter refinements
272+
def checkInheritedTraitParameters: Boolean = true
270273
end OverridingPairsChecker
271274

272275
/** 1. Check all members of class `clazz` for overriding conditions.
@@ -851,7 +854,7 @@ object RefChecks {
851854
checkCaseClassInheritanceInvariant()
852855
}
853856

854-
if (!clazz.is(Trait)) {
857+
if (!clazz.is(Trait) && checker.checkInheritedTraitParameters) {
855858
// check that parameterized base classes and traits are typed in the same way as from the superclass
856859
// I.e. say we have
857860
//
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
def foo[sealed B](x: B): B = x
2+
3+
def bar[B, sealed A >: B](x: A): A = foo[A](x)
4+
5+
class C[sealed A]
6+
7+
class CV[sealed A](x: Int):
8+
def this() = this:
9+
val x = new C[A]:
10+
println("foo")
11+
0
12+

0 commit comments

Comments
 (0)