Skip to content

Commit fac643a

Browse files
committed
Split postcheck phase in two
Perform bounds checking before checking self types. Checking self types interpolates them, which may give an upper approximation solution that failes subsequent bounds checks. On the other hand, well-formedness checkimng should come after self types checking since otherwise we get spurious "has empty capture set, cannot be tracked" messages.
1 parent 9391b9a commit fac643a

File tree

3 files changed

+38
-6
lines changed

3 files changed

+38
-6
lines changed

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

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -594,7 +594,9 @@ object CaptureSet:
594594
override def optionalInfo(using Context): String =
595595
for vars <- ctx.property(ShownVars) do vars += this
596596
val debugInfo =
597-
if !isConst && ctx.settings.YccDebug.value then ids else ""
597+
if !ctx.settings.YccDebug.value then ""
598+
else if isConst then ids ++ "(solved)"
599+
else ids
598600
val limitInfo =
599601
if ctx.settings.YprintLevel.value && level.isDefined
600602
then i"<at level ${level.toString}>"

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

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1363,8 +1363,9 @@ class CheckCaptures extends Recheck, SymTransformer:
13631363
withCaptureSetsExplained:
13641364
super.checkUnit(unit)
13651365
checkOverrides.traverse(unit.tpdTree)
1366-
checkSelfTypes(unit.tpdTree)
13671366
postCheck(unit.tpdTree)
1367+
checkSelfTypes(unit.tpdTree)
1368+
postCheckWF(unit.tpdTree)
13681369
if ctx.settings.YccDebug.value then
13691370
show(unit.tpdTree) // this does not print tree, but makes its variables visible for dependency printing
13701371

@@ -1514,7 +1515,6 @@ class CheckCaptures extends Recheck, SymTransformer:
15141515
check.traverse(tp)
15151516

15161517
/** Perform the following kinds of checks
1517-
* - Check all explicitly written capturing types for well-formedness using `checkWellFormedPost`.
15181518
* - Check that arguments of TypeApplys and AppliedTypes conform to their bounds.
15191519
* - Heal ill-formed capture sets of type parameters. See `healTypeParam`.
15201520
*/
@@ -1542,10 +1542,8 @@ class CheckCaptures extends Recheck, SymTransformer:
15421542
case _ =>
15431543
end check
15441544
end checker
1545-
checker.traverse(unit)(using ctx.withOwner(defn.RootClass))
1546-
for chk <- todoAtPostCheck do chk()
1547-
setup.postCheck()
15481545

1546+
checker.traverse(unit)(using ctx.withOwner(defn.RootClass))
15491547
if !ctx.reporter.errorsReported then
15501548
// We dont report errors here if previous errors were reported, because other
15511549
// errors often result in bad applied types, but flagging these bad types gives
@@ -1557,5 +1555,15 @@ class CheckCaptures extends Recheck, SymTransformer:
15571555
case tree: TypeTree => checkAppliedTypesIn(tree.withKnownType)
15581556
case _ => traverseChildren(t)
15591557
checkApplied.traverse(unit)
1558+
end postCheck
1559+
1560+
/** Perform the following kinds of checks:
1561+
* - Check all explicitly written capturing types for well-formedness using `checkWellFormedPost`.
1562+
* - Check that publicly visible inferred types correspond to the type
1563+
* they have without capture checking.
1564+
*/
1565+
def postCheckWF(unit: tpd.Tree)(using Context): Unit =
1566+
for chk <- todoAtPostCheck do chk()
1567+
setup.postCheck()
15601568
end CaptureChecker
15611569
end CheckCaptures
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
trait Dsl:
2+
3+
sealed trait Nat
4+
case object Zero extends Nat
5+
case class Succ[N <: Nat](n: N) extends Nat
6+
7+
type Stable[+l <: Nat, +b <: Nat, +A]
8+
type Now[+l <: Nat, +b <: Nat, +A]
9+
type Box[+A]
10+
def stable[l <: Nat, b <: Nat, A](e: Stable[l, b, A]): Now[l, b, Box[A]]
11+
12+
def program[A](prog: Now[Zero.type, Zero.type, A]): Now[Zero.type, Zero.type, A]
13+
14+
//val conforms: Zero.type <:< Nat = summon
15+
// ^ need to uncomment this line to compile with captureChecking enabled
16+
17+
def test: Any =
18+
program[Box[Int]]:
19+
val v : Stable[Zero.type, Zero.type, Int] = ???
20+
stable[Zero.type, Zero.type, Int](v)
21+
// ^
22+
// Type argument Dsl.this.Zero.type does not conform to upper bound Dsl.this.Nat

0 commit comments

Comments
 (0)