Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 6 additions & 1 deletion compiler/src/dotty/tools/dotc/transform/PatternMatcher.scala
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,11 @@ import Flags.*, Constants.*
import Decorators.*
import NameKinds.{PatMatStdBinderName, PatMatAltsName, PatMatResultName}
import config.Printers.patmatch
import config.Feature
import reporting.*
import ast.*
import util.Property.*
import cc.{CapturingType, Capabilities}

import scala.annotation.tailrec
import scala.collection.mutable
Expand Down Expand Up @@ -427,8 +429,11 @@ object PatternMatcher {
&& !hasExplicitTypeArgs(extractor)
case _ => false
}
val castTp = if Feature.ccEnabled
then CapturingType(tpt.tpe, scrutinee.termRef.singletonCaptureSet)
else tpt.tpe
TestPlan(TypeTest(tpt, isTrusted), scrutinee, tree.span,
letAbstract(ref(scrutinee).cast(tpt.tpe)) { casted =>
letAbstract(ref(scrutinee).cast(castTp)) { casted =>
nonNull += casted
patternPlan(casted, pat, onSuccess)
})
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -160,7 +160,7 @@ object IndexedSeqView {

@SerialVersionUID(3L)
class Reverse[A](underlying: SomeIndexedSeqOps[A]^) extends SeqView.Reverse[A](underlying) with IndexedSeqView[A] {
override def reverse: IndexedSeqView[A] = underlying match {
override def reverse: IndexedSeqView[A]^{underlying} = underlying match {
case x: IndexedSeqView[A] => x
case _ => super.reverse
}
Expand Down
8 changes: 3 additions & 5 deletions scala2-library-cc/src/scala/collection/View.scala
Original file line number Diff line number Diff line change
Expand Up @@ -152,15 +152,13 @@ object View extends IterableFactory[View] {
def apply[A](underlying: Iterable[A]^, p: A => Boolean, isFlipped: Boolean): Filter[A]^{underlying, p} =
underlying match {
case filter: Filter[A] if filter.isFlipped == isFlipped =>
new Filter(filter.underlying, a => filter.p(a) && p(a), isFlipped)
.asInstanceOf[Filter[A]^{underlying, p}]
unsafeAssumeSeparate:
new Filter(filter.underlying, a => filter.p(a) && p(a), isFlipped)
.asInstanceOf[Filter[A]^{underlying, p}]
// !!! asInstanceOf needed once paths were added, see path-patmat-should-be-pos.scala for minimization
//case filter: Filter[A]^{underlying} if filter.isFlipped == isFlipped =>
// unsafeAssumeSeparate:
// See filter-iterable.scala for a test where a variant of Filter
// works without the unsafeAssumeSeparate. But it requires significant
// changes compared to the version here. See also Filter in colltest5.CollectionStrawManCC5_1.
// new Filter(filter.underlying, a => filter.p(a) && p(a), isFlipped)
case _ => new Filter(underlying, p, isFlipped)
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ private[mutable] object CheckedIndexedSeqView {
@SerialVersionUID(3L)
class Reverse[A](underlying: SomeIndexedSeqOps[A]^)(protected val mutationCount: () ->{cap.rd} Int)
extends IndexedSeqView.Reverse[A](underlying) with CheckedIndexedSeqView[A] {
override def reverse: IndexedSeqView[A] = underlying match {
override def reverse: IndexedSeqView[A]^{underlying} = underlying match {
case x: IndexedSeqView[A] => x
case _ => super.reverse
}
Expand Down
1 change: 1 addition & 0 deletions scaladoc/src/dotty/tools/scaladoc/api.scala
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ enum Modifier(val name: String, val prefix: Boolean):
case Infix extends Modifier("infix", true)
case AbsOverride extends Modifier("abstract override", true)
case Update extends Modifier("update", true)
case Consume extends Modifier("consume", true)

case class ExtensionTarget(name: String, typeParams: Seq[TypeParameter], argsLists: Seq[TermParameterList], signature: Signature, dri: DRI, position: Long)
case class ImplicitConversion(from: DRI, to: DRI)
Expand Down
2 changes: 1 addition & 1 deletion scaladoc/src/dotty/tools/scaladoc/tasty/BasicSupport.scala
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ trait BasicSupport:
)
val fqNameAllowlist =
if ccEnabled then
fqNameAllowlist0 + CaptureDefs.useAnnotFullName + CaptureDefs.consumeAnnotFullName
fqNameAllowlist0 + CaptureDefs.useAnnotFullName
else fqNameAllowlist0
val documentedSymbol = summon[Quotes].reflect.Symbol.requiredClass("java.lang.annotation.Documented")
val annotations = sym.annotations.filter { a =>
Expand Down
15 changes: 9 additions & 6 deletions scaladoc/src/dotty/tools/scaladoc/tasty/ClassLikeSupport.scala
Original file line number Diff line number Diff line change
Expand Up @@ -23,11 +23,13 @@ trait ClassLikeSupport:

extension (symbol: Symbol) {
def getExtraModifiers(): Seq[Modifier] =
val mods = SymOps.getExtraModifiers(symbol)()
if ccEnabled && symbol.flags.is(Flags.Mutable)then
mods :+ Modifier.Update
else
mods
var mods = SymOps.getExtraModifiers(symbol)()
if ccEnabled && symbol.flags.is(Flags.Mutable) then
if symbol.hasAnnotation(cc.CaptureDefs.ConsumeAnnot) then
mods :+= Modifier.Consume
else
mods :+= Modifier.Update
mods
}

private def bareClasslikeKind(using Quotes)(symbol: reflect.Symbol): Kind =
Expand Down Expand Up @@ -452,11 +454,12 @@ trait ClassLikeSupport:
) =
val symbol = argument.symbol
val inlinePrefix = if symbol.flags.is(Flags.Inline) then "inline " else ""
val comsumePrefix = if self.ccEnabled && symbol.hasAnnotation(cc.CaptureDefs.ConsumeAnnot) then "consume " else ""
val name = symbol.normalizedName
val nameIfNotSynthetic = Option.when(!symbol.flags.is(Flags.Synthetic))(name)
api.TermParameter(
symbol.getAnnotations(),
inlinePrefix + prefix(symbol),
comsumePrefix + inlinePrefix + prefix(symbol),
nameIfNotSynthetic,
symbol.dri,
argument.tpt.asSignature(classDef, symbol.owner),
Expand Down
1 change: 1 addition & 0 deletions scaladoc/src/dotty/tools/scaladoc/tasty/TypesSupport.scala
Original file line number Diff line number Diff line change
Expand Up @@ -533,6 +533,7 @@ trait TypesSupport:
private def isCapturedInContext(using Quotes)(ref: reflect.TypeRepr)(using elideThis: reflect.ClassDef): Boolean =
import reflect._
ref match
case t if t.isCaptureRoot => true
case ReachCapability(c) => isCapturedInContext(c)
case ReadOnlyCapability(c) => isCapturedInContext(c)
case ThisType(tr) => !elideThis.symbol.typeRef.isPureClass(elideThis) /* is the current class pure? */
Expand Down
24 changes: 24 additions & 0 deletions tests/neg-custom-args/captures/match.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import language.experimental.captureChecking

trait A

case class B(x: AnyRef^) extends A

def test =
val x: AnyRef^ = new AnyRef
val a: A^{x} = B(x)

val y1: A = a match
case b: B => b // error: (b: B) becomes B^{x} implicitly

val y2: A^{x} = a match
case b: B =>
val bb: B^{b} = b
val aa: A^{a} = bb
b // ok

val x3: AnyRef = a match
case B(x2: AnyRef) => x2 // error: we lose some information about field x, but it still cannot be pure

val x4: AnyRef = a match
case b: B => b.x // error
Original file line number Diff line number Diff line change
Expand Up @@ -457,13 +457,12 @@ object CollectionStrawMan5 {
def apply[A](underlying: Iterable[A]^, pp: A => Boolean, isFlipped: Boolean): Filter[A]^{underlying, pp} =
underlying match
case filter: Filter[A] =>
new Filter(filter.underlying, a => filter.p(a) && pp(a))
.asInstanceOf[Filter[A]^{underlying, pp}]
//unsafeAssumeSeparate:
unsafeAssumeSeparate:
new Filter(filter.underlying, a => filter.p(a) && pp(a))
.asInstanceOf[Filter[A]^{underlying, pp}]
// See filter-iterable.scala for a test where a variant of Filter
// works without the unsafeAssumeSeparate. But it requires significant
// changes compared to the version here.
//new Filter(filter.underlying, a => filter.p(a) && pp(a))
case _ => new Filter(underlying, pp)

case class Partition[A](val underlying: Iterable[A]^, p: A => Boolean) {
Expand Down