Skip to content

Commit 209d793

Browse files
committed
Normalize captures also for explicit types
1 parent 81de544 commit 209d793

File tree

2 files changed

+20
-18
lines changed

2 files changed

+20
-18
lines changed

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

Lines changed: 19 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -237,8 +237,8 @@ extends tpd.TreeTraverser:
237237
// Don't map capture sets, since that would implicitly normalize sets that
238238
// are not well-formed.
239239
t.derivedAnnotatedType(t3, ann)
240-
case _ =>
241-
mapOverFollowingAliases(t)
240+
case t =>
241+
normalizeCaptures(mapOverFollowingAliases(t))
242242

243243
private def transformExplicitType(tp: Type, boxed: Boolean, mapRoots: Boolean)(using Context): Type =
244244
val tp1 = expandAliases(tp)
@@ -560,10 +560,8 @@ extends tpd.TreeTraverser:
560560
false
561561
}.showing(i"can have inferred capture $tp = $result", capt)
562562

563-
/** Add a capture set variable to `tp` if necessary, or maybe pull out
564-
* an embedded capture set variable from a part of `tp`.
565-
*/
566-
def decorate(tp: Type, mapRoots: Boolean, addedSet: Type => CaptureSet)(using Context): Type = tp match
563+
/** Pull out an embedded capture set from a part of `tp` */
564+
def normalizeCaptures(tp: Type)(using Context): Type = tp match
567565
case tp @ RefinedType(parent @ CapturingType(parent1, refs), rname, rinfo) =>
568566
CapturingType(tp.derivedRefinedType(parent1, rname, rinfo), refs, parent.isBoxed)
569567
case tp: RecType =>
@@ -575,33 +573,37 @@ extends tpd.TreeTraverser:
575573
// by `mapInferred`. Hence if the underlying type admits capture variables
576574
// a variable was already added, and the first case above would apply.
577575
case AndType(tp1 @ CapturingType(parent1, refs1), tp2 @ CapturingType(parent2, refs2)) =>
578-
assert(refs1.elems.isEmpty)
579-
assert(refs2.elems.isEmpty)
580576
assert(tp1.isBoxed == tp2.isBoxed)
581577
CapturingType(AndType(parent1, parent2), refs1 ** refs2, tp1.isBoxed)
582578
case tp @ OrType(tp1 @ CapturingType(parent1, refs1), tp2 @ CapturingType(parent2, refs2)) =>
583-
assert(refs1.elems.isEmpty)
584-
assert(refs2.elems.isEmpty)
585579
assert(tp1.isBoxed == tp2.isBoxed)
586580
CapturingType(OrType(parent1, parent2, tp.isSoft), refs1 ++ refs2, tp1.isBoxed)
587581
case tp @ OrType(tp1 @ CapturingType(parent1, refs1), tp2) =>
588582
CapturingType(OrType(parent1, tp2, tp.isSoft), refs1, tp1.isBoxed)
589583
case tp @ OrType(tp1, tp2 @ CapturingType(parent2, refs2)) =>
590584
CapturingType(OrType(tp1, parent2, tp.isSoft), refs2, tp2.isBoxed)
591585
case tp: LazyRef =>
592-
decorate(tp.ref, mapRoots, addedSet)
593-
case _ if tp.typeSymbol == defn.FromJavaObjectSymbol =>
586+
normalizeCaptures(tp.ref)
587+
case _ =>
588+
tp
589+
590+
/** Add a capture set variable to `tp` if necessary, or maybe pull out
591+
* an embedded capture set variable from a part of `tp`.
592+
*/
593+
def decorate(tp: Type, mapRoots: Boolean, addedSet: Type => CaptureSet)(using Context): Type =
594+
if tp.typeSymbol == defn.FromJavaObjectSymbol then
594595
// For capture checking, we assume Object from Java is the same as Any
595596
tp
596-
case _ =>
597+
else
597598
def maybeAdd(target: Type, fallback: Type) =
598599
if needsVariable(target) then CapturingType(target, addedSet(target))
599600
else fallback
600-
val tp1 = tp.dealiasKeepAnnots
601-
if tp1 ne tp then
601+
val tp0 = normalizeCaptures(tp)
602+
val tp1 = tp0.dealiasKeepAnnots
603+
if tp1 ne tp0 then
602604
val tp2 = transformExplicitType(tp1, boxed = false, mapRoots)
603-
maybeAdd(tp2, if tp2 ne tp1 then tp2 else tp)
604-
else maybeAdd(tp, tp)
605+
maybeAdd(tp2, if tp2 ne tp1 then tp2 else tp0)
606+
else maybeAdd(tp0, tp0)
605607

606608
/** Add a capture set variable to `tp` if necessary, or maybe pull out
607609
* an embedded capture set variable from a part of `tp`.
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
-- [E007] Type Mismatch Error: tests/neg-custom-args/captures/cc-glb.scala:7:19 ----------------------------------------
22
7 | val x2: Foo[T] = x1 // error
33
| ^^
4-
| Found: (x1 : (Foo[T]^) & (Foo[Any]^{io}))
4+
| Found: (x1 : (Foo[T] & Foo[Any])^{io})
55
| Required: Foo[T]
66
|
77
| longer explanation available when compiling with `-explain`

0 commit comments

Comments
 (0)