Skip to content

Commit 18778a4

Browse files
committed
Fix lubs over capturing types
Also, fix Seq rechecking so that elements are always box adapted
1 parent 954fdcd commit 18778a4

File tree

9 files changed

+89
-10
lines changed

9 files changed

+89
-10
lines changed

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

+3
Original file line numberDiff line numberDiff line change
@@ -719,6 +719,9 @@ class CheckCaptures extends Recheck, SymTransformer:
719719
openClosures = openClosures.tail
720720
end recheckClosureBlock
721721

722+
override def seqLiteralElemProto(tree: SeqLiteral, pt: Type, declared: Type)(using Context) =
723+
super.seqLiteralElemProto(tree, pt, declared).boxed
724+
722725
/** Maps mutable variables to the symbols that capture them (in the
723726
* CheckCaptures sense, i.e. symbol is referred to from a different method
724727
* than the one it is defined in).

compiler/src/dotty/tools/dotc/core/TypeComparer.scala

+5
Original file line numberDiff line numberDiff line change
@@ -2751,6 +2751,11 @@ class TypeComparer(@constructorOnly initctx: Context) extends ConstraintHandling
27512751
}
27522752
case tp1: TypeVar if tp1.isInstantiated =>
27532753
lub(tp1.underlying, tp2, isSoft = isSoft)
2754+
case CapturingType(parent1, refs1) =>
2755+
if tp1.isBoxCompatibleWith(tp2) then
2756+
tp1.derivedCapturingType(lub(parent1, tp2, isSoft = isSoft), refs1)
2757+
else // TODO: Analyze cases where they are not box compatible
2758+
NoType
27542759
case tp1: AnnotatedType if !tp1.isRefining =>
27552760
lub(tp1.underlying, tp2, isSoft = isSoft)
27562761
case _ =>

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

+9-4
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ import reporting.trace
2323
import annotation.constructorOnly
2424
import cc.CaptureSet.IdempotentCaptRefMap
2525
import annotation.tailrec
26+
import dotty.tools.dotc.cc.boxed
2627

2728
object Recheck:
2829
import tpd.*
@@ -438,12 +439,16 @@ abstract class Recheck extends Phase, SymTransformer:
438439
val finalizerType = recheck(tree.finalizer, defn.UnitType)
439440
TypeComparer.lub(bodyType :: casesTypes)
440441

442+
def seqLiteralElemProto(tree: SeqLiteral, pt: Type, declared: Type)(using Context): Type =
443+
declared.orElse:
444+
pt.stripNull().elemType match
445+
case NoType => WildcardType
446+
case bounds: TypeBounds => WildcardType(bounds)
447+
case elemtp => elemtp
448+
441449
def recheckSeqLiteral(tree: SeqLiteral, pt: Type)(using Context): Type =
442-
val elemProto = pt.stripNull().elemType match
443-
case NoType => WildcardType
444-
case bounds: TypeBounds => WildcardType(bounds)
445-
case elemtp => elemtp
446450
val declaredElemType = recheck(tree.elemtpt)
451+
val elemProto = seqLiteralElemProto(tree, pt, declaredElemType)
447452
val elemTypes = tree.elems.map(recheck(_, elemProto))
448453
seqLitType(tree, TypeComparer.lub(declaredElemType :: elemTypes))
449454

tests/neg-custom-args/captures/lazylist.check

+5-5
Original file line numberDiff line numberDiff line change
@@ -26,11 +26,11 @@
2626
| Required: lazylists.LazyList[Int]^{cap2}
2727
|
2828
| longer explanation available when compiling with `-explain`
29-
-- [E007] Type Mismatch Error: tests/neg-custom-args/captures/lazylist.scala:41:48 -------------------------------------
30-
41 | val ref4c: LazyList[Int]^{cap1, ref3, cap3} = ref4 // error
31-
| ^^^^
32-
| Found: (ref4 : lazylists.LazyList[Int]^{cap3, cap2, ref1})
33-
| Required: lazylists.LazyList[Int]^{cap1, ref3, cap3}
29+
-- [E007] Type Mismatch Error: tests/neg-custom-args/captures/lazylist.scala:41:42 -------------------------------------
30+
41 | val ref4c: LazyList[Int]^{cap1, ref3} = ref4 // error
31+
| ^^^^
32+
| Found: (ref4 : lazylists.LazyList[Int]^{cap3, ref2, ref1})
33+
| Required: lazylists.LazyList[Int]^{cap1, ref3}
3434
|
3535
| longer explanation available when compiling with `-explain`
3636
-- [E164] Declaration Error: tests/neg-custom-args/captures/lazylist.scala:22:6 ----------------------------------------

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

+1-1
Original file line numberDiff line numberDiff line change
@@ -38,4 +38,4 @@ def test(cap1: Cap, cap2: Cap, cap3: Cap) =
3838
val ref3 = ref1.map(g)
3939
val ref3c: LazyList[Int]^{cap2} = ref3 // error
4040
val ref4 = (if cap1 == cap2 then ref1 else ref2).map(h)
41-
val ref4c: LazyList[Int]^{cap1, ref3, cap3} = ref4 // error
41+
val ref4c: LazyList[Int]^{cap1, ref3} = ref4 // error
+21
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
-- [E007] Type Mismatch Error: tests/neg-custom-args/captures/lubs.scala:17:13 -----------------------------------------
2+
17 | val _: D = x1 // error
3+
| ^^
4+
| Found: (x1 : D^{d1})
5+
| Required: D
6+
|
7+
| longer explanation available when compiling with `-explain`
8+
-- [E007] Type Mismatch Error: tests/neg-custom-args/captures/lubs.scala:18:13 -----------------------------------------
9+
18 | val _: D = x2 // error
10+
| ^^
11+
| Found: (x2 : D^{d1})
12+
| Required: D
13+
|
14+
| longer explanation available when compiling with `-explain`
15+
-- [E007] Type Mismatch Error: tests/neg-custom-args/captures/lubs.scala:19:13 -----------------------------------------
16+
19 | val _: D = x3 // error
17+
| ^^
18+
| Found: (x3 : D^{d1, d2})
19+
| Required: D
20+
|
21+
| longer explanation available when compiling with `-explain`
+20
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
import java.sql.Date
2+
3+
class C extends caps.Capability
4+
class D
5+
6+
def Test(c1: C, c2: C) =
7+
val d: D = ???
8+
val d1: D^{c1} = ???
9+
val d2: D^{c2} = ???
10+
val x1 = if ??? then d else d1
11+
val _: D^{c1} = x1
12+
val x2 = if ??? then d1 else d
13+
val _: D^{c1} = x2
14+
val x3 = if ??? then d1 else d2
15+
val _: D^{c1, c2} = x3
16+
17+
val _: D = x1 // error
18+
val _: D = x2 // error
19+
val _: D = x3 // error
20+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
-- [E007] Type Mismatch Error: tests/neg-custom-args/captures/spread-problem.scala:8:6 ---------------------------------
2+
8 | race(Seq(src1, src2)*) // error
3+
| ^^^^^^^^^^^^^^^^^^^^^^
4+
| Found: Source[box T^?]^{src1, src2}
5+
| Required: Source[T]
6+
|
7+
| longer explanation available when compiling with `-explain`
8+
-- [E007] Type Mismatch Error: tests/neg-custom-args/captures/spread-problem.scala:11:6 --------------------------------
9+
11 | race(src1, src2) // error
10+
| ^^^^^^^^^^^^^^^^
11+
| Found: Source[box T^?]^{src1, src2}
12+
| Required: Source[T]
13+
|
14+
| longer explanation available when compiling with `-explain`
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
import language.experimental.captureChecking
2+
3+
trait Source[+T]
4+
5+
def race[T](@caps.unbox sources: (Source[T]^)*): Source[T]^{sources*} = ???
6+
7+
def raceTwo[T](src1: Source[T]^, src2: Source[T]^): Source[T]^{} =
8+
race(Seq(src1, src2)*) // error
9+
10+
def raceThree[T](src1: Source[T]^, src2: Source[T]^): Source[T]^{} =
11+
race(src1, src2) // error

0 commit comments

Comments
 (0)