diff --git a/compiler/src/dotty/tools/dotc/cc/CaptureOps.scala b/compiler/src/dotty/tools/dotc/cc/CaptureOps.scala index 5680df476f8d..a2d2d2cf358c 100644 --- a/compiler/src/dotty/tools/dotc/cc/CaptureOps.scala +++ b/compiler/src/dotty/tools/dotc/cc/CaptureOps.scala @@ -264,7 +264,9 @@ extension (tp: Type) def boxed(using Context): Type = tp.dealias match case tp @ CapturingType(parent, refs) if !tp.isBoxed && !refs.isAlwaysEmpty => tp.annot match - case ann: CaptureAnnotation => AnnotatedType(parent, ann.boxedAnnot) + case ann: CaptureAnnotation => + assert(!parent.derivesFrom(defn.Caps_CapSet)) + AnnotatedType(parent, ann.boxedAnnot) case ann => tp case tp: RealTypeBounds => tp.derivedTypeBounds(tp.lo.boxed, tp.hi.boxed) diff --git a/compiler/src/dotty/tools/dotc/cc/CapturingType.scala b/compiler/src/dotty/tools/dotc/cc/CapturingType.scala index bb79e52f1060..9f9b923b2c88 100644 --- a/compiler/src/dotty/tools/dotc/cc/CapturingType.scala +++ b/compiler/src/dotty/tools/dotc/cc/CapturingType.scala @@ -33,6 +33,7 @@ object CapturingType: * boxing status is the same or if A is boxed. */ def apply(parent: Type, refs: CaptureSet, boxed: Boolean = false)(using Context): Type = + assert(!boxed || !parent.derivesFrom(defn.Caps_CapSet)) if refs.isAlwaysEmpty && !refs.keepAlways then parent else parent match case parent @ CapturingType(parent1, refs1) if boxed || !parent.isBoxed => diff --git a/compiler/src/dotty/tools/dotc/cc/Setup.scala b/compiler/src/dotty/tools/dotc/cc/Setup.scala index c048edfb2102..25d50052f107 100644 --- a/compiler/src/dotty/tools/dotc/cc/Setup.scala +++ b/compiler/src/dotty/tools/dotc/cc/Setup.scala @@ -134,9 +134,10 @@ class Setup extends PreRecheck, SymTransformer, SetupAPI: private def box(tp: Type)(using Context): Type = def recur(tp: Type): Type = tp.dealiasKeepAnnotsAndOpaques match case tp @ CapturingType(parent, refs) => - if tp.isBoxed then tp else tp.boxed + if tp.isBoxed || parent.derivesFrom(defn.Caps_CapSet) then tp + else tp.boxed case tp @ AnnotatedType(parent, ann) => - if ann.symbol.isRetains + if ann.symbol.isRetains && !parent.derivesFrom(defn.Caps_CapSet) then CapturingType(parent, ann.tree.toCaptureSet, boxed = true) else tp.derivedAnnotatedType(box(parent), ann) case tp1 @ AppliedType(tycon, args) if defn.isNonRefinedFunction(tp1) => @@ -605,8 +606,10 @@ class Setup extends PreRecheck, SymTransformer, SetupAPI: !refs.isEmpty case tp: (TypeRef | AppliedType) => val sym = tp.typeSymbol - if sym.isClass then !sym.isPureClass - else instanceCanBeImpure(tp.superType) + if sym.isClass + then !sym.isPureClass + else !tp.derivesFrom(defn.Caps_CapSet) // CapSet arguments don't get other capture set variables added + && instanceCanBeImpure(tp.superType) case tp: (RefinedOrRecType | MatchType) => instanceCanBeImpure(tp.underlying) case tp: AndType => diff --git a/tests/pos/polycap.scala b/tests/pos/polycap.scala new file mode 100644 index 000000000000..684f46454595 --- /dev/null +++ b/tests/pos/polycap.scala @@ -0,0 +1,14 @@ +import language.experimental.captureChecking + +class Source[+T, Cap^] + +def completed[T, Cap^](result: T): Source[T, Cap] = + //val fut = new Source[T, Cap]() + val fut2 = new Source[T, Cap]() + fut2: Source[T, Cap] + + + + + +