Skip to content

Commit 43ef239

Browse files
committed
Check conformance to caps.Pure upper bound only under cc
This is necessary to ensure source compatibility of the capture checked stdlib.
1 parent c140894 commit 43ef239

File tree

3 files changed

+42
-2
lines changed

3 files changed

+42
-2
lines changed

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

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -706,9 +706,29 @@ object TypeOps:
706706
def loop(args: List[Tree], boundss: List[TypeBounds]): Unit = args match
707707
case arg :: args1 => boundss match
708708
case bounds :: boundss1 =>
709+
710+
// Drop caps.Pure from a bound (1) at the top-level, (2) in an `&`, (3) under a type lambda.
711+
def dropPure(tp: Type): Option[Type] = tp match
712+
case tp @ AndType(tp1, tp2) =>
713+
for tp1o <- dropPure(tp1); tp2o <- dropPure(tp2) yield
714+
tp.derivedAndType(tp1o, tp2o)
715+
case tp: HKTypeLambda =>
716+
for rt <- dropPure(tp.resType) yield
717+
tp.derivedLambdaType(resType = rt)
718+
case _ =>
719+
if tp.typeSymbol == defn.PureClass then None
720+
else Some(tp)
721+
722+
val relevantBounds =
723+
if Feature.ccEnabled then bounds
724+
else
725+
// Drop caps.Pure from bound, it should be checked only when capture checking is enabled
726+
dropPure(bounds.hi).match
727+
case Some(hi1) => bounds.derivedTypeBounds(bounds.lo, hi1)
728+
case None => TypeBounds(bounds.lo, defn.AnyKindType)
709729
arg.tpe match
710-
case TypeBounds(lo, hi) => checkOverlapsBounds(lo, hi, arg, bounds)
711-
case tp => checkOverlapsBounds(tp, tp, arg, bounds)
730+
case TypeBounds(lo, hi) => checkOverlapsBounds(lo, hi, arg, relevantBounds)
731+
case tp => checkOverlapsBounds(tp, tp, arg, relevantBounds)
712732
loop(args1, boundss1)
713733
case _ =>
714734
case _ =>
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
import caps.Pure
2+
def foo[C <: Pure]() = ()
3+
def bar[T, C <: Iterable[T] & Pure]() = ()
4+
def baz[CC[_] <: Pure]() = ()
5+
def bam[CC[A] <: Pure & Iterable[A]]() = ()
6+
def test =
7+
foo[Int]() // error
8+
bar[Int, List[Int]]() // error
9+
baz[Seq]() // error
10+
bam[Seq]() // error

tests/pos/puretest.scala

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
import caps.Pure
2+
def foo[C <: Pure]() = ()
3+
def bar[T, C <: Iterable[T] & Pure]() = ()
4+
def baz[CC[_] <: Pure]() = ()
5+
def bam[CC[A] <: Pure & Iterable[A]]() = ()
6+
def test =
7+
foo[Int]()
8+
bar[Int, List[Int]]()
9+
baz[Seq]()
10+
bam[Seq]()

0 commit comments

Comments
 (0)