Skip to content

Commit 8cb4945

Browse files
authored
Fix capture set variable installation in Setup (#18885)
Fixes #18881
2 parents 7713bb6 + 7307f34 commit 8cb4945

File tree

3 files changed

+32
-11
lines changed

3 files changed

+32
-11
lines changed

Diff for: compiler/src/dotty/tools/dotc/cc/Setup.scala

+10-11
Original file line numberDiff line numberDiff line change
@@ -543,7 +543,8 @@ class Setup extends PreRecheck, SymTransformer, SetupAPI:
543543
end postProcess
544544
end setupTraverser
545545

546-
private def superTypeIsImpure(tp: Type)(using Context): Boolean = {
546+
/** Checks whether an abstract type could be impure. See also: [[needsVariable]]. */
547+
private def instanceCanBeImpure(tp: Type)(using Context): Boolean = {
547548
tp.dealiasKeepAnnots match
548549
case CapturingType(_, refs) =>
549550
!refs.isAlwaysEmpty
@@ -552,20 +553,18 @@ class Setup extends PreRecheck, SymTransformer, SetupAPI:
552553
case tp: (TypeRef | AppliedType) =>
553554
val sym = tp.typeSymbol
554555
if sym.isClass then
555-
sym == defn.AnyClass
556-
// we assume Any is a shorthand of {cap} Any, so if Any is an upper
557-
// bound, the type is taken to be impure.
556+
!sym.isPureClass
558557
else
559-
sym != defn.Caps_Cap && superTypeIsImpure(tp.superType)
558+
sym != defn.Caps_Cap && instanceCanBeImpure(tp.superType)
560559
case tp: (RefinedOrRecType | MatchType) =>
561-
superTypeIsImpure(tp.underlying)
560+
instanceCanBeImpure(tp.underlying)
562561
case tp: AndType =>
563-
superTypeIsImpure(tp.tp1) || superTypeIsImpure(tp.tp2)
562+
instanceCanBeImpure(tp.tp1) || instanceCanBeImpure(tp.tp2)
564563
case tp: OrType =>
565-
superTypeIsImpure(tp.tp1) && superTypeIsImpure(tp.tp2)
564+
instanceCanBeImpure(tp.tp1) && instanceCanBeImpure(tp.tp2)
566565
case _ =>
567566
false
568-
}.showing(i"super type is impure $tp = $result", capt)
567+
}.showing(i"instance can be impure $tp = $result", capt)
569568

570569
/** Should a capture set variable be added on type `tp`? */
571570
def needsVariable(tp: Type)(using Context): Boolean = {
@@ -577,7 +576,7 @@ class Setup extends PreRecheck, SymTransformer, SetupAPI:
577576
else
578577
val tp1 = tp.dealiasKeepAnnots
579578
if tp1 ne tp then needsVariable(tp1)
580-
else superTypeIsImpure(tp1)
579+
else instanceCanBeImpure(tp1)
581580
case tp: (RefinedOrRecType | MatchType) =>
582581
needsVariable(tp.underlying)
583582
case tp: AndType =>
@@ -708,4 +707,4 @@ class Setup extends PreRecheck, SymTransformer, SetupAPI:
708707
def postCheck()(using Context): Unit =
709708
for chk <- todoAtPostCheck do chk(ctx)
710709
todoAtPostCheck.clear()
711-
end Setup
710+
end Setup
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
import language.experimental.captureChecking
2+
3+
trait Resource
4+
def id[X](x: X): x.type = x
5+
def foo[M <: Resource](r: M^): Unit = id(r) // was error, should be ok
6+
def bar[M](r: M^): Unit = id(r) // ok

Diff for: tests/pos-custom-args/captures/future-traverse.scala

+16
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
import language.experimental.captureChecking
2+
3+
trait Builder[-A, +C]
4+
trait BuildFrom[-From, -A, +C] {
5+
def newBuilder(from: From): Builder[A, C]
6+
}
7+
8+
trait Future[+T] { this: Future[T]^ =>
9+
import Future.*
10+
def foldLeft[R](r: R): R = r
11+
def traverse[A, B, M[X] <: IterableOnce[X]](in: M[A]^, bf: BuildFrom[M[A]^, B, M[B]^]): Unit =
12+
foldLeft(successful(bf.newBuilder(in)))
13+
}
14+
object Future {
15+
def successful[T](result: T): Future[T] = ???
16+
}

0 commit comments

Comments
 (0)