From 2e81d8b67e9b1af9c8bb250a72d92c35f318ee64 Mon Sep 17 00:00:00 2001 From: Natsu Kagami Date: Tue, 1 Apr 2025 18:06:20 +0200 Subject: [PATCH 01/32] Add capture checking to boundary and NonLocalReturns --- library/src/scala/util/boundary.scala | 4 ++-- library/src/scala/util/control/NonLocalReturns.scala | 4 +++- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/library/src/scala/util/boundary.scala b/library/src/scala/util/boundary.scala index 3039fc70be90..3afba484cc77 100644 --- a/library/src/scala/util/boundary.scala +++ b/library/src/scala/util/boundary.scala @@ -38,7 +38,7 @@ object boundary: /** Labels are targets indicating which boundary will be exited by a `break`. */ @implicitNotFound("explain=A Label is generated from an enclosing `scala.util.boundary` call.\nMaybe that boundary is missing?") - final class Label[-T] + final class Label[-T] extends caps.Control /** Abort current computation and instead return `value` as the value of * the enclosing `boundary` call that created `label`. @@ -60,7 +60,7 @@ object boundary: val local = Label[T]() try body(using local) catch case ex: Break[T] @unchecked => - if ex.label eq local then ex.value + if ex.isSameLabelAs(local) then ex.value else throw ex end boundary diff --git a/library/src/scala/util/control/NonLocalReturns.scala b/library/src/scala/util/control/NonLocalReturns.scala index f59b4c22a4c2..aa446ce33004 100644 --- a/library/src/scala/util/control/NonLocalReturns.scala +++ b/library/src/scala/util/control/NonLocalReturns.scala @@ -1,5 +1,7 @@ package scala.util.control +import language.experimental.captureChecking + import scala.compiletime.uninitialized /** Library implementation of nonlocal return. @@ -22,7 +24,7 @@ import scala.compiletime.uninitialized @deprecated("Use scala.util.boundary instead", "3.3") object NonLocalReturns { @deprecated("Use scala.util.boundary.Break instead", "3.3") - class ReturnThrowable[T] extends ControlThrowable { + class ReturnThrowable[T] extends ControlThrowable, caps.Control { private var myResult: T = uninitialized def throwReturn(result: T): Nothing = { myResult = result From 1ada5f6c2b2bf5f90599d19e6039a4e22a36d9a3 Mon Sep 17 00:00:00 2001 From: Natsu Kagami Date: Tue, 11 Mar 2025 16:48:21 +0100 Subject: [PATCH 02/32] Add capture-checking test for boundary --- tests/neg-custom-args/captures/boundary.check | 27 +++++++++++++++++++ tests/neg-custom-args/captures/boundary.scala | 9 +++++++ 2 files changed, 36 insertions(+) create mode 100644 tests/neg-custom-args/captures/boundary.check create mode 100644 tests/neg-custom-args/captures/boundary.scala diff --git a/tests/neg-custom-args/captures/boundary.check b/tests/neg-custom-args/captures/boundary.check new file mode 100644 index 000000000000..4b51012191ed --- /dev/null +++ b/tests/neg-custom-args/captures/boundary.check @@ -0,0 +1,27 @@ +-- [E007] Type Mismatch Error: tests/neg-custom-args/captures/boundary.scala:8:31 -------------------------------------- +8 | boundary.break(l2)(using l1) // error + | ^^ + | Found: (local : scala.util.boundary.Label[scala.util.boundary.Label[Unit]]^) + | Required: scala.util.boundary.Label[box scala.util.boundary.Label[Unit]^{local²}]^ + | + | where: local is a value locally defined in object test + | local² is a value locally defined in object test + | + | longer explanation available when compiling with `-explain` +-- [E007] Type Mismatch Error: tests/neg-custom-args/captures/boundary.scala:6:32 -------------------------------------- + 6 | boundary[boundary.Label[Unit]]: l1 ?=> // error + | ^ + | Found: scala.util.boundary.Break[scala.util.boundary.Label[Unit]] @unchecked + | Required: scala.util.boundary.Break[box scala.util.boundary.Label[Unit]^] @unchecked + 7 | boundary[Unit]: l2 ?=> + 8 | boundary.break(l2)(using l1) // error + 9 | ??? + |-------------------------------------------------------------------------------------------------------------------- + |Inline stack trace + |- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + |This location contains code that was inlined from boundary.scala:73 +73 | catch case ex: Break[T] @unchecked => + | ^ + -------------------------------------------------------------------------------------------------------------------- + | + | longer explanation available when compiling with `-explain` diff --git a/tests/neg-custom-args/captures/boundary.scala b/tests/neg-custom-args/captures/boundary.scala new file mode 100644 index 000000000000..4f2a994d392e --- /dev/null +++ b/tests/neg-custom-args/captures/boundary.scala @@ -0,0 +1,9 @@ +import language.experimental.captureChecking + +import scala.util.boundary + +object test: + boundary[boundary.Label[Unit]]: l1 ?=> // error + boundary[Unit]: l2 ?=> + boundary.break(l2)(using l1) // error + ??? From 0a6490c0de0a025289e66ea20fd230d4c4603338 Mon Sep 17 00:00:00 2001 From: Natsu Kagami Date: Wed, 12 Mar 2025 13:16:54 +0100 Subject: [PATCH 03/32] Patch DropBreaks to correctly detect boundary blocks We previously had the `ex.label eq label` comparision, which is no longer the case, with the (package) private label field. --- compiler/src/dotty/tools/dotc/core/StdNames.scala | 1 + .../dotty/tools/dotc/transform/DropBreaks.scala | 4 ++-- library/src/scala/util/boundary.scala | 14 ++++++++++++-- 3 files changed, 15 insertions(+), 4 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/core/StdNames.scala b/compiler/src/dotty/tools/dotc/core/StdNames.scala index 0bde164186b7..b4bf46b62360 100644 --- a/compiler/src/dotty/tools/dotc/core/StdNames.scala +++ b/compiler/src/dotty/tools/dotc/core/StdNames.scala @@ -530,6 +530,7 @@ object StdNames { val isEmpty: N = "isEmpty" val isInstanceOf_ : N = "isInstanceOf" val isInstanceOfPM: N = "$isInstanceOf$" + val isSameLabelAs : N = "isSameLabelAs" val java: N = "java" val key: N = "key" val label: N = "label" diff --git a/compiler/src/dotty/tools/dotc/transform/DropBreaks.scala b/compiler/src/dotty/tools/dotc/transform/DropBreaks.scala index 5f26a6af6c3c..b1c0080705ad 100644 --- a/compiler/src/dotty/tools/dotc/transform/DropBreaks.scala +++ b/compiler/src/dotty/tools/dotc/transform/DropBreaks.scala @@ -63,10 +63,10 @@ class DropBreaks extends MiniPhase: */ def unapply(expr: Tree)(using Context): Option[(Symbol, Symbol)] = stripTyped(expr) match case If( - Apply(Select(Select(ex: Ident, label), eq), (lbl @ Ident(local)) :: Nil), + Apply(Select(ex: Ident, isSameLabelAs), (lbl @ Ident(local)) :: Nil), Select(ex2: Ident, value), Apply(throww, (ex3: Ident) :: Nil)) - if label == nme.label && eq == nme.eq && local == nme.local && value == nme.value + if isSameLabelAs == nme.isSameLabelAs && local == nme.local && value == nme.value && throww.symbol == defn.throwMethod && ex.symbol == ex2.symbol && ex.symbol == ex3.symbol => Some((ex.symbol, lbl.symbol)) diff --git a/library/src/scala/util/boundary.scala b/library/src/scala/util/boundary.scala index 3afba484cc77..e589618f008d 100644 --- a/library/src/scala/util/boundary.scala +++ b/library/src/scala/util/boundary.scala @@ -1,4 +1,6 @@ package scala.util + +import language.experimental.captureChecking import scala.annotation.implicitNotFound /** A boundary that can be exited by `break` calls. @@ -31,9 +33,17 @@ object boundary: /** User code should call `break.apply` instead of throwing this exception * directly. */ - final class Break[T] private[boundary](val label: Label[T], val value: T) + final class Break[T] private[boundary](private[boundary] val label: Label[T]^{}, val value: T) extends RuntimeException( - /*message*/ null, /*cause*/ null, /*enableSuppression=*/ false, /*writableStackTrace*/ false) + /*message*/ null, /*cause*/ null, /*enableSuppression=*/ false, /*writableStackTrace*/ false): + /** Compare the given [[Label]] to the one this [[Break]] was constructed with. */ + def isSameLabelAs(other: Label[T]) = label eq other + + object Break: + import caps.unsafe.unsafeAssumePure + def apply[T](label: Label[T], value: T) = + // SAFETY: labels cannot leak from [[Break]], and is only used for equality comparison. + new Break(label.unsafeAssumePure, value) /** Labels are targets indicating which boundary will be exited by a `break`. */ From cc82c70fcff0f7144cd34f0f953933e209c5778d Mon Sep 17 00:00:00 2001 From: Natsu Kagami Date: Mon, 31 Mar 2025 17:12:18 +0200 Subject: [PATCH 04/32] Add capture checking to CommandLineParser --- library/src/scala/util/CommandLineParser.scala | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/library/src/scala/util/CommandLineParser.scala b/library/src/scala/util/CommandLineParser.scala index fd239ef231c5..a43148c3699b 100644 --- a/library/src/scala/util/CommandLineParser.scala +++ b/library/src/scala/util/CommandLineParser.scala @@ -1,5 +1,7 @@ package scala.util +import language.experimental.captureChecking + /** A utility object to support command line parsing for @main methods */ object CommandLineParser { @@ -12,7 +14,7 @@ object CommandLineParser { /** Parse command line argument `s`, which has index `n`, as a value of type `T` * @throws ParseError if argument cannot be converted to type `T`. */ - def parseString[T](str: String, n: Int)(using fs: FromString[T]): T = { + def parseString[T](str: String, n: Int)(using fs: FromString[T]^): T = { try fs.fromString(str) catch { case ex: IllegalArgumentException => throw ParseError(n, ex.toString) @@ -22,14 +24,14 @@ object CommandLineParser { /** Parse `n`'th argument in `args` (counting from 0) as a value of type `T` * @throws ParseError if argument does not exist or cannot be converted to type `T`. */ - def parseArgument[T](args: Array[String], n: Int)(using fs: FromString[T]): T = + def parseArgument[T](args: Array[String], n: Int)(using fs: FromString[T]^): T = if n < args.length then parseString(args(n), n) else throw ParseError(n, "more arguments expected") /** Parse all arguments from `n`'th one (counting from 0) as a list of values of type `T` * @throws ParseError if some of the arguments cannot be converted to type `T`. */ - def parseRemainingArguments[T](args: Array[String], n: Int)(using fs: FromString[T]): List[T] = + def parseRemainingArguments[T](args: Array[String], n: Int)(using fs: FromString[T]^): List[T] = if n < args.length then parseString(args(n), n) :: parseRemainingArguments(args, n + 1) else Nil From 32ef601039e2040f55c99477ca6db45ba99ba39a Mon Sep 17 00:00:00 2001 From: Natsu Kagami Date: Mon, 31 Mar 2025 17:20:13 +0200 Subject: [PATCH 05/32] Add capture checking to scala.util --- library/src/scala/util/FromDigits.scala | 1 + library/src/scala/util/NotGiven.scala | 2 ++ library/src/scala/util/TupledFunction.scala | 4 +++- project/Build.scala | 1 + 4 files changed, 7 insertions(+), 1 deletion(-) diff --git a/library/src/scala/util/FromDigits.scala b/library/src/scala/util/FromDigits.scala index 44532649868d..73b5a79b7546 100644 --- a/library/src/scala/util/FromDigits.scala +++ b/library/src/scala/util/FromDigits.scala @@ -3,6 +3,7 @@ import scala.math.{BigInt} import quoted.* import annotation.internal.sharable +import language.experimental.captureChecking /** A type class for types that admit numeric literals. */ diff --git a/library/src/scala/util/NotGiven.scala b/library/src/scala/util/NotGiven.scala index 973e709042cb..4896a1c44c80 100644 --- a/library/src/scala/util/NotGiven.scala +++ b/library/src/scala/util/NotGiven.scala @@ -1,5 +1,7 @@ package scala.util +import language.experimental.captureChecking + /** A special class used to implement negation in implicit search. * * Consider the problem of using implicit `i1` for a query type `D` if an implicit diff --git a/library/src/scala/util/TupledFunction.scala b/library/src/scala/util/TupledFunction.scala index 99df6b5b7cae..b5a6bfd7f65b 100644 --- a/library/src/scala/util/TupledFunction.scala +++ b/library/src/scala/util/TupledFunction.scala @@ -1,5 +1,7 @@ package scala.util +import language.experimental.captureChecking + import scala.annotation.implicitNotFound import scala.annotation.experimental @@ -16,7 +18,7 @@ sealed trait TupledFunction[F, G]: @experimental private[scala] object TupledFunction: - def apply[F, G](tupledImpl: F => G, untupledImpl: G => F): TupledFunction[F, G] = + def apply[F, G](tupledImpl: F => G, untupledImpl: G => F): TupledFunction[F, G]^{tupledImpl, untupledImpl} = new TupledFunction[F, G]: def tupled(f: F): G = tupledImpl(f) def untupled(g: G): F = untupledImpl(g) diff --git a/project/Build.scala b/project/Build.scala index 9acb1c7d55aa..33e7a83e7ce0 100644 --- a/project/Build.scala +++ b/project/Build.scala @@ -1083,6 +1083,7 @@ object Build { // NOTE: Do not use `sourceDirectories` since `sources` are currently pinned until `3.8.0` "-sourcepath", (Compile / sources).value.map(_.getCanonicalPath).distinct.mkString(File.pathSeparator), "-Yexplicit-nulls", + "-explain", ), (Compile / doc / scalacOptions) ++= ScaladocConfigs.DefaultGenerationSettings.value.settings, (Compile / packageSrc / mappings) ++= { From 28b770545e787b94bf244854207d69fbae93acf9 Mon Sep 17 00:00:00 2001 From: Natsu Kagami Date: Mon, 31 Mar 2025 17:52:26 +0200 Subject: [PATCH 06/32] Add capture checking to scala.runtime Mostly imports here --- library/src/scala/runtime/$throws.scala | 3 +++ library/src/scala/runtime/Arrays.scala | 2 ++ library/src/scala/runtime/EnumValue.scala | 2 ++ library/src/scala/runtime/FunctionXXL.scala | 2 ++ library/src/scala/runtime/LazyVals.scala | 1 + library/src/scala/runtime/MatchCase.scala | 2 ++ library/src/scala/runtime/Scala3RunTime.scala | 2 ++ 7 files changed, 14 insertions(+) diff --git a/library/src/scala/runtime/$throws.scala b/library/src/scala/runtime/$throws.scala index af35f7402ca3..f02b5b205f47 100644 --- a/library/src/scala/runtime/$throws.scala +++ b/library/src/scala/runtime/$throws.scala @@ -1,4 +1,7 @@ package scala.runtime + +import language.experimental.captureChecking + import annotation.experimental /** A helper type to allow syntax like diff --git a/library/src/scala/runtime/Arrays.scala b/library/src/scala/runtime/Arrays.scala index 085b36c08a1f..2e8b62d76a56 100644 --- a/library/src/scala/runtime/Arrays.scala +++ b/library/src/scala/runtime/Arrays.scala @@ -1,5 +1,7 @@ package scala.runtime +import language.experimental.captureChecking + import scala.annotation.unused import scala.reflect.ClassTag diff --git a/library/src/scala/runtime/EnumValue.scala b/library/src/scala/runtime/EnumValue.scala index 1cd13605279e..62b3af3584ba 100644 --- a/library/src/scala/runtime/EnumValue.scala +++ b/library/src/scala/runtime/EnumValue.scala @@ -1,5 +1,7 @@ package scala.runtime +import language.experimental.captureChecking + transparent trait EnumValue extends Product, Serializable: override def canEqual(that: Any) = this eq that.asInstanceOf[AnyRef] override def productArity: Int = 0 diff --git a/library/src/scala/runtime/FunctionXXL.scala b/library/src/scala/runtime/FunctionXXL.scala index 250e03577e08..be23632e7eff 100644 --- a/library/src/scala/runtime/FunctionXXL.scala +++ b/library/src/scala/runtime/FunctionXXL.scala @@ -1,5 +1,7 @@ package scala.runtime +import language.experimental.captureChecking + /** A function with all parameters grouped in an array. */ trait FunctionXXL { diff --git a/library/src/scala/runtime/LazyVals.scala b/library/src/scala/runtime/LazyVals.scala index deea2201414a..a924b5dd2a4d 100644 --- a/library/src/scala/runtime/LazyVals.scala +++ b/library/src/scala/runtime/LazyVals.scala @@ -1,5 +1,6 @@ package scala.runtime +import language.experimental.captureChecking import java.util.concurrent.CountDownLatch import scala.annotation.* diff --git a/library/src/scala/runtime/MatchCase.scala b/library/src/scala/runtime/MatchCase.scala index 2f1a27328bbc..f163413df2a3 100644 --- a/library/src/scala/runtime/MatchCase.scala +++ b/library/src/scala/runtime/MatchCase.scala @@ -1,5 +1,7 @@ package scala.runtime +import language.experimental.captureChecking + /** A type constructor for a case in a match type. */ final abstract class MatchCase[Pat, +Body] diff --git a/library/src/scala/runtime/Scala3RunTime.scala b/library/src/scala/runtime/Scala3RunTime.scala index e503b2d7ec7e..685947f293e0 100644 --- a/library/src/scala/runtime/Scala3RunTime.scala +++ b/library/src/scala/runtime/Scala3RunTime.scala @@ -1,5 +1,7 @@ package scala.runtime +import language.experimental.captureChecking + object Scala3RunTime: // Called by inline def assert's. Extracted to minimize the bytecode size at call site. From 4d88844020e878b7741c2a6755bd613762ea59d5 Mon Sep 17 00:00:00 2001 From: Natsu Kagami Date: Tue, 1 Apr 2025 14:38:10 +0200 Subject: [PATCH 07/32] Add capture checking to rest of scala.runtime (except TupledFunctions) --- library/src/scala/runtime/TupleMirror.scala | 2 ++ library/src/scala/runtime/TupleXXL.scala | 2 ++ library/src/scala/runtime/TupledFunctions.scala | 2 ++ library/src/scala/runtime/Tuples.scala | 2 ++ library/src/scala/runtime/TypeBox.scala | 2 ++ library/src/scala/runtime/coverage/Invoker.scala | 2 ++ 6 files changed, 12 insertions(+) diff --git a/library/src/scala/runtime/TupleMirror.scala b/library/src/scala/runtime/TupleMirror.scala index e6981df54134..2abe4a5004d5 100644 --- a/library/src/scala/runtime/TupleMirror.scala +++ b/library/src/scala/runtime/TupleMirror.scala @@ -1,5 +1,7 @@ package scala.runtime +import language.experimental.captureChecking + /** A concrete subclass of `scala.deriving.Mirror.Product`, enabling reduction of bytecode size. * as we do not need to synthesize an anonymous Mirror class at every callsite. */ diff --git a/library/src/scala/runtime/TupleXXL.scala b/library/src/scala/runtime/TupleXXL.scala index b4a81d60f817..2da0cbb15396 100644 --- a/library/src/scala/runtime/TupleXXL.scala +++ b/library/src/scala/runtime/TupleXXL.scala @@ -1,5 +1,7 @@ package scala.runtime +import language.experimental.captureChecking + final class TupleXXL private (es: IArray[Object]) extends Product { assert(es.length > 22) diff --git a/library/src/scala/runtime/TupledFunctions.scala b/library/src/scala/runtime/TupledFunctions.scala index 52b39dedbf76..48a3a63f48a4 100644 --- a/library/src/scala/runtime/TupledFunctions.scala +++ b/library/src/scala/runtime/TupledFunctions.scala @@ -1,5 +1,7 @@ package scala.runtime +import language.experimental.captureChecking + import scala.util.TupledFunction import scala.annotation.experimental diff --git a/library/src/scala/runtime/Tuples.scala b/library/src/scala/runtime/Tuples.scala index 66dc486d2a1d..d9a078a5456a 100644 --- a/library/src/scala/runtime/Tuples.scala +++ b/library/src/scala/runtime/Tuples.scala @@ -1,5 +1,7 @@ package scala.runtime +import language.experimental.captureChecking + object Tuples { inline val MaxSpecialized = 22 diff --git a/library/src/scala/runtime/TypeBox.scala b/library/src/scala/runtime/TypeBox.scala index ec2e42eeafc7..629242460564 100644 --- a/library/src/scala/runtime/TypeBox.scala +++ b/library/src/scala/runtime/TypeBox.scala @@ -1,5 +1,7 @@ package scala.runtime +import language.experimental.captureChecking + /** A type for skolems that are generated during capture conversion. Capture conversion * narrows the type of a tree whose type has wildcard arguments. A typical situation * is a tree `t` of type `C[_ >: L <: U]` and an expected type `C[X]` where `X` is an diff --git a/library/src/scala/runtime/coverage/Invoker.scala b/library/src/scala/runtime/coverage/Invoker.scala index 98f71076b2f6..e8156c57095d 100644 --- a/library/src/scala/runtime/coverage/Invoker.scala +++ b/library/src/scala/runtime/coverage/Invoker.scala @@ -1,5 +1,7 @@ package scala.runtime.coverage +import language.experimental.captureChecking + import scala.annotation.internal.sharable import scala.annotation.nowarn import scala.collection.concurrent.TrieMap From 8c95d6cb701adfe12214d7f92ea37bf5e4ef3780 Mon Sep 17 00:00:00 2001 From: Natsu Kagami Date: Thu, 7 Aug 2025 16:35:33 +0200 Subject: [PATCH 08/32] Add capture checking to IArray --- library/src/scala/IArray.scala | 54 ++++++++++++++++++---------------- 1 file changed, 28 insertions(+), 26 deletions(-) diff --git a/library/src/scala/IArray.scala b/library/src/scala/IArray.scala index 887ca517ef2b..9b27d2f9f2d0 100644 --- a/library/src/scala/IArray.scala +++ b/library/src/scala/IArray.scala @@ -1,6 +1,8 @@ package scala import reflect.ClassTag +import language.experimental.captureChecking + import scala.collection.{LazyZip2, SeqView, Searching, Stepper, StepperShape} import scala.collection.immutable.ArraySeq import scala.collection.mutable.{ArrayBuilder, Builder} @@ -92,12 +94,12 @@ object IArray: /** Builds a new array by applying a function to all elements of this array * and using the elements of the resulting collections. */ - extension [T](arr: IArray[T]) def flatMap[U: ClassTag](f: T => IterableOnce[U]): IArray[U] = + extension [T](arr: IArray[T]) def flatMap[U: ClassTag](f: T => IterableOnce[U]^): IArray[U] = genericArrayOps(arr).flatMap(f) /** Flattens a two-dimensional array by concatenating all its rows * into a single array. */ - extension [T](arr: IArray[T]) def flatten[U](using asIterable: T => Iterable[U], ct: ClassTag[U]): IArray[U] = + extension [T](arr: IArray[T]) def flatten[U](using asIterable: T => Iterable[U]^, ct: ClassTag[U]): IArray[U] = genericArrayOps(arr).flatten /** Folds the elements of this array using the specified associative binary operator. */ @@ -222,7 +224,7 @@ object IArray: genericArrayOps(arr).sortWith(f) /** Sorts this array according to an Ordering. */ - extension [T](arr: IArray[T]) def sorted(using math.Ordering[T]): IArray[T] = + extension [T](arr: IArray[T]) def sorted(using math.Ordering[T]^): IArray[T] = genericArrayOps(arr).sorted /** Splits this array into a prefix/suffix pair according to a predicate. */ @@ -260,42 +262,42 @@ object IArray: def ++[U >: T: ClassTag](suffix: IterableOnce[U]): IArray[U] = genericArrayOps(arr) ++ suffix def :+ [U >: T: ClassTag](x: U): IArray[U] = genericArrayOps(arr) :+ x def :++ [U >: T: ClassTag](suffix: IArray[U]): IArray[U] = genericArrayOps(arr) :++ suffix - def :++ [U >: T: ClassTag](suffix: IterableOnce[U]): IArray[U] = genericArrayOps(arr) :++ suffix + def :++ [U >: T: ClassTag](suffix: IterableOnce[U]^): IArray[U] = genericArrayOps(arr) :++ suffix def appended[U >: T: ClassTag](x: U): IArray[U] = genericArrayOps(arr).appended(x) def appendedAll[U >: T: ClassTag](suffix: IArray[U]): IArray[U] = genericArrayOps(arr).appendedAll(suffix) - def appendedAll[U >: T: ClassTag](suffix: IterableOnce[U]): IArray[U] = genericArrayOps(arr).appendedAll(suffix) - def collect[U: ClassTag](pf: PartialFunction[T, U]): IArray[U] = genericArrayOps(arr).collect(pf) - def collectFirst[U](f: PartialFunction[T, U]): Option[U] = genericArrayOps(arr).collectFirst(f) + def appendedAll[U >: T: ClassTag](suffix: IterableOnce[U]^): IArray[U] = genericArrayOps(arr).appendedAll(suffix) + def collect[U: ClassTag](pf: PartialFunction[T, U]^): IArray[U] = genericArrayOps(arr).collect(pf) + def collectFirst[U](f: PartialFunction[T, U]^): Option[U] = genericArrayOps(arr).collectFirst(f) def combinations(n: Int): Iterator[IArray[T]] = genericArrayOps(arr).combinations(n) def concat[U >: T: ClassTag](suffix: IArray[U]): IArray[U] = genericArrayOps(arr).concat(suffix) - def concat[U >: T: ClassTag](suffix: IterableOnce[U]): IArray[U] = genericArrayOps(arr).concat(suffix) + def concat[U >: T: ClassTag](suffix: IterableOnce[U]^): IArray[U] = genericArrayOps(arr).concat(suffix) def diff[U >: T](that: IArray[U]): IArray[T] = genericArrayOps(arr).diff(that.toSeq) - def diff[U >: T](that: Seq[U]): IArray[T] = genericArrayOps(arr).diff(that) + def diff[U >: T](that: Seq[U]^): IArray[T] = genericArrayOps(arr).diff(that) def distinct: IArray[T] = genericArrayOps(arr).distinct def distinctBy[U](f: T => U): IArray[T] = genericArrayOps(arr).distinctBy(f) def startsWith[U >: T](that: IArray[U]): Boolean = genericArrayOps(arr).startsWith(that, 0) def startsWith[U >: T](that: IArray[U], offset: Int): Boolean = genericArrayOps(arr).startsWith(that, offset) - def startsWith[U >: T](that: IterableOnce[U]): Boolean = genericArrayOps(arr).startsWith(that, 0) - def startsWith[U >: T](that: IterableOnce[U], offset: Int): Boolean = genericArrayOps(arr).startsWith(that, offset) + def startsWith[U >: T](that: IterableOnce[U]^): Boolean = genericArrayOps(arr).startsWith(that, 0) + def startsWith[U >: T](that: IterableOnce[U]^, offset: Int): Boolean = genericArrayOps(arr).startsWith(that, offset) def endsWith[U >: T](that: IArray[U]): Boolean = genericArrayOps(arr).endsWith(that) - def endsWith[U >: T](that: Iterable[U]): Boolean = genericArrayOps(arr).endsWith(that) + def endsWith[U >: T](that: Iterable[U]^): Boolean = genericArrayOps(arr).endsWith(that) def groupBy[K](f: T => K): Map[K, IArray[T]] = genericArrayOps(arr).groupBy(f) def groupMap[K, U: ClassTag](key: T => K)(f: T => U): Map[K, IArray[U]] = genericArrayOps(arr).groupMap(key)(f) def grouped(size: Int): Iterator[IArray[T]] = genericArrayOps(arr).grouped(size) def inits: Iterator[IArray[T]] = genericArrayOps(arr).inits def intersect[U >: T](that: IArray[U]): IArray[T] = genericArrayOps(arr).intersect(that) - def intersect[U >: T](that: Seq[U]): IArray[T] = genericArrayOps(arr).intersect(that) + def intersect[U >: T](that: Seq[U]^): IArray[T] = genericArrayOps(arr).intersect(that) def lazyZip[U](that: IArray[U]): LazyZip2[T, U, IArray[T]] = genericArrayOps(arr).lazyZip[U](that).asInstanceOf[LazyZip2[T, U, IArray[T]]] - def lazyZip[U](that: Iterable[U]): LazyZip2[T, U, IArray[T]] = genericArrayOps(arr).lazyZip[U](that).asInstanceOf[LazyZip2[T, U, IArray[T]]] + def lazyZip[U](that: Iterable[U]^): LazyZip2[T, U, IArray[T]] = genericArrayOps(arr).lazyZip[U](that).asInstanceOf[LazyZip2[T, U, IArray[T]]] def lengthCompare(len: Int): Int = genericArrayOps(arr).lengthCompare(len) def padTo[U >: T: ClassTag](len: Int, elem: U): IArray[U] = genericArrayOps(arr).padTo(len, elem) def partitionMap[T1: ClassTag, T2: ClassTag](f: T => Either[T1, T2]): (IArray[T1], IArray[T2]) = genericArrayOps(arr).partitionMap(f) def patch[U >: T: ClassTag](from: Int, other: IterableOnce[U], replaced: Int): IArray[U] = genericArrayOps(arr).patch(from, other, replaced) def permutations: Iterator[IArray[T]] = genericArrayOps(arr).permutations def prepended[U >: T: ClassTag](x: U): IArray[U] = genericArrayOps(arr).prepended(x) - def prependedAll[U >: T: ClassTag](prefix: IterableOnce[U]): IArray[U] = genericArrayOps(arr).prependedAll(prefix) + def prependedAll[U >: T: ClassTag](prefix: IterableOnce[U]^): IArray[U] = genericArrayOps(arr).prependedAll(prefix) def reverseIterator: Iterator[T] = genericArrayOps(arr).reverseIterator - def search[U >: T](elem: U)(using Ordering[U]): Searching.SearchResult = arr.toSeq.search(elem) + def search[U >: T](elem: U)(using Ordering[U]^): Searching.SearchResult = arr.toSeq.search(elem) def search[U >: T](elem: U, from: Int, to: Int)(using Ordering[U]): Searching.SearchResult = arr.toSeq.search(elem, from, to) def sizeCompare(that: IArray[Any]): Int = arr.toSeq.sizeCompare(that) def sizeCompare(that: Iterable[?]): Int = arr.toSeq.sizeCompare(that) @@ -312,14 +314,14 @@ object IArray: def unzip3[T1, T2, T3](using asTriple: T => (T1, T2, T3), ct1: ClassTag[T1], ct2: ClassTag[T2], ct3: ClassTag[T3]): (IArray[T1], IArray[T2], IArray[T3]) = genericArrayOps(arr).unzip3 def updated[U >: T: ClassTag](index: Int, elem: U): IArray[U] = genericArrayOps(arr).updated(index, elem) def view: SeqView[T] = genericArrayOps(arr).view - def withFilter(p: T => Boolean): WithFilter[T] = new WithFilter(p, arr) + def withFilter(p: T => Boolean): WithFilter[T]^{p} = new WithFilter(p, arr) def zip[U](that: IArray[U]): IArray[(T, U)] = genericArrayOps(arr).zip(that) - def zip[U](that: IterableOnce[U]): IArray[(T, U)] = genericArrayOps(arr).zip(that) + def zip[U](that: IterableOnce[U]^): IArray[(T, U)] = genericArrayOps(arr).zip(that) def zipAll[T1 >: T, U](that: IArray[U], thisElem: T1, thatElem: U): IArray[(T1, U)] = genericArrayOps(arr).zipAll(that, thisElem, thatElem) - def zipAll[T1 >: T, U](that: Iterable[U], thisElem: T1, thatElem: U): IArray[(T1, U)] = genericArrayOps(arr).zipAll(that, thisElem, thatElem) + def zipAll[T1 >: T, U](that: Iterable[U]^, thisElem: T1, thatElem: U): IArray[(T1, U)] = genericArrayOps(arr).zipAll(that, thisElem, thatElem) def zipWithIndex: IArray[(T, Int)] = genericArrayOps(arr).zipWithIndex - extension [T, U >: T: ClassTag](prefix: IterableOnce[T]) + extension [T, U >: T: ClassTag](prefix: IterableOnce[T]^) def ++:(arr: IArray[U]): IArray[U] = genericArrayOps(arr).prependedAll(prefix) extension [T, U >: T: ClassTag](prefix: IArray[T]) @@ -444,7 +446,7 @@ object IArray: * @param it the iterable collection * @return an array consisting of elements of the iterable collection */ - def from[A : ClassTag](it: IterableOnce[A]): IArray[A] = + def from[A : ClassTag](it: IterableOnce[A]^): IArray[A] = unsafeFromArray(Array.from(it)) def newBuilder[T](using t: ClassTag[T]): Builder[T, IArray[T]] = @@ -606,8 +608,8 @@ object IArray: * @param ys an array of AnyRef * @return true if corresponding elements are equal */ - def equals(xs: IArray[AnyRef], ys: IArray[AnyRef]): Boolean = - Array.equals(xs.asInstanceOf[Array[AnyRef]], ys.asInstanceOf[Array[AnyRef]]) + def equals(xs: IArray[AnyRef^], ys: IArray[AnyRef^]): Boolean = + Array.equals(xs.asInstanceOf[Array[AnyRef^{xs*}]], ys.asInstanceOf[Array[AnyRef^{ys*}]]) /** Returns a decomposition of the array into a sequence. This supports * a pattern match like `{ case IArray(x,y,z) => println('3 elements')}`. @@ -660,7 +662,7 @@ object IArray: * @return a new array resulting from applying the given collection-valued function * `f` to each element of this array and concatenating the results. */ - def flatMap[U: ClassTag](f: T => IterableOnce[U]): IArray[U] = { + def flatMap[U: ClassTag](f: T => IterableOnce[U]^): IArray[U] = { val b = IArray.newBuilder[U] var i = 0 while(i < xs.length) { @@ -671,11 +673,11 @@ object IArray: b.result() } - def flatMap[BS, U](f: T => BS)(using asIterable: BS => Iterable[U], m: ClassTag[U]): IArray[U] = + def flatMap[BS, U](f: T => BS)(using asIterable: BS => Iterable[U]^, m: ClassTag[U]): IArray[U] = flatMap[U](x => asIterable(f(x))) /** Creates a new non-strict filter which combines this filter with the given predicate. */ - def withFilter(q: T => Boolean): WithFilter[T] = new WithFilter[T](a => p(a) && q(a), xs) + def withFilter(q: T => Boolean): WithFilter[T]^{p, q} = new WithFilter[T](a => p(a) && q(a), xs) end WithFilter From 9a5c1b7e227ccbcc7a55adbc6051b7f8c4745ed4 Mon Sep 17 00:00:00 2001 From: Natsu Kagami Date: Tue, 5 Aug 2025 18:13:14 +0200 Subject: [PATCH 09/32] [TODO INVESTIGATE] IArray: `Array[AnyRef^{xs*}]` not working, revert cast --- library/src/scala/IArray.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/src/scala/IArray.scala b/library/src/scala/IArray.scala index 9b27d2f9f2d0..12eac3985626 100644 --- a/library/src/scala/IArray.scala +++ b/library/src/scala/IArray.scala @@ -609,7 +609,7 @@ object IArray: * @return true if corresponding elements are equal */ def equals(xs: IArray[AnyRef^], ys: IArray[AnyRef^]): Boolean = - Array.equals(xs.asInstanceOf[Array[AnyRef^{xs*}]], ys.asInstanceOf[Array[AnyRef^{ys*}]]) + Array.equals(xs.asInstanceOf[Array[AnyRef^{xs}]], ys.asInstanceOf[Array[AnyRef^{ys}]]) /** Returns a decomposition of the array into a sequence. This supports * a pattern match like `{ case IArray(x,y,z) => println('3 elements')}`. From 397b62f953b3218bc807ed25c6d002c9a3ccb9c7 Mon Sep 17 00:00:00 2001 From: Natsu Kagami Date: Thu, 7 Aug 2025 16:35:46 +0200 Subject: [PATCH 10/32] Add capture checking to various scala.* base package files Just imports --- library/src/scala/CanEqual.scala | 2 ++ library/src/scala/CanThrow.scala | 2 ++ library/src/scala/Conversion.scala | 2 ++ library/src/scala/NamedTuple.scala | 2 ++ library/src/scala/PolyFunction.scala | 2 ++ library/src/scala/Precise.scala | 3 +++ library/src/scala/Selectable.scala | 1 + library/src/scala/caps/Pure.scala | 2 ++ library/src/scala/main.scala | 2 ++ library/src/scala/runtime/stdLibPatches/Predef.scala | 2 ++ 10 files changed, 20 insertions(+) diff --git a/library/src/scala/CanEqual.scala b/library/src/scala/CanEqual.scala index 8c331bb21b43..12cfdfc6f5fd 100644 --- a/library/src/scala/CanEqual.scala +++ b/library/src/scala/CanEqual.scala @@ -1,5 +1,7 @@ package scala +import language.experimental.captureChecking + import annotation.implicitNotFound import scala.collection.{Seq, Set, Map} diff --git a/library/src/scala/CanThrow.scala b/library/src/scala/CanThrow.scala index d55d631235e7..0852ce804cd7 100644 --- a/library/src/scala/CanThrow.scala +++ b/library/src/scala/CanThrow.scala @@ -2,6 +2,8 @@ package scala import language.experimental.erasedDefinitions import annotation.{implicitNotFound, experimental, capability} +import language.experimental.captureChecking + /** A capability class that allows to throw exception `E`. When used with the * experimental.saferExceptions feature, a `throw Ex()` expression will require * a given of class `CanThrow[Ex]` to be available. diff --git a/library/src/scala/Conversion.scala b/library/src/scala/Conversion.scala index cbae3448dab9..41c6cf0c0307 100644 --- a/library/src/scala/Conversion.scala +++ b/library/src/scala/Conversion.scala @@ -1,5 +1,7 @@ package scala +import language.experimental.captureChecking + /** A class for implicit values that can serve as implicit conversions. * The implicit resolution algorithm will act as if there existed * the additional implicit definition: diff --git a/library/src/scala/NamedTuple.scala b/library/src/scala/NamedTuple.scala index c63ad29c56e9..f88f7760365b 100644 --- a/library/src/scala/NamedTuple.scala +++ b/library/src/scala/NamedTuple.scala @@ -1,6 +1,8 @@ package scala import compiletime.ops.boolean.* +import language.experimental.captureChecking + object NamedTuple: /** The type to which named tuples get mapped to. For instance, diff --git a/library/src/scala/PolyFunction.scala b/library/src/scala/PolyFunction.scala index 44278b6cffde..f37b1f9eab45 100644 --- a/library/src/scala/PolyFunction.scala +++ b/library/src/scala/PolyFunction.scala @@ -1,5 +1,7 @@ package scala +import language.experimental.captureChecking + /* (EXPERIMENTAL) NEW DOCUMENTATION: This should be used when we stabilize erased definitions or other generalize other function types. * * Marker trait for many (poly) function types. diff --git a/library/src/scala/Precise.scala b/library/src/scala/Precise.scala index f8a8dd6b47f4..838327c79409 100644 --- a/library/src/scala/Precise.scala +++ b/library/src/scala/Precise.scala @@ -1,4 +1,7 @@ package scala + +import language.experimental.captureChecking + import annotation.experimental import language.experimental.erasedDefinitions diff --git a/library/src/scala/Selectable.scala b/library/src/scala/Selectable.scala index 74004a350679..801ab1ea4bc7 100644 --- a/library/src/scala/Selectable.scala +++ b/library/src/scala/Selectable.scala @@ -1,5 +1,6 @@ package scala +import language.experimental.captureChecking /** A marker trait for objects that support structural selection via * `selectDynamic` and `applyDynamic` diff --git a/library/src/scala/caps/Pure.scala b/library/src/scala/caps/Pure.scala index dfb8127bcc7f..11d0e3f039e9 100644 --- a/library/src/scala/caps/Pure.scala +++ b/library/src/scala/caps/Pure.scala @@ -1,6 +1,8 @@ package scala package caps +import language.experimental.captureChecking + /** A marker trait that declares that all inheriting classes are "pure" in the * sense that their values retain no capabilities including capabilities needed * to perform effects. This has formal meaning only under capture checking. diff --git a/library/src/scala/main.scala b/library/src/scala/main.scala index 057fdad4c2fb..f0494bf975e0 100644 --- a/library/src/scala/main.scala +++ b/library/src/scala/main.scala @@ -8,6 +8,8 @@ package scala +import language.experimental.captureChecking + /** An annotation that designates a main function */ class main extends scala.annotation.Annotation {} diff --git a/library/src/scala/runtime/stdLibPatches/Predef.scala b/library/src/scala/runtime/stdLibPatches/Predef.scala index 3ea13255ac73..ed4cf207c925 100644 --- a/library/src/scala/runtime/stdLibPatches/Predef.scala +++ b/library/src/scala/runtime/stdLibPatches/Predef.scala @@ -1,5 +1,7 @@ package scala.runtime.stdLibPatches +import scala.language.experimental.captureChecking + import scala.annotation.experimental import scala.annotation.internal.RuntimeChecked From 7155f3d0361316dcb10af96c76cdbbd2a5847387 Mon Sep 17 00:00:00 2001 From: Natsu Kagami Date: Mon, 7 Apr 2025 18:32:32 +0200 Subject: [PATCH 11/32] [TODO FIX] Temporarily drop upper bound of higher-kinded type `F` in tuple match types Currently it's tripping up the cc phase --- library/src/scala/NamedTuple.scala | 2 +- library/src/scala/Tuple.scala | 7 ++++--- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/library/src/scala/NamedTuple.scala b/library/src/scala/NamedTuple.scala index f88f7760365b..aee1695750cd 100644 --- a/library/src/scala/NamedTuple.scala +++ b/library/src/scala/NamedTuple.scala @@ -89,7 +89,7 @@ object NamedTuple: /** The type of the named tuple `X` mapped with the type-level function `F`. * If `X = (n1 : T1, ..., ni : Ti)` then `Map[X, F] = `(n1 : F[T1], ..., ni : F[Ti])`. */ - type Map[X <: AnyNamedTuple, F[_ <: Tuple.Union[DropNames[X]]]] = + type Map[X <: AnyNamedTuple, F[_]] = NamedTuple[Names[X], Tuple.Map[DropNames[X], F]] /** A named tuple with the elements of tuple `X` in reversed order */ diff --git a/library/src/scala/Tuple.scala b/library/src/scala/Tuple.scala index 57d1572772e2..1337784cc9e2 100644 --- a/library/src/scala/Tuple.scala +++ b/library/src/scala/Tuple.scala @@ -1,5 +1,6 @@ package scala +import language.experimental.captureChecking import annotation.showAsInfix import compiletime.* import compiletime.ops.int.* @@ -174,13 +175,13 @@ object Tuple { case h *: t => F[h, Fold[t, Z, F]] /** Converts a tuple `(T1, ..., Tn)` to `(F[T1], ..., F[Tn])` */ - type Map[Tup <: Tuple, F[_ <: Union[Tup]]] <: Tuple = Tup match { + type Map[Tup <: Tuple, F[_]] <: Tuple = Tup match { case EmptyTuple => EmptyTuple case h *: t => F[h] *: Map[t, F] } /** Converts a tuple `(T1, ..., Tn)` to a flattened `(..F[T1], ..., ..F[Tn])` */ - type FlatMap[Tup <: Tuple, F[_ <: Union[Tup]] <: Tuple] <: Tuple = Tup match { + type FlatMap[Tup <: Tuple, F[_] <: Tuple] <: Tuple = Tup match { case EmptyTuple => EmptyTuple case h *: t => Concat[F[h], FlatMap[t, F]] } @@ -196,7 +197,7 @@ object Tuple { * ``` * @syntax markdown */ - type Filter[Tup <: Tuple, P[_ <: Union[Tup]] <: Boolean] <: Tuple = Tup match { + type Filter[Tup <: Tuple, P[_] <: Boolean] <: Tuple = Tup match { case EmptyTuple => EmptyTuple case h *: t => P[h] match { case true => h *: Filter[t, P] From 1c7196d90e2b877d2155326a03bc7b1a9f1763ef Mon Sep 17 00:00:00 2001 From: Natsu Kagami Date: Mon, 7 Apr 2025 18:42:15 +0200 Subject: [PATCH 12/32] Add capture checking to scala.reflect Just imports for now, no quotes support for capturing types yet --- library/src/scala/reflect/Enum.scala | 2 ++ library/src/scala/reflect/Selectable.scala | 2 ++ library/src/scala/reflect/TypeTest.scala | 2 ++ library/src/scala/reflect/Typeable.scala | 2 ++ 4 files changed, 8 insertions(+) diff --git a/library/src/scala/reflect/Enum.scala b/library/src/scala/reflect/Enum.scala index 8fb9135f6478..3be8965c97a6 100644 --- a/library/src/scala/reflect/Enum.scala +++ b/library/src/scala/reflect/Enum.scala @@ -1,5 +1,7 @@ package scala.reflect +import language.experimental.captureChecking + /** A base trait of all Scala enum definitions */ transparent trait Enum extends Any, Product, Serializable: diff --git a/library/src/scala/reflect/Selectable.scala b/library/src/scala/reflect/Selectable.scala index ac8e502128bb..52b584bf815e 100644 --- a/library/src/scala/reflect/Selectable.scala +++ b/library/src/scala/reflect/Selectable.scala @@ -1,5 +1,7 @@ package scala.reflect +import language.experimental.captureChecking + /** A class that implements structural selections using Java reflection. * * It can be used as a supertrait of a class or be made available diff --git a/library/src/scala/reflect/TypeTest.scala b/library/src/scala/reflect/TypeTest.scala index 23dea5ec9ced..b122d3b92bc2 100644 --- a/library/src/scala/reflect/TypeTest.scala +++ b/library/src/scala/reflect/TypeTest.scala @@ -1,5 +1,7 @@ package scala.reflect +import language.experimental.captureChecking + /** A `TypeTest[S, T]` contains the logic needed to know at runtime if a value of * type `S` is an instance of `T`. * diff --git a/library/src/scala/reflect/Typeable.scala b/library/src/scala/reflect/Typeable.scala index 3214de77123e..a298d91041c6 100644 --- a/library/src/scala/reflect/Typeable.scala +++ b/library/src/scala/reflect/Typeable.scala @@ -1,5 +1,7 @@ package scala.reflect +import language.experimental.captureChecking + /** A shorhand for `TypeTest[Any, T]`. A `Typeable[T] contains the logic needed to * know at runtime if a value can be downcasted to `T`. * From 67f8eecbe42f2cdaa8dd42f694fe0b6c83366fcf Mon Sep 17 00:00:00 2001 From: Natsu Kagami Date: Mon, 7 Apr 2025 18:42:34 +0200 Subject: [PATCH 13/32] [TODO REMOVE] Add TODO list --- TODO.md | 66 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 66 insertions(+) create mode 100644 TODO.md diff --git a/TODO.md b/TODO.md new file mode 100644 index 000000000000..98e15f8b8d3f --- /dev/null +++ b/TODO.md @@ -0,0 +1,66 @@ +- [ ] library/src/scala/annotation/MacroAnnotation.scala +- [ ] library/src/scala/annotation/RefiningAnnotation.scala +- [ ] library/src/scala/annotation/alpha.scala +- [ ] library/src/scala/annotation/capability.scala +- [ ] library/src/scala/annotation/constructorOnly.scala +- [ ] library/src/scala/annotation/experimental.scala +- [ ] library/src/scala/annotation/init.scala +- [ ] library/src/scala/annotation/internal/$into.scala +- [ ] library/src/scala/annotation/internal/Alias.scala +- [ ] library/src/scala/annotation/internal/AnnotationDefault.scala +- [ ] library/src/scala/annotation/internal/AssignedNonLocally.scala +- [ ] library/src/scala/annotation/internal/Body.scala +- [ ] library/src/scala/annotation/internal/Child.scala +- [ ] library/src/scala/annotation/internal/ContextResultCount.scala +- [ ] library/src/scala/annotation/internal/ErasedParam.scala +- [ ] library/src/scala/annotation/internal/InlineParam.scala +- [ ] library/src/scala/annotation/internal/MappedAlternative.scala +- [ ] library/src/scala/annotation/internal/ProvisionalSuperClass.scala +- [ ] library/src/scala/annotation/internal/Repeated.scala +- [ ] library/src/scala/annotation/internal/RuntimeChecked.scala +- [ ] library/src/scala/annotation/internal/SourceFile.scala +- [ ] library/src/scala/annotation/internal/WithPureFuns.scala +- [ ] library/src/scala/annotation/internal/WitnessNames.scala +- [ ] library/src/scala/annotation/internal/preview.scala +- [ ] library/src/scala/annotation/internal/reachCapability.scala +- [ ] library/src/scala/annotation/internal/readOnlyCapability.scala +- [ ] library/src/scala/annotation/internal/requiresCapability.scala +- [ ] library/src/scala/annotation/internal/sharable.scala +- [ ] library/src/scala/annotation/internal/unshared.scala +- [ ] library/src/scala/annotation/into.scala +- [ ] library/src/scala/annotation/publicInBinary.scala +- [ ] library/src/scala/annotation/retains.scala +- [ ] library/src/scala/annotation/retainsByName.scala +- [ ] library/src/scala/annotation/static.scala +- [ ] library/src/scala/annotation/targetName.scala +- [ ] library/src/scala/annotation/threadUnsafe.scala +- [ ] library/src/scala/annotation/transparentTrait.scala +- [ ] library/src/scala/annotation/unchecked/uncheckedCapabilityLeaks.scala +- [ ] library/src/scala/annotation/unchecked/uncheckedCaptures.scala +- [ ] library/src/scala/annotation/unroll.scala +- [ ] library/src/scala/compiletime/ops/any.scala +- [ ] library/src/scala/compiletime/ops/boolean.scala +- [ ] library/src/scala/compiletime/ops/double.scala +- [ ] library/src/scala/compiletime/ops/float.scala +- [ ] library/src/scala/compiletime/ops/int.scala +- [ ] library/src/scala/compiletime/ops/long.scala +- [ ] library/src/scala/compiletime/ops/string.scala +- [ ] library/src/scala/compiletime/package.scala +- [ ] library/src/scala/compiletime/testing/Error.scala +- [ ] library/src/scala/compiletime/testing/ErrorKind.scala +- [ ] library/src/scala/compiletime/testing/package.scala +- [ ] library/src/scala/deriving/Mirror.scala +- [ ] library/src/scala/quoted/Expr.scala +- [ ] library/src/scala/quoted/ExprMap.scala +- [ ] library/src/scala/quoted/Exprs.scala +- [ ] library/src/scala/quoted/FromExpr.scala +- [ ] library/src/scala/quoted/Quotes.scala +- [ ] library/src/scala/quoted/ToExpr.scala +- [ ] library/src/scala/quoted/Type.scala +- [ ] library/src/scala/quoted/Varargs.scala +- [ ] library/src/scala/quoted/runtime/Expr.scala +- [ ] library/src/scala/quoted/runtime/Patterns.scala +- [ ] library/src/scala/quoted/runtime/QuoteMatching.scala +- [ ] library/src/scala/quoted/runtime/QuoteUnpickler.scala +- [ ] library/src/scala/quoted/runtime/SplicedType.scala +- [ ] library/src/scala/quoted/runtime/StopMacroExpansion.scala From 0791961c0765b084511a65df5ced8748b6f3cbdc Mon Sep 17 00:00:00 2001 From: Natsu Kagami Date: Tue, 8 Apr 2025 11:07:09 +0200 Subject: [PATCH 14/32] [TODO EXPLAIN] Add capture checking to Mirror and TupleMirror We need to split the files here, because... ? --- TODO.md | 45 +++++++++++++++++-- .../dotc/transform/SyntheticMembers.scala | 2 + library/src/scala/deriving/Mirror.scala | 4 +- mk_todo.fish | 6 +++ 4 files changed, 52 insertions(+), 5 deletions(-) create mode 100755 mk_todo.fish diff --git a/TODO.md b/TODO.md index 98e15f8b8d3f..b3a67da8893c 100644 --- a/TODO.md +++ b/TODO.md @@ -1,3 +1,13 @@ +- [x] library/src/scala/CanEqual.scala +- [x] library/src/scala/CanThrow.scala +- [x] library/src/scala/Conversion.scala +- [x] library/src/scala/IArray.scala +- [x] library/src/scala/NamedTuple.scala +- [x] library/src/scala/PolyFunction.scala +- [x] library/src/scala/Precise.scala +- [x] library/src/scala/Pure.scala +- [x] library/src/scala/Selectable.scala +- [x] library/src/scala/Tuple.scala - [ ] library/src/scala/annotation/MacroAnnotation.scala - [ ] library/src/scala/annotation/RefiningAnnotation.scala - [ ] library/src/scala/annotation/alpha.scala @@ -10,6 +20,7 @@ - [ ] library/src/scala/annotation/internal/AnnotationDefault.scala - [ ] library/src/scala/annotation/internal/AssignedNonLocally.scala - [ ] library/src/scala/annotation/internal/Body.scala +- [ ] library/src/scala/annotation/internal/CaptureChecked.scala - [ ] library/src/scala/annotation/internal/Child.scala - [ ] library/src/scala/annotation/internal/ContextResultCount.scala - [ ] library/src/scala/annotation/internal/ErasedParam.scala @@ -38,6 +49,7 @@ - [ ] library/src/scala/annotation/unchecked/uncheckedCapabilityLeaks.scala - [ ] library/src/scala/annotation/unchecked/uncheckedCaptures.scala - [ ] library/src/scala/annotation/unroll.scala +- [ ] library/src/scala/caps/package.scala - [ ] library/src/scala/compiletime/ops/any.scala - [ ] library/src/scala/compiletime/ops/boolean.scala - [ ] library/src/scala/compiletime/ops/double.scala @@ -46,10 +58,10 @@ - [ ] library/src/scala/compiletime/ops/long.scala - [ ] library/src/scala/compiletime/ops/string.scala - [ ] library/src/scala/compiletime/package.scala -- [ ] library/src/scala/compiletime/testing/Error.scala -- [ ] library/src/scala/compiletime/testing/ErrorKind.scala -- [ ] library/src/scala/compiletime/testing/package.scala -- [ ] library/src/scala/deriving/Mirror.scala +- [x] library/src/scala/compiletime/testing/Error.scala +- [x] library/src/scala/compiletime/testing/ErrorKind.scala +- [x] library/src/scala/compiletime/testing/package.scala +- [x] library/src/scala/main.scala - [ ] library/src/scala/quoted/Expr.scala - [ ] library/src/scala/quoted/ExprMap.scala - [ ] library/src/scala/quoted/Exprs.scala @@ -64,3 +76,28 @@ - [ ] library/src/scala/quoted/runtime/QuoteUnpickler.scala - [ ] library/src/scala/quoted/runtime/SplicedType.scala - [ ] library/src/scala/quoted/runtime/StopMacroExpansion.scala +- [x] library/src/scala/reflect/Enum.scala +- [x] library/src/scala/reflect/Selectable.scala +- [x] library/src/scala/reflect/TypeTest.scala +- [x] library/src/scala/reflect/Typeable.scala +- [x] library/src/scala/runtime/$throws.scala +- [x] library/src/scala/runtime/Arrays.scala +- [x] library/src/scala/runtime/EnumValue.scala +- [x] library/src/scala/runtime/FunctionXXL.scala +- [x] library/src/scala/runtime/LazyVals.scala +- [x] library/src/scala/runtime/MatchCase.scala +- [x] library/src/scala/runtime/Scala3RunTime.scala +- [x] library/src/scala/runtime/TupleMirror.scala +- [x] library/src/scala/runtime/TupleXXL.scala +- [x] library/src/scala/runtime/TupledFunctions.scala +- [x] library/src/scala/runtime/Tuples.scala +- [x] library/src/scala/runtime/TypeBox.scala +- [x] library/src/scala/runtime/coverage/Invoker.scala +- [ ] library/src/scala/runtime/stdLibPatches/Predef.scala +- [ ] library/src/scala/runtime/stdLibPatches/language.scala +- [x] library/src/scala/util/CommandLineParser.scala +- [x] library/src/scala/util/FromDigits.scala +- [x] library/src/scala/util/NotGiven.scala +- [x] library/src/scala/util/TupledFunction.scala +- [x] library/src/scala/util/boundary.scala +- [x] library/src/scala/util/control/NonLocalReturns.scala diff --git a/compiler/src/dotty/tools/dotc/transform/SyntheticMembers.scala b/compiler/src/dotty/tools/dotc/transform/SyntheticMembers.scala index fbff51acb514..6ea8773f4664 100644 --- a/compiler/src/dotty/tools/dotc/transform/SyntheticMembers.scala +++ b/compiler/src/dotty/tools/dotc/transform/SyntheticMembers.scala @@ -17,6 +17,8 @@ import util.Spans.Span import config.Printers.derive import NullOpsDecorator.* import scala.runtime.Statics +import dotty.tools.dotc.config.Feature +import dotty.tools.dotc.cc.CapturingType object SyntheticMembers { diff --git a/library/src/scala/deriving/Mirror.scala b/library/src/scala/deriving/Mirror.scala index a7477cf0fb2d..c69577d20cc1 100644 --- a/library/src/scala/deriving/Mirror.scala +++ b/library/src/scala/deriving/Mirror.scala @@ -1,5 +1,7 @@ package scala.deriving +import language.experimental.captureChecking + /** Mirrors allows typelevel access to enums, case classes and objects, and their sealed parents. */ sealed trait Mirror { @@ -23,7 +25,7 @@ object Mirror { } /** The Mirror for a product type */ - trait Product extends Mirror { + trait Product extends Mirror { self => /** Create a new instance of type `T` with elements taken from product `p`. */ def fromProduct(p: scala.Product): MirroredMonoType diff --git a/mk_todo.fish b/mk_todo.fish new file mode 100755 index 000000000000..606e2787b8ab --- /dev/null +++ b/mk_todo.fish @@ -0,0 +1,6 @@ +#!/usr/bin/env fish + +for file in (ls library/src/**.scala | sort) + set checkbox (if rg -Fq "import language.experimental.captureChecking" $file; echo "[x]"; else; echo "[ ]"; end) + printf "- %s %s\n" $checkbox $file +end From d3ad017c597c7ebe26f082bc2e8fa0cd8dc6e04e Mon Sep 17 00:00:00 2001 From: Natsu Kagami Date: Mon, 11 Aug 2025 02:11:59 +0200 Subject: [PATCH 15/32] Disable CC on Mirror for now, it's interferring with case classes --- library/src/scala/deriving/Mirror.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/src/scala/deriving/Mirror.scala b/library/src/scala/deriving/Mirror.scala index c69577d20cc1..85351e9b7f23 100644 --- a/library/src/scala/deriving/Mirror.scala +++ b/library/src/scala/deriving/Mirror.scala @@ -1,6 +1,6 @@ package scala.deriving -import language.experimental.captureChecking +// import language.experimental.captureChecking /** Mirrors allows typelevel access to enums, case classes and objects, and their sealed parents. */ From 11c1aa36d6e2c61cf1a94adef3e3ed2dfca9acec Mon Sep 17 00:00:00 2001 From: Natsu Kagami Date: Tue, 8 Apr 2025 13:45:46 +0200 Subject: [PATCH 16/32] Add capture checking to scala.caps --- TODO.md | 2 +- compiler/src/dotty/tools/dotc/cc/Synthetics.scala | 2 +- library/src/scala/caps/package.scala | 2 ++ library/src/scala/compiletime/testing/Error.scala | 2 ++ library/src/scala/compiletime/testing/ErrorKind.scala | 2 ++ library/src/scala/compiletime/testing/package.scala | 2 ++ 6 files changed, 10 insertions(+), 2 deletions(-) diff --git a/TODO.md b/TODO.md index b3a67da8893c..3d574234552f 100644 --- a/TODO.md +++ b/TODO.md @@ -49,7 +49,7 @@ - [ ] library/src/scala/annotation/unchecked/uncheckedCapabilityLeaks.scala - [ ] library/src/scala/annotation/unchecked/uncheckedCaptures.scala - [ ] library/src/scala/annotation/unroll.scala -- [ ] library/src/scala/caps/package.scala +- [x] library/src/scala/caps/package.scala - [ ] library/src/scala/compiletime/ops/any.scala - [ ] library/src/scala/compiletime/ops/boolean.scala - [ ] library/src/scala/compiletime/ops/double.scala diff --git a/compiler/src/dotty/tools/dotc/cc/Synthetics.scala b/compiler/src/dotty/tools/dotc/cc/Synthetics.scala index bb2228932cb8..a32cb76fc127 100644 --- a/compiler/src/dotty/tools/dotc/cc/Synthetics.scala +++ b/compiler/src/dotty/tools/dotc/cc/Synthetics.scala @@ -168,4 +168,4 @@ object Synthetics: transformCompareCaptures) end transform -end Synthetics \ No newline at end of file +end Synthetics diff --git a/library/src/scala/caps/package.scala b/library/src/scala/caps/package.scala index ff029fbbae9c..3dee23d3e8e1 100644 --- a/library/src/scala/caps/package.scala +++ b/library/src/scala/caps/package.scala @@ -1,6 +1,8 @@ package scala package caps +import language.experimental.captureChecking + import annotation.{experimental, compileTimeOnly, retainsCap} /** diff --git a/library/src/scala/compiletime/testing/Error.scala b/library/src/scala/compiletime/testing/Error.scala index fc6ca0bcaabc..65ad302771db 100644 --- a/library/src/scala/compiletime/testing/Error.scala +++ b/library/src/scala/compiletime/testing/Error.scala @@ -1,5 +1,7 @@ package scala.compiletime.testing +import language.experimental.captureChecking + /** Represents a compile-time error. * * @see scala.compiletime.testing.typeCheckErrors diff --git a/library/src/scala/compiletime/testing/ErrorKind.scala b/library/src/scala/compiletime/testing/ErrorKind.scala index c7e38ae22d83..1e45e3250f94 100644 --- a/library/src/scala/compiletime/testing/ErrorKind.scala +++ b/library/src/scala/compiletime/testing/ErrorKind.scala @@ -1,5 +1,7 @@ package scala.compiletime.testing +import language.experimental.captureChecking + /** An error can be either a parse-time or a typecheck-time */ sealed trait ErrorKind // This should be an enum but currently, Dotty lib fails to // compile with an obscure error. diff --git a/library/src/scala/compiletime/testing/package.scala b/library/src/scala/compiletime/testing/package.scala index ebe629244fb3..b2c4cbedf9df 100644 --- a/library/src/scala/compiletime/testing/package.scala +++ b/library/src/scala/compiletime/testing/package.scala @@ -1,6 +1,8 @@ package scala.compiletime package testing +import language.experimental.captureChecking + /** Whether the code type checks in the current context? * * An inline definition with a call to `typeChecks` should be transparent. From 3b1ca637737830a557f1442dd9068edba305104d Mon Sep 17 00:00:00 2001 From: Natsu Kagami Date: Wed, 9 Apr 2025 20:38:03 +0200 Subject: [PATCH 17/32] Add capture checking to compiletime.Ops --- TODO.md | 16 ++++++++-------- library/src/scala/compiletime/ops/any.scala | 2 ++ library/src/scala/compiletime/ops/boolean.scala | 2 ++ library/src/scala/compiletime/ops/double.scala | 2 ++ library/src/scala/compiletime/ops/float.scala | 2 ++ library/src/scala/compiletime/ops/int.scala | 2 ++ library/src/scala/compiletime/ops/long.scala | 2 ++ library/src/scala/compiletime/ops/string.scala | 2 ++ library/src/scala/compiletime/package.scala | 2 ++ 9 files changed, 24 insertions(+), 8 deletions(-) diff --git a/TODO.md b/TODO.md index 3d574234552f..a64c7b18b349 100644 --- a/TODO.md +++ b/TODO.md @@ -50,14 +50,14 @@ - [ ] library/src/scala/annotation/unchecked/uncheckedCaptures.scala - [ ] library/src/scala/annotation/unroll.scala - [x] library/src/scala/caps/package.scala -- [ ] library/src/scala/compiletime/ops/any.scala -- [ ] library/src/scala/compiletime/ops/boolean.scala -- [ ] library/src/scala/compiletime/ops/double.scala -- [ ] library/src/scala/compiletime/ops/float.scala -- [ ] library/src/scala/compiletime/ops/int.scala -- [ ] library/src/scala/compiletime/ops/long.scala -- [ ] library/src/scala/compiletime/ops/string.scala -- [ ] library/src/scala/compiletime/package.scala +- [x] library/src/scala/compiletime/ops/any.scala +- [x] library/src/scala/compiletime/ops/boolean.scala +- [x] library/src/scala/compiletime/ops/double.scala +- [x] library/src/scala/compiletime/ops/float.scala +- [x] library/src/scala/compiletime/ops/int.scala +- [x] library/src/scala/compiletime/ops/long.scala +- [x] library/src/scala/compiletime/ops/string.scala +- [x] library/src/scala/compiletime/package.scala - [x] library/src/scala/compiletime/testing/Error.scala - [x] library/src/scala/compiletime/testing/ErrorKind.scala - [x] library/src/scala/compiletime/testing/package.scala diff --git a/library/src/scala/compiletime/ops/any.scala b/library/src/scala/compiletime/ops/any.scala index b3c1930f9715..26e38d234b78 100644 --- a/library/src/scala/compiletime/ops/any.scala +++ b/library/src/scala/compiletime/ops/any.scala @@ -1,6 +1,8 @@ package scala.compiletime package ops +import language.experimental.captureChecking + object any: /** Equality comparison of two singleton types. * ```scala diff --git a/library/src/scala/compiletime/ops/boolean.scala b/library/src/scala/compiletime/ops/boolean.scala index 3e1b5650a519..0ef6785e2fcd 100644 --- a/library/src/scala/compiletime/ops/boolean.scala +++ b/library/src/scala/compiletime/ops/boolean.scala @@ -1,6 +1,8 @@ package scala.compiletime package ops +import language.experimental.captureChecking + object boolean: /** Negation of a `Boolean` singleton type. diff --git a/library/src/scala/compiletime/ops/double.scala b/library/src/scala/compiletime/ops/double.scala index 4bb4527f14a9..789df9c6462c 100644 --- a/library/src/scala/compiletime/ops/double.scala +++ b/library/src/scala/compiletime/ops/double.scala @@ -1,6 +1,8 @@ package scala.compiletime package ops +import language.experimental.captureChecking + object double: /** Addition of two `Double` singleton types. * ```scala diff --git a/library/src/scala/compiletime/ops/float.scala b/library/src/scala/compiletime/ops/float.scala index bd9b5c75f1f1..70a06522f526 100644 --- a/library/src/scala/compiletime/ops/float.scala +++ b/library/src/scala/compiletime/ops/float.scala @@ -1,6 +1,8 @@ package scala.compiletime package ops +import language.experimental.captureChecking + object float: /** Addition of two `Float` singleton types. * ```scala diff --git a/library/src/scala/compiletime/ops/int.scala b/library/src/scala/compiletime/ops/int.scala index b8ec370421e2..b74ee054da6d 100644 --- a/library/src/scala/compiletime/ops/int.scala +++ b/library/src/scala/compiletime/ops/int.scala @@ -1,6 +1,8 @@ package scala.compiletime package ops +import language.experimental.captureChecking + object int: /** Successor of a natural number where zero is the type 0 and successors are reduced as if the definition was: * diff --git a/library/src/scala/compiletime/ops/long.scala b/library/src/scala/compiletime/ops/long.scala index 3bda31e4979c..7188dffb5af8 100644 --- a/library/src/scala/compiletime/ops/long.scala +++ b/library/src/scala/compiletime/ops/long.scala @@ -1,6 +1,8 @@ package scala.compiletime package ops +import language.experimental.captureChecking + object long: /** Successor of a natural number where zero is the type 0 and successors are reduced as if the definition was: * diff --git a/library/src/scala/compiletime/ops/string.scala b/library/src/scala/compiletime/ops/string.scala index 90515c62e55b..9ef5a3fb7b79 100644 --- a/library/src/scala/compiletime/ops/string.scala +++ b/library/src/scala/compiletime/ops/string.scala @@ -1,6 +1,8 @@ package scala.compiletime package ops +import language.experimental.captureChecking + object string: /** Concatenation of two `String` singleton types. * ```scala diff --git a/library/src/scala/compiletime/package.scala b/library/src/scala/compiletime/package.scala index 1a161ebd4a03..3821b9dbd2e7 100644 --- a/library/src/scala/compiletime/package.scala +++ b/library/src/scala/compiletime/package.scala @@ -1,6 +1,8 @@ package scala package compiletime +import language.experimental.captureChecking + import annotation.{compileTimeOnly, experimental} /** Use this method when you have a type, do not have a value for it but want to From af9d128743fefcba9b3f2f4010727390be793761 Mon Sep 17 00:00:00 2001 From: Natsu Kagami Date: Wed, 9 Apr 2025 20:39:55 +0200 Subject: [PATCH 18/32] Add capture checking to stdLibPatches --- TODO.md | 4 ++-- library/src/scala/runtime/stdLibPatches/language.scala | 2 ++ mk_todo.fish | 2 +- 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/TODO.md b/TODO.md index a64c7b18b349..5437ab1f3f71 100644 --- a/TODO.md +++ b/TODO.md @@ -93,8 +93,8 @@ - [x] library/src/scala/runtime/Tuples.scala - [x] library/src/scala/runtime/TypeBox.scala - [x] library/src/scala/runtime/coverage/Invoker.scala -- [ ] library/src/scala/runtime/stdLibPatches/Predef.scala -- [ ] library/src/scala/runtime/stdLibPatches/language.scala +- [x] library/src/scala/runtime/stdLibPatches/Predef.scala +- [x] library/src/scala/runtime/stdLibPatches/language.scala - [x] library/src/scala/util/CommandLineParser.scala - [x] library/src/scala/util/FromDigits.scala - [x] library/src/scala/util/NotGiven.scala diff --git a/library/src/scala/runtime/stdLibPatches/language.scala b/library/src/scala/runtime/stdLibPatches/language.scala index c16f9eec7fe7..202afbbe5064 100644 --- a/library/src/scala/runtime/stdLibPatches/language.scala +++ b/library/src/scala/runtime/stdLibPatches/language.scala @@ -1,5 +1,7 @@ package scala.runtime.stdLibPatches +import scala.language.experimental.captureChecking + import scala.annotation.compileTimeOnly /** Scala 3 additions and replacements to the `scala.language` object. diff --git a/mk_todo.fish b/mk_todo.fish index 606e2787b8ab..365c2c46dcd5 100755 --- a/mk_todo.fish +++ b/mk_todo.fish @@ -1,6 +1,6 @@ #!/usr/bin/env fish for file in (ls library/src/**.scala | sort) - set checkbox (if rg -Fq "import language.experimental.captureChecking" $file; echo "[x]"; else; echo "[ ]"; end) + set checkbox (if rg -q 'import (scala.)?language.experimental.captureChecking' $file; echo "[x]"; else; echo "[ ]"; end) printf "- %s %s\n" $checkbox $file end From e2f2387744608fe8185648405f96a30d2fbe023b Mon Sep 17 00:00:00 2001 From: Natsu Kagami Date: Thu, 10 Apr 2025 12:01:41 +0200 Subject: [PATCH 19/32] Add capture checking to annotations --- TODO.md | 80 +++++++++---------- .../scala/annotation/MacroAnnotation.scala | 2 + .../scala/annotation/RefiningAnnotation.scala | 2 + library/src/scala/annotation/alpha.scala | 2 + library/src/scala/annotation/capability.scala | 2 + .../scala/annotation/constructorOnly.scala | 2 + .../src/scala/annotation/experimental.scala | 2 + library/src/scala/annotation/init.scala | 2 + .../src/scala/annotation/internal/$into.scala | 3 + .../src/scala/annotation/internal/Alias.scala | 2 + .../internal/AnnotationDefault.scala | 2 + .../internal/AssignedNonLocally.scala | 2 + .../src/scala/annotation/internal/Body.scala | 2 + .../annotation/internal/CaptureChecked.scala | 2 + .../src/scala/annotation/internal/Child.scala | 2 + .../internal/ContextResultCount.scala | 2 + .../annotation/internal/ErasedParam.scala | 2 + .../annotation/internal/InlineParam.scala | 2 + .../internal/MappedAlternative.scala | 2 + .../internal/ProvisionalSuperClass.scala | 2 + .../scala/annotation/internal/Repeated.scala | 2 + .../annotation/internal/RuntimeChecked.scala | 2 + .../annotation/internal/SourceFile.scala | 2 + .../annotation/internal/WithPureFuns.scala | 2 + .../annotation/internal/WitnessNames.scala | 2 + .../scala/annotation/internal/preview.scala | 1 + .../annotation/internal/reachCapability.scala | 2 + .../internal/readOnlyCapability.scala | 2 + .../internal/requiresCapability.scala | 2 + .../scala/annotation/internal/sharable.scala | 2 + .../scala/annotation/internal/unshared.scala | 2 + .../src/scala/annotation/publicInBinary.scala | 2 + library/src/scala/annotation/retains.scala | 2 + .../src/scala/annotation/retainsByName.scala | 2 + library/src/scala/annotation/static.scala | 2 + library/src/scala/annotation/targetName.scala | 2 + .../src/scala/annotation/threadUnsafe.scala | 2 + .../scala/annotation/transparentTrait.scala | 2 + .../unchecked/uncheckedCaptures.scala | 2 + library/src/scala/annotation/unroll.scala | 2 + 40 files changed, 118 insertions(+), 40 deletions(-) diff --git a/TODO.md b/TODO.md index 5437ab1f3f71..568b81335d94 100644 --- a/TODO.md +++ b/TODO.md @@ -8,47 +8,47 @@ - [x] library/src/scala/Pure.scala - [x] library/src/scala/Selectable.scala - [x] library/src/scala/Tuple.scala -- [ ] library/src/scala/annotation/MacroAnnotation.scala -- [ ] library/src/scala/annotation/RefiningAnnotation.scala -- [ ] library/src/scala/annotation/alpha.scala -- [ ] library/src/scala/annotation/capability.scala -- [ ] library/src/scala/annotation/constructorOnly.scala -- [ ] library/src/scala/annotation/experimental.scala -- [ ] library/src/scala/annotation/init.scala -- [ ] library/src/scala/annotation/internal/$into.scala -- [ ] library/src/scala/annotation/internal/Alias.scala -- [ ] library/src/scala/annotation/internal/AnnotationDefault.scala -- [ ] library/src/scala/annotation/internal/AssignedNonLocally.scala -- [ ] library/src/scala/annotation/internal/Body.scala -- [ ] library/src/scala/annotation/internal/CaptureChecked.scala -- [ ] library/src/scala/annotation/internal/Child.scala -- [ ] library/src/scala/annotation/internal/ContextResultCount.scala -- [ ] library/src/scala/annotation/internal/ErasedParam.scala -- [ ] library/src/scala/annotation/internal/InlineParam.scala -- [ ] library/src/scala/annotation/internal/MappedAlternative.scala -- [ ] library/src/scala/annotation/internal/ProvisionalSuperClass.scala -- [ ] library/src/scala/annotation/internal/Repeated.scala -- [ ] library/src/scala/annotation/internal/RuntimeChecked.scala -- [ ] library/src/scala/annotation/internal/SourceFile.scala -- [ ] library/src/scala/annotation/internal/WithPureFuns.scala -- [ ] library/src/scala/annotation/internal/WitnessNames.scala -- [ ] library/src/scala/annotation/internal/preview.scala -- [ ] library/src/scala/annotation/internal/reachCapability.scala -- [ ] library/src/scala/annotation/internal/readOnlyCapability.scala -- [ ] library/src/scala/annotation/internal/requiresCapability.scala -- [ ] library/src/scala/annotation/internal/sharable.scala -- [ ] library/src/scala/annotation/internal/unshared.scala -- [ ] library/src/scala/annotation/into.scala -- [ ] library/src/scala/annotation/publicInBinary.scala -- [ ] library/src/scala/annotation/retains.scala -- [ ] library/src/scala/annotation/retainsByName.scala -- [ ] library/src/scala/annotation/static.scala -- [ ] library/src/scala/annotation/targetName.scala -- [ ] library/src/scala/annotation/threadUnsafe.scala -- [ ] library/src/scala/annotation/transparentTrait.scala +- [x] library/src/scala/annotation/MacroAnnotation.scala +- [x] library/src/scala/annotation/RefiningAnnotation.scala +- [x] library/src/scala/annotation/alpha.scala +- [x] library/src/scala/annotation/capability.scala +- [x] library/src/scala/annotation/constructorOnly.scala +- [x] library/src/scala/annotation/experimental.scala +- [x] library/src/scala/annotation/init.scala +- [x] library/src/scala/annotation/internal/$into.scala +- [x] library/src/scala/annotation/internal/Alias.scala +- [x] library/src/scala/annotation/internal/AnnotationDefault.scala +- [x] library/src/scala/annotation/internal/AssignedNonLocally.scala +- [x] library/src/scala/annotation/internal/Body.scala +- [x] library/src/scala/annotation/internal/CaptureChecked.scala +- [x] library/src/scala/annotation/internal/Child.scala +- [x] library/src/scala/annotation/internal/ContextResultCount.scala +- [x] library/src/scala/annotation/internal/ErasedParam.scala +- [x] library/src/scala/annotation/internal/InlineParam.scala +- [x] library/src/scala/annotation/internal/MappedAlternative.scala +- [x] library/src/scala/annotation/internal/ProvisionalSuperClass.scala +- [x] library/src/scala/annotation/internal/Repeated.scala +- [x] library/src/scala/annotation/internal/RuntimeChecked.scala +- [x] library/src/scala/annotation/internal/SourceFile.scala +- [x] library/src/scala/annotation/internal/WithPureFuns.scala +- [x] library/src/scala/annotation/internal/WitnessNames.scala +- [x] library/src/scala/annotation/internal/preview.scala +- [x] library/src/scala/annotation/internal/reachCapability.scala +- [x] library/src/scala/annotation/internal/readOnlyCapability.scala +- [x] library/src/scala/annotation/internal/requiresCapability.scala +- [x] library/src/scala/annotation/internal/sharable.scala +- [x] library/src/scala/annotation/internal/unshared.scala +- [x] library/src/scala/annotation/into.scala +- [x] library/src/scala/annotation/publicInBinary.scala +- [x] library/src/scala/annotation/retains.scala +- [x] library/src/scala/annotation/retainsByName.scala +- [x] library/src/scala/annotation/static.scala +- [x] library/src/scala/annotation/targetName.scala +- [x] library/src/scala/annotation/threadUnsafe.scala +- [x] library/src/scala/annotation/transparentTrait.scala - [ ] library/src/scala/annotation/unchecked/uncheckedCapabilityLeaks.scala -- [ ] library/src/scala/annotation/unchecked/uncheckedCaptures.scala -- [ ] library/src/scala/annotation/unroll.scala +- [x] library/src/scala/annotation/unchecked/uncheckedCaptures.scala +- [x] library/src/scala/annotation/unroll.scala - [x] library/src/scala/caps/package.scala - [x] library/src/scala/compiletime/ops/any.scala - [x] library/src/scala/compiletime/ops/boolean.scala diff --git a/library/src/scala/annotation/MacroAnnotation.scala b/library/src/scala/annotation/MacroAnnotation.scala index ffaa0cf88464..7f2bd56c56c1 100644 --- a/library/src/scala/annotation/MacroAnnotation.scala +++ b/library/src/scala/annotation/MacroAnnotation.scala @@ -2,6 +2,8 @@ package scala package annotation +import language.experimental.captureChecking + import scala.quoted.* /** Base trait for macro annotation implementation. diff --git a/library/src/scala/annotation/RefiningAnnotation.scala b/library/src/scala/annotation/RefiningAnnotation.scala index 65761d5234d4..6fb2960b9685 100644 --- a/library/src/scala/annotation/RefiningAnnotation.scala +++ b/library/src/scala/annotation/RefiningAnnotation.scala @@ -1,5 +1,7 @@ package scala.annotation +import language.experimental.captureChecking + /** A base trait for annotations that yield proper subtypes of the types they annotate. * Refining annotations are more "sticky" than normal ones. They are conceptually kept * around when normal refinements would also not be stripped away. diff --git a/library/src/scala/annotation/alpha.scala b/library/src/scala/annotation/alpha.scala index ac2a11c5b650..932713ce2031 100644 --- a/library/src/scala/annotation/alpha.scala +++ b/library/src/scala/annotation/alpha.scala @@ -1,5 +1,7 @@ package scala.annotation +import language.experimental.captureChecking + /** An annotation that defines an external name for a definition. * If an `alpha(extname)` annotation is given for a method or some other * definition, its implementation will use the name `extname` instead of diff --git a/library/src/scala/annotation/capability.scala b/library/src/scala/annotation/capability.scala index d3453e3c8168..63428b509b77 100644 --- a/library/src/scala/annotation/capability.scala +++ b/library/src/scala/annotation/capability.scala @@ -1,6 +1,8 @@ package scala.annotation import annotation.experimental +import language.experimental.captureChecking + /** Marks an annotated class as a capability. * If the annotation is present and -Ycc is set, any (possibly aliased * or refined) instance of the class type is implicitly augmented with diff --git a/library/src/scala/annotation/constructorOnly.scala b/library/src/scala/annotation/constructorOnly.scala index 8fefc3b012dd..4959b7c503b6 100644 --- a/library/src/scala/annotation/constructorOnly.scala +++ b/library/src/scala/annotation/constructorOnly.scala @@ -8,6 +8,8 @@ package scala.annotation +import language.experimental.captureChecking + import scala.annotation.meta.* /** An annotation that goes on parameters of classes or traits. It asserts diff --git a/library/src/scala/annotation/experimental.scala b/library/src/scala/annotation/experimental.scala index 634cfe12db7f..ee91a6408b4b 100644 --- a/library/src/scala/annotation/experimental.scala +++ b/library/src/scala/annotation/experimental.scala @@ -1,5 +1,7 @@ package scala.annotation +import language.experimental.captureChecking + /** An annotation that can be used to mark a definition as experimental. * * @see [[https://dotty.epfl.ch/docs/reference/other-new-features/experimental-defs]] diff --git a/library/src/scala/annotation/init.scala b/library/src/scala/annotation/init.scala index 7dea418664e6..c2b12041e1db 100644 --- a/library/src/scala/annotation/init.scala +++ b/library/src/scala/annotation/init.scala @@ -1,5 +1,7 @@ package scala.annotation +import language.experimental.captureChecking + /** Annotations to control the behavior of the compiler check for safe initialization of static obects. * * Programmers usually do not need to use any annotations. They are intended for complex initialization diff --git a/library/src/scala/annotation/internal/$into.scala b/library/src/scala/annotation/internal/$into.scala index bad0e399d389..565aad3f2aa7 100644 --- a/library/src/scala/annotation/internal/$into.scala +++ b/library/src/scala/annotation/internal/$into.scala @@ -1,4 +1,7 @@ package scala.annotation.internal + +import language.experimental.captureChecking + import annotation.experimental /** An internal annotation on (part of) a parameter type that serves as a marker where diff --git a/library/src/scala/annotation/internal/Alias.scala b/library/src/scala/annotation/internal/Alias.scala index 5c8f7d4b9ffa..3d3de9f27c00 100644 --- a/library/src/scala/annotation/internal/Alias.scala +++ b/library/src/scala/annotation/internal/Alias.scala @@ -1,5 +1,7 @@ package scala.annotation.internal +import language.experimental.captureChecking + import scala.annotation.Annotation /** An annotation to record a Scala2 pickled alias. diff --git a/library/src/scala/annotation/internal/AnnotationDefault.scala b/library/src/scala/annotation/internal/AnnotationDefault.scala index 5280d091c1ec..5ea16e60a76c 100644 --- a/library/src/scala/annotation/internal/AnnotationDefault.scala +++ b/library/src/scala/annotation/internal/AnnotationDefault.scala @@ -1,5 +1,7 @@ package scala.annotation.internal +import language.experimental.captureChecking + import scala.annotation.Annotation /** An annotation to tag Java annotation default values */ diff --git a/library/src/scala/annotation/internal/AssignedNonLocally.scala b/library/src/scala/annotation/internal/AssignedNonLocally.scala index 8095ba91cfee..075f2f4453c8 100644 --- a/library/src/scala/annotation/internal/AssignedNonLocally.scala +++ b/library/src/scala/annotation/internal/AssignedNonLocally.scala @@ -1,6 +1,8 @@ package scala.annotation package internal +import language.experimental.captureChecking + /** An annotation to indicate that a private `var` was assigned with a prefix * other than the `this` type of its owner. */ diff --git a/library/src/scala/annotation/internal/Body.scala b/library/src/scala/annotation/internal/Body.scala index b6aa0c0fb616..682c26388cdf 100644 --- a/library/src/scala/annotation/internal/Body.scala +++ b/library/src/scala/annotation/internal/Body.scala @@ -1,5 +1,7 @@ package scala.annotation.internal +import language.experimental.captureChecking + import scala.annotation.Annotation /** The class associated with a `BodyAnnotation`, which indicates diff --git a/library/src/scala/annotation/internal/CaptureChecked.scala b/library/src/scala/annotation/internal/CaptureChecked.scala index 0bc6d628a542..a41c6364d46d 100644 --- a/library/src/scala/annotation/internal/CaptureChecked.scala +++ b/library/src/scala/annotation/internal/CaptureChecked.scala @@ -1,6 +1,8 @@ package scala.annotation package internal +import language.experimental.captureChecking + /** A marker annotation on a toplevel class that indicates * that the class was typed with the captureChecking language import. */ diff --git a/library/src/scala/annotation/internal/Child.scala b/library/src/scala/annotation/internal/Child.scala index b0d380e2460d..a6ec1f13b699 100644 --- a/library/src/scala/annotation/internal/Child.scala +++ b/library/src/scala/annotation/internal/Child.scala @@ -1,6 +1,8 @@ package scala.annotation package internal +import language.experimental.captureChecking + /** An annotation to indicate a child class or object of the annotated class. * E.g. if we have * diff --git a/library/src/scala/annotation/internal/ContextResultCount.scala b/library/src/scala/annotation/internal/ContextResultCount.scala index ecaedb65bf4f..8469a1171cfc 100644 --- a/library/src/scala/annotation/internal/ContextResultCount.scala +++ b/library/src/scala/annotation/internal/ContextResultCount.scala @@ -1,6 +1,8 @@ package scala.annotation package internal +import language.experimental.captureChecking + /** An annotation that's automatically added for methods * that have one or more nested context closures as their right hand side. * The parameter `n` is an Int Literal that tells how many nested closures diff --git a/library/src/scala/annotation/internal/ErasedParam.scala b/library/src/scala/annotation/internal/ErasedParam.scala index a5ed192820c3..e1482292464a 100644 --- a/library/src/scala/annotation/internal/ErasedParam.scala +++ b/library/src/scala/annotation/internal/ErasedParam.scala @@ -1,5 +1,7 @@ package scala.annotation package internal +import language.experimental.captureChecking + /** An annotation produced by Namer to indicate an erased parameter */ final class ErasedParam() extends Annotation diff --git a/library/src/scala/annotation/internal/InlineParam.scala b/library/src/scala/annotation/internal/InlineParam.scala index 0b3649e89da9..a95fd8363eee 100644 --- a/library/src/scala/annotation/internal/InlineParam.scala +++ b/library/src/scala/annotation/internal/InlineParam.scala @@ -1,5 +1,7 @@ package scala.annotation.internal +import language.experimental.captureChecking + import scala.annotation.Annotation /** An annotation produced by Namer to indicate an inline parameter */ diff --git a/library/src/scala/annotation/internal/MappedAlternative.scala b/library/src/scala/annotation/internal/MappedAlternative.scala index 19bd84df633c..72a545a2898d 100644 --- a/library/src/scala/annotation/internal/MappedAlternative.scala +++ b/library/src/scala/annotation/internal/MappedAlternative.scala @@ -1,6 +1,8 @@ package scala.annotation package internal +import language.experimental.captureChecking + /** An annotation added by overloading resoluton to mapped symbols that * explore deeper into the types of the opverloaded alternatives. * Its tree is a TypeTree with two parameters which are both needed to diff --git a/library/src/scala/annotation/internal/ProvisionalSuperClass.scala b/library/src/scala/annotation/internal/ProvisionalSuperClass.scala index 147b7b087c5a..96b8d42c2240 100644 --- a/library/src/scala/annotation/internal/ProvisionalSuperClass.scala +++ b/library/src/scala/annotation/internal/ProvisionalSuperClass.scala @@ -1,6 +1,8 @@ package scala.annotation package internal +import language.experimental.captureChecking + /** An annotation to record a provisional super class */ class ProvisionalSuperClass extends StaticAnnotation diff --git a/library/src/scala/annotation/internal/Repeated.scala b/library/src/scala/annotation/internal/Repeated.scala index 75eb3bc25f1a..fd01f0512b67 100644 --- a/library/src/scala/annotation/internal/Repeated.scala +++ b/library/src/scala/annotation/internal/Repeated.scala @@ -1,5 +1,7 @@ package scala.annotation.internal +import language.experimental.captureChecking + import scala.annotation.Annotation /** An annotation produced by desugaring to indicate that a diff --git a/library/src/scala/annotation/internal/RuntimeChecked.scala b/library/src/scala/annotation/internal/RuntimeChecked.scala index ed83936dc473..6612b1a904fc 100644 --- a/library/src/scala/annotation/internal/RuntimeChecked.scala +++ b/library/src/scala/annotation/internal/RuntimeChecked.scala @@ -1,5 +1,7 @@ package scala.annotation.internal +import language.experimental.captureChecking + import scala.annotation.Annotation import scala.annotation.experimental diff --git a/library/src/scala/annotation/internal/SourceFile.scala b/library/src/scala/annotation/internal/SourceFile.scala index b203869cf383..16003869dcc7 100644 --- a/library/src/scala/annotation/internal/SourceFile.scala +++ b/library/src/scala/annotation/internal/SourceFile.scala @@ -1,5 +1,7 @@ package scala.annotation.internal +import language.experimental.captureChecking + import scala.annotation.Annotation /** An annotation to record a Scala2 pickled alias. diff --git a/library/src/scala/annotation/internal/WithPureFuns.scala b/library/src/scala/annotation/internal/WithPureFuns.scala index 979dd7c405cc..9b28959423e5 100644 --- a/library/src/scala/annotation/internal/WithPureFuns.scala +++ b/library/src/scala/annotation/internal/WithPureFuns.scala @@ -1,6 +1,8 @@ package scala.annotation package internal +import language.experimental.captureChecking + /** A marker annotation on a toplevel class that indicates * that the class was typed with the pureFunctions language import. */ diff --git a/library/src/scala/annotation/internal/WitnessNames.scala b/library/src/scala/annotation/internal/WitnessNames.scala index 3921c2083617..e2a17958f354 100644 --- a/library/src/scala/annotation/internal/WitnessNames.scala +++ b/library/src/scala/annotation/internal/WitnessNames.scala @@ -1,6 +1,8 @@ package scala.annotation package internal +import language.experimental.captureChecking + /** An annotation that is used for marking type definitions that should get * context bound companions. The scheme is as follows: * diff --git a/library/src/scala/annotation/internal/preview.scala b/library/src/scala/annotation/internal/preview.scala index a6e797d78e97..2bae60d0eee6 100644 --- a/library/src/scala/annotation/internal/preview.scala +++ b/library/src/scala/annotation/internal/preview.scala @@ -1,6 +1,7 @@ package scala.annotation package internal +import language.experimental.captureChecking /** An annotation that can be used to mark a definition as preview. * diff --git a/library/src/scala/annotation/internal/reachCapability.scala b/library/src/scala/annotation/internal/reachCapability.scala index 9f5e344adbe9..cddc19011129 100644 --- a/library/src/scala/annotation/internal/reachCapability.scala +++ b/library/src/scala/annotation/internal/reachCapability.scala @@ -1,6 +1,8 @@ package scala.annotation package internal +import language.experimental.captureChecking + /** An annotation that marks a capture ref as a reach capability. * `x*` is encoded as `x.type @reachCapability` */ diff --git a/library/src/scala/annotation/internal/readOnlyCapability.scala b/library/src/scala/annotation/internal/readOnlyCapability.scala index 8e939aea6bb9..516543dba053 100644 --- a/library/src/scala/annotation/internal/readOnlyCapability.scala +++ b/library/src/scala/annotation/internal/readOnlyCapability.scala @@ -1,6 +1,8 @@ package scala.annotation package internal +import language.experimental.captureChecking + /** An annotation that marks a capture ref as a read-only capability. * `x.rd` is encoded as `x.type @readOnlyCapability` */ diff --git a/library/src/scala/annotation/internal/requiresCapability.scala b/library/src/scala/annotation/internal/requiresCapability.scala index 56fca22d2982..94653a8b0890 100644 --- a/library/src/scala/annotation/internal/requiresCapability.scala +++ b/library/src/scala/annotation/internal/requiresCapability.scala @@ -1,6 +1,8 @@ package scala.annotation.internal import annotation.StaticAnnotation +import language.experimental.captureChecking + /** An annotation to record a required capaility in the type of a throws */ class requiresCapability(capability: Any) extends StaticAnnotation diff --git a/library/src/scala/annotation/internal/sharable.scala b/library/src/scala/annotation/internal/sharable.scala index e2d6dcc61beb..862c57a383a3 100644 --- a/library/src/scala/annotation/internal/sharable.scala +++ b/library/src/scala/annotation/internal/sharable.scala @@ -1,5 +1,7 @@ package scala.annotation.internal +import language.experimental.captureChecking + import scala.annotation.Annotation /** An annotation indicating to `-Ycheck:reentrant` that a class or val can be safely shared. diff --git a/library/src/scala/annotation/internal/unshared.scala b/library/src/scala/annotation/internal/unshared.scala index 89796eba09e3..052e57a18454 100644 --- a/library/src/scala/annotation/internal/unshared.scala +++ b/library/src/scala/annotation/internal/unshared.scala @@ -1,5 +1,7 @@ package scala.annotation.internal +import language.experimental.captureChecking + import scala.annotation.Annotation /** An annotation indicating to `-Ycheck:reentrant` that an object will not be accessed from multiple threads. diff --git a/library/src/scala/annotation/publicInBinary.scala b/library/src/scala/annotation/publicInBinary.scala index a517f085dc7a..133e7f8d06b5 100644 --- a/library/src/scala/annotation/publicInBinary.scala +++ b/library/src/scala/annotation/publicInBinary.scala @@ -1,5 +1,7 @@ package scala.annotation +import language.experimental.captureChecking + /** A binary API is a definition that is annotated with `@publicInBinary`. * This annotation can be placed on `def`, `val`, `lazy val`, `var`, class constructors, `object`, and `given` definitions. * A binary API will be publicly available in the bytecode. Tools like TASTy MiMa will take this into account to check diff --git a/library/src/scala/annotation/retains.scala b/library/src/scala/annotation/retains.scala index 05896b117796..f526a17c053e 100644 --- a/library/src/scala/annotation/retains.scala +++ b/library/src/scala/annotation/retains.scala @@ -1,5 +1,7 @@ package scala.annotation +import language.experimental.captureChecking + /** An annotation that indicates capture of a set of references under capture checking. * * T @retains[x.type | y.type | z.type] diff --git a/library/src/scala/annotation/retainsByName.scala b/library/src/scala/annotation/retainsByName.scala index acc8ec664af3..b01f890f86b9 100644 --- a/library/src/scala/annotation/retainsByName.scala +++ b/library/src/scala/annotation/retainsByName.scala @@ -1,5 +1,7 @@ package scala.annotation +import language.experimental.captureChecking + /** An annotation that indicates capture of an enclosing by-name type */ @experimental class retainsByName[Elems] extends annotation.StaticAnnotation diff --git a/library/src/scala/annotation/static.scala b/library/src/scala/annotation/static.scala index 7cee5fc160d5..dc40ab9f3ac2 100644 --- a/library/src/scala/annotation/static.scala +++ b/library/src/scala/annotation/static.scala @@ -1,5 +1,7 @@ package scala.annotation +import language.experimental.captureChecking + import scala.annotation.meta.* /** https://github.com/scala/scala.github.com/pull/491 */ diff --git a/library/src/scala/annotation/targetName.scala b/library/src/scala/annotation/targetName.scala index 56e1361c73d7..17945fa86fb7 100644 --- a/library/src/scala/annotation/targetName.scala +++ b/library/src/scala/annotation/targetName.scala @@ -1,5 +1,7 @@ package scala.annotation +import language.experimental.captureChecking + /** An annotation that defines an external name for a definition. * If an `targetName(extname)` annotation is given for a method or some other * definition, its implementation will use the name `extname` instead of diff --git a/library/src/scala/annotation/threadUnsafe.scala b/library/src/scala/annotation/threadUnsafe.scala index 36fecec941c2..dd87e74f3048 100644 --- a/library/src/scala/annotation/threadUnsafe.scala +++ b/library/src/scala/annotation/threadUnsafe.scala @@ -1,5 +1,7 @@ package scala.annotation +import language.experimental.captureChecking + /** This annotation can only be used on a field which defines a lazy val. * When this annotation is used, the initialization of the lazy val will use a * faster mechanism which is not thread-safe. diff --git a/library/src/scala/annotation/transparentTrait.scala b/library/src/scala/annotation/transparentTrait.scala index ae6cb5bb1188..b82234708881 100644 --- a/library/src/scala/annotation/transparentTrait.scala +++ b/library/src/scala/annotation/transparentTrait.scala @@ -1,5 +1,7 @@ package scala.annotation +import language.experimental.captureChecking + /** An annotation that can be used from Scala 2 to mark a trait as transparent. * Scala 3 code would use the modifier `transparent` instead. Transparent traits * are not inferred when combined with other types in an intersection. diff --git a/library/src/scala/annotation/unchecked/uncheckedCaptures.scala b/library/src/scala/annotation/unchecked/uncheckedCaptures.scala index 477ac6d742f7..e494cef28a0e 100644 --- a/library/src/scala/annotation/unchecked/uncheckedCaptures.scala +++ b/library/src/scala/annotation/unchecked/uncheckedCaptures.scala @@ -1,6 +1,8 @@ package scala.annotation package unchecked +import language.experimental.captureChecking + /** An annotation for mutable variables that are allowed to capture * the root capability `cap`. Allowing this is not capture safe since * it can cause leakage of capabilities from local scopes by assigning diff --git a/library/src/scala/annotation/unroll.scala b/library/src/scala/annotation/unroll.scala index c37b7903d605..dcc279f93798 100644 --- a/library/src/scala/annotation/unroll.scala +++ b/library/src/scala/annotation/unroll.scala @@ -1,5 +1,7 @@ package scala.annotation +import language.experimental.captureChecking + @experimental("under review as part of SIP-61") /**The `@unroll` annotation is reserved for parameters of classes and methods. * From 618ba9c5438a58feeade9f2732abac8502e2dfae Mon Sep 17 00:00:00 2001 From: Natsu Kagami Date: Thu, 10 Apr 2025 21:06:04 +0200 Subject: [PATCH 20/32] Attempt to capture-check quotes --- TODO.md | 28 +++++++++---------- library/src/scala/quoted/Expr.scala | 2 ++ library/src/scala/quoted/ExprMap.scala | 2 ++ library/src/scala/quoted/Exprs.scala | 2 ++ library/src/scala/quoted/FromExpr.scala | 2 ++ library/src/scala/quoted/Quotes.scala | 2 ++ library/src/scala/quoted/ToExpr.scala | 2 ++ library/src/scala/quoted/Type.scala | 2 ++ library/src/scala/quoted/Varargs.scala | 2 ++ library/src/scala/quoted/runtime/Expr.scala | 2 ++ .../src/scala/quoted/runtime/Patterns.scala | 2 ++ .../scala/quoted/runtime/QuoteMatching.scala | 2 ++ .../scala/quoted/runtime/QuoteUnpickler.scala | 2 ++ .../scala/quoted/runtime/SplicedType.scala | 2 ++ .../quoted/runtime/StopMacroExpansion.scala | 2 ++ 15 files changed, 42 insertions(+), 14 deletions(-) diff --git a/TODO.md b/TODO.md index 568b81335d94..eeeefbbf57f8 100644 --- a/TODO.md +++ b/TODO.md @@ -62,20 +62,20 @@ - [x] library/src/scala/compiletime/testing/ErrorKind.scala - [x] library/src/scala/compiletime/testing/package.scala - [x] library/src/scala/main.scala -- [ ] library/src/scala/quoted/Expr.scala -- [ ] library/src/scala/quoted/ExprMap.scala -- [ ] library/src/scala/quoted/Exprs.scala -- [ ] library/src/scala/quoted/FromExpr.scala -- [ ] library/src/scala/quoted/Quotes.scala -- [ ] library/src/scala/quoted/ToExpr.scala -- [ ] library/src/scala/quoted/Type.scala -- [ ] library/src/scala/quoted/Varargs.scala -- [ ] library/src/scala/quoted/runtime/Expr.scala -- [ ] library/src/scala/quoted/runtime/Patterns.scala -- [ ] library/src/scala/quoted/runtime/QuoteMatching.scala -- [ ] library/src/scala/quoted/runtime/QuoteUnpickler.scala -- [ ] library/src/scala/quoted/runtime/SplicedType.scala -- [ ] library/src/scala/quoted/runtime/StopMacroExpansion.scala +- [x] library/src/scala/quoted/Expr.scala +- [x] library/src/scala/quoted/ExprMap.scala +- [x] library/src/scala/quoted/Exprs.scala +- [x] library/src/scala/quoted/FromExpr.scala +- [x] library/src/scala/quoted/Quotes.scala +- [x] library/src/scala/quoted/ToExpr.scala +- [x] library/src/scala/quoted/Type.scala +- [x] library/src/scala/quoted/Varargs.scala +- [x] library/src/scala/quoted/runtime/Expr.scala +- [x] library/src/scala/quoted/runtime/Patterns.scala +- [x] library/src/scala/quoted/runtime/QuoteMatching.scala +- [x] library/src/scala/quoted/runtime/QuoteUnpickler.scala +- [x] library/src/scala/quoted/runtime/SplicedType.scala +- [x] library/src/scala/quoted/runtime/StopMacroExpansion.scala - [x] library/src/scala/reflect/Enum.scala - [x] library/src/scala/reflect/Selectable.scala - [x] library/src/scala/reflect/TypeTest.scala diff --git a/library/src/scala/quoted/Expr.scala b/library/src/scala/quoted/Expr.scala index bfb26023e2c8..9d297ed27d0e 100644 --- a/library/src/scala/quoted/Expr.scala +++ b/library/src/scala/quoted/Expr.scala @@ -1,5 +1,7 @@ package scala.quoted +import language.experimental.captureChecking + /** Quoted expression of type `T`. * * `Expr` has extension methods that are defined in `scala.quoted.Quotes`. diff --git a/library/src/scala/quoted/ExprMap.scala b/library/src/scala/quoted/ExprMap.scala index fbe5dee2b342..8aa513eec4ac 100644 --- a/library/src/scala/quoted/ExprMap.scala +++ b/library/src/scala/quoted/ExprMap.scala @@ -1,5 +1,7 @@ package scala.quoted +import language.experimental.captureChecking + trait ExprMap: /** Map an expression `e` with a type `T` */ diff --git a/library/src/scala/quoted/Exprs.scala b/library/src/scala/quoted/Exprs.scala index 48b0200236bf..2cc2e2944761 100644 --- a/library/src/scala/quoted/Exprs.scala +++ b/library/src/scala/quoted/Exprs.scala @@ -1,5 +1,7 @@ package scala.quoted +import language.experimental.captureChecking + object Exprs: /** Matches literal sequence of literal constant value expressions and return a sequence of values. diff --git a/library/src/scala/quoted/FromExpr.scala b/library/src/scala/quoted/FromExpr.scala index bcd10e4f09ed..2d9e3ebc5ab6 100644 --- a/library/src/scala/quoted/FromExpr.scala +++ b/library/src/scala/quoted/FromExpr.scala @@ -1,5 +1,7 @@ package scala.quoted +import language.experimental.captureChecking + /** A type class for types that can convert a `quoted.Expr[T]` to a `T`. * * - Converts expression containing literal values to their values: diff --git a/library/src/scala/quoted/Quotes.scala b/library/src/scala/quoted/Quotes.scala index b4ea133e47eb..61902c1842f0 100644 --- a/library/src/scala/quoted/Quotes.scala +++ b/library/src/scala/quoted/Quotes.scala @@ -1,5 +1,7 @@ package scala.quoted +import language.experimental.captureChecking + import scala.annotation.{experimental, implicitNotFound, unused} import scala.reflect.TypeTest diff --git a/library/src/scala/quoted/ToExpr.scala b/library/src/scala/quoted/ToExpr.scala index 6c167c353d87..fbe590c660de 100644 --- a/library/src/scala/quoted/ToExpr.scala +++ b/library/src/scala/quoted/ToExpr.scala @@ -1,5 +1,7 @@ package scala.quoted +import language.experimental.captureChecking + import scala.reflect.ClassTag /** A type class for types that can convert a value of `T` into `quoted.Expr[T]` diff --git a/library/src/scala/quoted/Type.scala b/library/src/scala/quoted/Type.scala index b035bdd6e52f..2d3a0b4fcabb 100644 --- a/library/src/scala/quoted/Type.scala +++ b/library/src/scala/quoted/Type.scala @@ -1,5 +1,7 @@ package scala.quoted +import language.experimental.captureChecking + import scala.annotation.{compileTimeOnly, experimental} /** Type (or type constructor) `T` needed contextually when using `T` in a quoted expression `'{... T ...}` */ diff --git a/library/src/scala/quoted/Varargs.scala b/library/src/scala/quoted/Varargs.scala index 61937fc8fecb..3ffd0b64120d 100644 --- a/library/src/scala/quoted/Varargs.scala +++ b/library/src/scala/quoted/Varargs.scala @@ -1,5 +1,7 @@ package scala.quoted +import language.experimental.captureChecking + /** Expression representation of literal sequence of expressions. * * `Varargs` can be used to create the an expression `args` that will be used as varargs `'{ f($args: _*) }` diff --git a/library/src/scala/quoted/runtime/Expr.scala b/library/src/scala/quoted/runtime/Expr.scala index b95f225c13b3..e3a54a64a06a 100644 --- a/library/src/scala/quoted/runtime/Expr.scala +++ b/library/src/scala/quoted/runtime/Expr.scala @@ -1,6 +1,8 @@ package scala.quoted package runtime +import language.experimental.captureChecking + import scala.annotation.{Annotation, compileTimeOnly} @compileTimeOnly("Illegal reference to `scala.quoted.runtime.Expr`") diff --git a/library/src/scala/quoted/runtime/Patterns.scala b/library/src/scala/quoted/runtime/Patterns.scala index f8e172d30f62..cdbbb224424e 100644 --- a/library/src/scala/quoted/runtime/Patterns.scala +++ b/library/src/scala/quoted/runtime/Patterns.scala @@ -1,5 +1,7 @@ package scala.quoted.runtime +import language.experimental.captureChecking + import scala.annotation.{Annotation, compileTimeOnly} import scala.annotation.experimental diff --git a/library/src/scala/quoted/runtime/QuoteMatching.scala b/library/src/scala/quoted/runtime/QuoteMatching.scala index c95ffe87b5dc..90205266d01a 100644 --- a/library/src/scala/quoted/runtime/QuoteMatching.scala +++ b/library/src/scala/quoted/runtime/QuoteMatching.scala @@ -1,5 +1,7 @@ package scala.quoted.runtime +import language.experimental.captureChecking + import scala.quoted.{Expr, Type} /** Part of the Quotes interface that needs to be implemented by the compiler but is not visible to users */ diff --git a/library/src/scala/quoted/runtime/QuoteUnpickler.scala b/library/src/scala/quoted/runtime/QuoteUnpickler.scala index 63e62658cbb4..aa83ceea2e28 100644 --- a/library/src/scala/quoted/runtime/QuoteUnpickler.scala +++ b/library/src/scala/quoted/runtime/QuoteUnpickler.scala @@ -1,5 +1,7 @@ package scala.quoted.runtime +import language.experimental.captureChecking + import scala.quoted.{Quotes, Expr, Type} /** Part of the Quotes interface that needs to be implemented by the compiler but is not visible to users */ diff --git a/library/src/scala/quoted/runtime/SplicedType.scala b/library/src/scala/quoted/runtime/SplicedType.scala index 1a7b74740d33..0a4242dffa6c 100644 --- a/library/src/scala/quoted/runtime/SplicedType.scala +++ b/library/src/scala/quoted/runtime/SplicedType.scala @@ -1,5 +1,7 @@ package scala.quoted.runtime +import language.experimental.captureChecking + import scala.annotation.{Annotation, compileTimeOnly} /** Artifact of pickled type splices diff --git a/library/src/scala/quoted/runtime/StopMacroExpansion.scala b/library/src/scala/quoted/runtime/StopMacroExpansion.scala index b4d570167621..678c8f93ee66 100644 --- a/library/src/scala/quoted/runtime/StopMacroExpansion.scala +++ b/library/src/scala/quoted/runtime/StopMacroExpansion.scala @@ -1,5 +1,7 @@ package scala.quoted.runtime +import language.experimental.captureChecking + /** Throwable used to abort the expansion of a macro after an error was reported */ class StopMacroExpansion extends Throwable: From 2f6a394f65f24427e6eac28d37ca9b107b342c53 Mon Sep 17 00:00:00 2001 From: Natsu Kagami Date: Mon, 14 Apr 2025 12:42:50 +0200 Subject: [PATCH 21/32] Track sun.misc.Unsafe in LazyVal implementation --- library/src/scala/runtime/LazyVals.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/src/scala/runtime/LazyVals.scala b/library/src/scala/runtime/LazyVals.scala index a924b5dd2a4d..a92712c71a05 100644 --- a/library/src/scala/runtime/LazyVals.scala +++ b/library/src/scala/runtime/LazyVals.scala @@ -10,7 +10,7 @@ import scala.annotation.* */ object LazyVals { @nowarn - private val unsafe: sun.misc.Unsafe = { + private val unsafe: sun.misc.Unsafe^ = { // do not let unsafe leak def throwInitializationException() = throw new ExceptionInInitializerError( new IllegalStateException("Can't find instance of sun.misc.Unsafe") From 402ac89e205de262e75fa17242b532ad1e8100aa Mon Sep 17 00:00:00 2001 From: Natsu Kagami Date: Thu, 31 Jul 2025 18:17:46 +0200 Subject: [PATCH 22/32] Require Conversion to be pure --- .../src/dotty/tools/dotc/core/Definitions.scala | 1 + library/src/scala/Conversion.scala | 14 +++++++------- 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/core/Definitions.scala b/compiler/src/dotty/tools/dotc/core/Definitions.scala index 5102f7021825..a0a937dd803b 100644 --- a/compiler/src/dotty/tools/dotc/core/Definitions.scala +++ b/compiler/src/dotty/tools/dotc/core/Definitions.scala @@ -1149,6 +1149,7 @@ class Definitions { "reactor.util.annotation.NonNullApi" :: "io.reactivex.annotations.NonNull" :: Nil) + // convenient one-parameter method types def methOfAny(tp: Type): MethodType = MethodType(List(AnyType), tp) def methOfAnyVal(tp: Type): MethodType = MethodType(List(AnyValType), tp) diff --git a/library/src/scala/Conversion.scala b/library/src/scala/Conversion.scala index 41c6cf0c0307..282566063b6e 100644 --- a/library/src/scala/Conversion.scala +++ b/library/src/scala/Conversion.scala @@ -25,12 +25,13 @@ import language.experimental.captureChecking */ @java.lang.FunctionalInterface abstract class Conversion[-T, +U] extends Function1[T, U]: - /** Convert value `x` of type `T` to type `U` */ - def apply(x: T): U + self => + /** Convert value `x` of type `T` to type `U` */ + def apply(x: T): U - extension (x: T) - /** `x.convert` converts a value `x` of type `T` to type `U` */ - def convert = this(x) + extension (x: T) + /** `x.convert` converts a value `x` of type `T` to type `U` */ + def convert = this(x) object Conversion: import annotation.experimental @@ -46,5 +47,4 @@ object Conversion: /** Unwrap an `into` */ extension [T](x: into[T]) @experimental def underlying: T = x - -end Conversion \ No newline at end of file +end Conversion From ccda5a1f3418622a6c2212a2693c81ee95d13ca3 Mon Sep 17 00:00:00 2001 From: Natsu Kagami Date: Thu, 7 Aug 2025 22:25:23 +0200 Subject: [PATCH 23/32] Remove CC from tuples for now, Map is not compiling Relies on #23695 to land on next base version --- library/src/scala/NamedTuple.scala | 2 +- library/src/scala/Tuple.scala | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/library/src/scala/NamedTuple.scala b/library/src/scala/NamedTuple.scala index aee1695750cd..f88f7760365b 100644 --- a/library/src/scala/NamedTuple.scala +++ b/library/src/scala/NamedTuple.scala @@ -89,7 +89,7 @@ object NamedTuple: /** The type of the named tuple `X` mapped with the type-level function `F`. * If `X = (n1 : T1, ..., ni : Ti)` then `Map[X, F] = `(n1 : F[T1], ..., ni : F[Ti])`. */ - type Map[X <: AnyNamedTuple, F[_]] = + type Map[X <: AnyNamedTuple, F[_ <: Tuple.Union[DropNames[X]]]] = NamedTuple[Names[X], Tuple.Map[DropNames[X], F]] /** A named tuple with the elements of tuple `X` in reversed order */ diff --git a/library/src/scala/Tuple.scala b/library/src/scala/Tuple.scala index 1337784cc9e2..2f865f9037ba 100644 --- a/library/src/scala/Tuple.scala +++ b/library/src/scala/Tuple.scala @@ -1,6 +1,6 @@ package scala -import language.experimental.captureChecking +// import language.experimental.captureChecking import annotation.showAsInfix import compiletime.* import compiletime.ops.int.* @@ -175,13 +175,13 @@ object Tuple { case h *: t => F[h, Fold[t, Z, F]] /** Converts a tuple `(T1, ..., Tn)` to `(F[T1], ..., F[Tn])` */ - type Map[Tup <: Tuple, F[_]] <: Tuple = Tup match { + type Map[Tup <: Tuple, F <: [_ <: Union[Tup]] =>> Any] <: Tuple = Tup match { case EmptyTuple => EmptyTuple case h *: t => F[h] *: Map[t, F] } /** Converts a tuple `(T1, ..., Tn)` to a flattened `(..F[T1], ..., ..F[Tn])` */ - type FlatMap[Tup <: Tuple, F[_] <: Tuple] <: Tuple = Tup match { + type FlatMap[Tup <: Tuple, F[_ <: Union[Tup]] <: Tuple] <: Tuple = Tup match { case EmptyTuple => EmptyTuple case h *: t => Concat[F[h], FlatMap[t, F]] } @@ -197,7 +197,7 @@ object Tuple { * ``` * @syntax markdown */ - type Filter[Tup <: Tuple, P[_] <: Boolean] <: Tuple = Tup match { + type Filter[Tup <: Tuple, P[_ <: Union[Tup]] <: Boolean] <: Tuple = Tup match { case EmptyTuple => EmptyTuple case h *: t => P[h] match { case true => h *: Filter[t, P] From d3015152dc783fb99e8aa5c30728cd0dcba5cc17 Mon Sep 17 00:00:00 2001 From: Natsu Kagami Date: Fri, 8 Aug 2025 17:31:58 +0200 Subject: [PATCH 24/32] Make sure that DropBreaks catch also constant folded statements --- .../src/dotty/tools/dotc/transform/DropBreaks.scala | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/compiler/src/dotty/tools/dotc/transform/DropBreaks.scala b/compiler/src/dotty/tools/dotc/transform/DropBreaks.scala index b1c0080705ad..d5f555763bb4 100644 --- a/compiler/src/dotty/tools/dotc/transform/DropBreaks.scala +++ b/compiler/src/dotty/tools/dotc/transform/DropBreaks.scala @@ -27,6 +27,8 @@ object DropBreaks: /** The number of other references to associated label */ var otherRefs: Int = 0 + override def toString() = s"LabelUsage($goto, $enclMeth, returnRefs = $returnRefs, otherRefs = $otherRefs)" + private val LabelUsages = new Property.Key[Map[Symbol, LabelUsage]] private val ShadowedLabels = new Property.Key[Set[Symbol]] @@ -70,6 +72,15 @@ class DropBreaks extends MiniPhase: && throww.symbol == defn.throwMethod && ex.symbol == ex2.symbol && ex.symbol == ex3.symbol => Some((ex.symbol, lbl.symbol)) + case If( + Apply(Select(ex: Ident, isSameLabelAs), (lbl @ Ident(local)) :: Nil), + Literal(_), // in the case where the value is constant folded + Apply(throww, (ex3: Ident) :: Nil)) + if isSameLabelAs == nme.isSameLabelAs && local == nme.local + && throww.symbol == defn.throwMethod + && ex.symbol == ex3.symbol + && expr.tpe.isSingleton => + Some((ex.symbol, lbl.symbol)) case _ => None end GuardedThrow From 3b957f213c778b6ba591f9c5f87315abae78bf97 Mon Sep 17 00:00:00 2001 From: Natsu Kagami Date: Mon, 11 Aug 2025 02:12:27 +0200 Subject: [PATCH 25/32] Update test outputs --- .../backend/jvm/LabelBytecodeTests.scala | 2 +- tests/neg-custom-args/captures/boundary.check | 59 +++++++++++++------ tests/neg-custom-args/captures/boundary.scala | 11 ++-- tests/neg-macros/i19842-a.check | 2 +- tests/neg-macros/i19842-b.check | 2 +- tests/neg-macros/i23008.check | 4 +- tests/run/assert-stack.check | 4 +- 7 files changed, 52 insertions(+), 32 deletions(-) diff --git a/compiler/test/dotty/tools/backend/jvm/LabelBytecodeTests.scala b/compiler/test/dotty/tools/backend/jvm/LabelBytecodeTests.scala index aea567b87f91..6a420e2bb56e 100644 --- a/compiler/test/dotty/tools/backend/jvm/LabelBytecodeTests.scala +++ b/compiler/test/dotty/tools/backend/jvm/LabelBytecodeTests.scala @@ -21,7 +21,7 @@ class LabelBytecodeTests extends DottyBytecodeTest { """val local = boundary.Label[Long]() |try break(5L)(using local) |catch case ex: boundary.Break[Long] @unchecked => - | if ex.label eq local then ex.value + | if ex.isSameLabelAs(local) then ex.value | else throw ex """.stripMargin, "Long", diff --git a/tests/neg-custom-args/captures/boundary.check b/tests/neg-custom-args/captures/boundary.check index 4b51012191ed..a795f131998a 100644 --- a/tests/neg-custom-args/captures/boundary.check +++ b/tests/neg-custom-args/captures/boundary.check @@ -1,26 +1,47 @@ --- [E007] Type Mismatch Error: tests/neg-custom-args/captures/boundary.scala:8:31 -------------------------------------- -8 | boundary.break(l2)(using l1) // error - | ^^ - | Found: (local : scala.util.boundary.Label[scala.util.boundary.Label[Unit]]^) - | Required: scala.util.boundary.Label[box scala.util.boundary.Label[Unit]^{local²}]^ - | - | where: local is a value locally defined in object test - | local² is a value locally defined in object test - | - | longer explanation available when compiling with `-explain` --- [E007] Type Mismatch Error: tests/neg-custom-args/captures/boundary.scala:6:32 -------------------------------------- - 6 | boundary[boundary.Label[Unit]]: l1 ?=> // error +-- [E007] Type Mismatch Error: tests/neg-custom-args/captures/boundary.scala:5:4 --------------------------------------- + 4 | boundary[AnyRef^]: + 5 | l1 ?=> // error // error | ^ - | Found: scala.util.boundary.Break[scala.util.boundary.Label[Unit]] @unchecked - | Required: scala.util.boundary.Break[box scala.util.boundary.Label[Unit]^] @unchecked - 7 | boundary[Unit]: l2 ?=> - 8 | boundary.break(l2)(using l1) // error - 9 | ??? + |Found: scala.util.boundary.Label[Object^?]^{cap.rd} + |Required: scala.util.boundary.Label[Object^]^² + | + |where: ^ refers to the universal root capability + | ^² refers to a fresh root capability classified as Control in the type of value local + | cap is a fresh root capability classified as Control created in value local when constructing Capability instance scala.util.boundary.Label[Object^?] + | + |Note that capability cap + |cannot be included in outer capture set ?. + 6 | boundary[Unit]: l2 ?=> + 7 | boundary.break(l2)(using l1) + 8 | ??? + |-------------------------------------------------------------------------------------------------------------------- + |Inline stack trace + |- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + |This location contains code that was inlined from boundary.scala:70 +70 | val local = Label[T]() + | ^^^^^^^^^^ + -------------------------------------------------------------------------------------------------------------------- + | + | longer explanation available when compiling with `-explain` +-- [E007] Type Mismatch Error: tests/neg-custom-args/captures/boundary.scala:5:4 --------------------------------------- + 4 | boundary[AnyRef^]: + 5 | l1 ?=> // error // error + | ^ + | Found: scala.util.boundary.Break[AnyRef^] @unchecked + | Required: scala.util.boundary.Break[Object^²] @unchecked + | + | where: ^ refers to the universal root capability + | ^² refers to a fresh root capability created in package + | + | Note that capability cap is not included in capture set {cap}. + 6 | boundary[Unit]: l2 ?=> + 7 | boundary.break(l2)(using l1) + 8 | ??? |-------------------------------------------------------------------------------------------------------------------- |Inline stack trace |- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - |This location contains code that was inlined from boundary.scala:73 -73 | catch case ex: Break[T] @unchecked => + |This location contains code that was inlined from boundary.scala:72 +72 | catch case ex: Break[T] @unchecked => | ^ -------------------------------------------------------------------------------------------------------------------- | diff --git a/tests/neg-custom-args/captures/boundary.scala b/tests/neg-custom-args/captures/boundary.scala index 4f2a994d392e..9792a0e49fa3 100644 --- a/tests/neg-custom-args/captures/boundary.scala +++ b/tests/neg-custom-args/captures/boundary.scala @@ -1,9 +1,8 @@ -import language.experimental.captureChecking - import scala.util.boundary object test: - boundary[boundary.Label[Unit]]: l1 ?=> // error - boundary[Unit]: l2 ?=> - boundary.break(l2)(using l1) // error - ??? + boundary[AnyRef^]: + l1 ?=> // error // error + boundary[Unit]: l2 ?=> + boundary.break(l2)(using l1) + ??? diff --git a/tests/neg-macros/i19842-a.check b/tests/neg-macros/i19842-a.check index 4d92739e00ff..33588b7278c2 100644 --- a/tests/neg-macros/i19842-a.check +++ b/tests/neg-macros/i19842-a.check @@ -7,7 +7,7 @@ |Parents in symbol: [class Object, trait Serializer] |Parents in tree: [trait Serializer] | - | at scala.runtime.Scala3RunTime$.assertFailed(Scala3RunTime.scala:8) + | at scala.runtime.Scala3RunTime$.assertFailed(Scala3RunTime.scala:10) | at dotty.tools.dotc.transform.TreeChecker$.checkParents(TreeChecker.scala:210) | at scala.quoted.runtime.impl.QuotesImpl$reflect$ClassDef$.module(QuotesImpl.scala:286) | at scala.quoted.runtime.impl.QuotesImpl$reflect$ClassDef$.module(QuotesImpl.scala:285) diff --git a/tests/neg-macros/i19842-b.check b/tests/neg-macros/i19842-b.check index 5a2fe6f39d48..29500e10fb25 100644 --- a/tests/neg-macros/i19842-b.check +++ b/tests/neg-macros/i19842-b.check @@ -7,7 +7,7 @@ |Parents in symbol: [class Object, trait Serializer] |Parents in tree: [class Object, trait Serializer, trait Foo] | - | at scala.runtime.Scala3RunTime$.assertFailed(Scala3RunTime.scala:8) + | at scala.runtime.Scala3RunTime$.assertFailed(Scala3RunTime.scala:10) | at dotty.tools.dotc.transform.TreeChecker$.checkParents(TreeChecker.scala:210) | at scala.quoted.runtime.impl.QuotesImpl$reflect$ClassDef$.module(QuotesImpl.scala:286) | at scala.quoted.runtime.impl.QuotesImpl$reflect$ClassDef$.module(QuotesImpl.scala:285) diff --git a/tests/neg-macros/i23008.check b/tests/neg-macros/i23008.check index 5193fb0ad7c4..c44f7cccb52a 100644 --- a/tests/neg-macros/i23008.check +++ b/tests/neg-macros/i23008.check @@ -7,9 +7,9 @@ | at scala.Predef$.require(Predef.scala:337) | at scala.quoted.runtime.impl.QuotesImpl$reflect$StringConstant$.apply(QuotesImpl.scala:2540) | at scala.quoted.runtime.impl.QuotesImpl$reflect$StringConstant$.apply(QuotesImpl.scala:2539) + | at scala.quoted.ToExpr$StringToExpr.apply(ToExpr.scala:82) | at scala.quoted.ToExpr$StringToExpr.apply(ToExpr.scala:80) - | at scala.quoted.ToExpr$StringToExpr.apply(ToExpr.scala:78) - | at scala.quoted.Expr$.apply(Expr.scala:70) + | at scala.quoted.Expr$.apply(Expr.scala:72) | at Macros$.buildStringCode(Macro_1.scala:9) | |--------------------------------------------------------------------------------------------------------------------- diff --git a/tests/run/assert-stack.check b/tests/run/assert-stack.check index c2c97450fd57..aec36d2a4f6e 100644 --- a/tests/run/assert-stack.check +++ b/tests/run/assert-stack.check @@ -1,6 +1,6 @@ -scala.runtime.Scala3RunTime$.assertFailed(Scala3RunTime.scala:8) +scala.runtime.Scala3RunTime$.assertFailed(Scala3RunTime.scala:10) Test$.main(assert-stack.scala:7) -scala.runtime.Scala3RunTime$.assertFailed(Scala3RunTime.scala:11) +scala.runtime.Scala3RunTime$.assertFailed(Scala3RunTime.scala:13) Test$.main(assert-stack.scala:12) From 4f4aa5b627897d15121cad2b7e2386fbae939d17 Mon Sep 17 00:00:00 2001 From: Natsu Kagami Date: Fri, 15 Aug 2025 18:00:20 +0200 Subject: [PATCH 26/32] Remove TODO --- TODO.md | 103 --------------------------------------------------- mk_todo.fish | 6 --- 2 files changed, 109 deletions(-) delete mode 100644 TODO.md delete mode 100755 mk_todo.fish diff --git a/TODO.md b/TODO.md deleted file mode 100644 index eeeefbbf57f8..000000000000 --- a/TODO.md +++ /dev/null @@ -1,103 +0,0 @@ -- [x] library/src/scala/CanEqual.scala -- [x] library/src/scala/CanThrow.scala -- [x] library/src/scala/Conversion.scala -- [x] library/src/scala/IArray.scala -- [x] library/src/scala/NamedTuple.scala -- [x] library/src/scala/PolyFunction.scala -- [x] library/src/scala/Precise.scala -- [x] library/src/scala/Pure.scala -- [x] library/src/scala/Selectable.scala -- [x] library/src/scala/Tuple.scala -- [x] library/src/scala/annotation/MacroAnnotation.scala -- [x] library/src/scala/annotation/RefiningAnnotation.scala -- [x] library/src/scala/annotation/alpha.scala -- [x] library/src/scala/annotation/capability.scala -- [x] library/src/scala/annotation/constructorOnly.scala -- [x] library/src/scala/annotation/experimental.scala -- [x] library/src/scala/annotation/init.scala -- [x] library/src/scala/annotation/internal/$into.scala -- [x] library/src/scala/annotation/internal/Alias.scala -- [x] library/src/scala/annotation/internal/AnnotationDefault.scala -- [x] library/src/scala/annotation/internal/AssignedNonLocally.scala -- [x] library/src/scala/annotation/internal/Body.scala -- [x] library/src/scala/annotation/internal/CaptureChecked.scala -- [x] library/src/scala/annotation/internal/Child.scala -- [x] library/src/scala/annotation/internal/ContextResultCount.scala -- [x] library/src/scala/annotation/internal/ErasedParam.scala -- [x] library/src/scala/annotation/internal/InlineParam.scala -- [x] library/src/scala/annotation/internal/MappedAlternative.scala -- [x] library/src/scala/annotation/internal/ProvisionalSuperClass.scala -- [x] library/src/scala/annotation/internal/Repeated.scala -- [x] library/src/scala/annotation/internal/RuntimeChecked.scala -- [x] library/src/scala/annotation/internal/SourceFile.scala -- [x] library/src/scala/annotation/internal/WithPureFuns.scala -- [x] library/src/scala/annotation/internal/WitnessNames.scala -- [x] library/src/scala/annotation/internal/preview.scala -- [x] library/src/scala/annotation/internal/reachCapability.scala -- [x] library/src/scala/annotation/internal/readOnlyCapability.scala -- [x] library/src/scala/annotation/internal/requiresCapability.scala -- [x] library/src/scala/annotation/internal/sharable.scala -- [x] library/src/scala/annotation/internal/unshared.scala -- [x] library/src/scala/annotation/into.scala -- [x] library/src/scala/annotation/publicInBinary.scala -- [x] library/src/scala/annotation/retains.scala -- [x] library/src/scala/annotation/retainsByName.scala -- [x] library/src/scala/annotation/static.scala -- [x] library/src/scala/annotation/targetName.scala -- [x] library/src/scala/annotation/threadUnsafe.scala -- [x] library/src/scala/annotation/transparentTrait.scala -- [ ] library/src/scala/annotation/unchecked/uncheckedCapabilityLeaks.scala -- [x] library/src/scala/annotation/unchecked/uncheckedCaptures.scala -- [x] library/src/scala/annotation/unroll.scala -- [x] library/src/scala/caps/package.scala -- [x] library/src/scala/compiletime/ops/any.scala -- [x] library/src/scala/compiletime/ops/boolean.scala -- [x] library/src/scala/compiletime/ops/double.scala -- [x] library/src/scala/compiletime/ops/float.scala -- [x] library/src/scala/compiletime/ops/int.scala -- [x] library/src/scala/compiletime/ops/long.scala -- [x] library/src/scala/compiletime/ops/string.scala -- [x] library/src/scala/compiletime/package.scala -- [x] library/src/scala/compiletime/testing/Error.scala -- [x] library/src/scala/compiletime/testing/ErrorKind.scala -- [x] library/src/scala/compiletime/testing/package.scala -- [x] library/src/scala/main.scala -- [x] library/src/scala/quoted/Expr.scala -- [x] library/src/scala/quoted/ExprMap.scala -- [x] library/src/scala/quoted/Exprs.scala -- [x] library/src/scala/quoted/FromExpr.scala -- [x] library/src/scala/quoted/Quotes.scala -- [x] library/src/scala/quoted/ToExpr.scala -- [x] library/src/scala/quoted/Type.scala -- [x] library/src/scala/quoted/Varargs.scala -- [x] library/src/scala/quoted/runtime/Expr.scala -- [x] library/src/scala/quoted/runtime/Patterns.scala -- [x] library/src/scala/quoted/runtime/QuoteMatching.scala -- [x] library/src/scala/quoted/runtime/QuoteUnpickler.scala -- [x] library/src/scala/quoted/runtime/SplicedType.scala -- [x] library/src/scala/quoted/runtime/StopMacroExpansion.scala -- [x] library/src/scala/reflect/Enum.scala -- [x] library/src/scala/reflect/Selectable.scala -- [x] library/src/scala/reflect/TypeTest.scala -- [x] library/src/scala/reflect/Typeable.scala -- [x] library/src/scala/runtime/$throws.scala -- [x] library/src/scala/runtime/Arrays.scala -- [x] library/src/scala/runtime/EnumValue.scala -- [x] library/src/scala/runtime/FunctionXXL.scala -- [x] library/src/scala/runtime/LazyVals.scala -- [x] library/src/scala/runtime/MatchCase.scala -- [x] library/src/scala/runtime/Scala3RunTime.scala -- [x] library/src/scala/runtime/TupleMirror.scala -- [x] library/src/scala/runtime/TupleXXL.scala -- [x] library/src/scala/runtime/TupledFunctions.scala -- [x] library/src/scala/runtime/Tuples.scala -- [x] library/src/scala/runtime/TypeBox.scala -- [x] library/src/scala/runtime/coverage/Invoker.scala -- [x] library/src/scala/runtime/stdLibPatches/Predef.scala -- [x] library/src/scala/runtime/stdLibPatches/language.scala -- [x] library/src/scala/util/CommandLineParser.scala -- [x] library/src/scala/util/FromDigits.scala -- [x] library/src/scala/util/NotGiven.scala -- [x] library/src/scala/util/TupledFunction.scala -- [x] library/src/scala/util/boundary.scala -- [x] library/src/scala/util/control/NonLocalReturns.scala diff --git a/mk_todo.fish b/mk_todo.fish deleted file mode 100755 index 365c2c46dcd5..000000000000 --- a/mk_todo.fish +++ /dev/null @@ -1,6 +0,0 @@ -#!/usr/bin/env fish - -for file in (ls library/src/**.scala | sort) - set checkbox (if rg -q 'import (scala.)?language.experimental.captureChecking' $file; echo "[x]"; else; echo "[ ]"; end) - printf "- %s %s\n" $checkbox $file -end From c771f9f1634b2f91241d1a57892355630cea4b7c Mon Sep 17 00:00:00 2001 From: Natsu Kagami Date: Fri, 15 Aug 2025 18:01:15 +0200 Subject: [PATCH 27/32] Remove extra added line --- compiler/src/dotty/tools/dotc/core/Definitions.scala | 1 - 1 file changed, 1 deletion(-) diff --git a/compiler/src/dotty/tools/dotc/core/Definitions.scala b/compiler/src/dotty/tools/dotc/core/Definitions.scala index a0a937dd803b..5102f7021825 100644 --- a/compiler/src/dotty/tools/dotc/core/Definitions.scala +++ b/compiler/src/dotty/tools/dotc/core/Definitions.scala @@ -1149,7 +1149,6 @@ class Definitions { "reactor.util.annotation.NonNullApi" :: "io.reactivex.annotations.NonNull" :: Nil) - // convenient one-parameter method types def methOfAny(tp: Type): MethodType = MethodType(List(AnyType), tp) def methOfAnyVal(tp: Type): MethodType = MethodType(List(AnyValType), tp) From bdfe28abcdd83bc57d05e26edec98b02f986a9b4 Mon Sep 17 00:00:00 2001 From: Natsu Kagami Date: Sat, 16 Aug 2025 00:58:59 +0200 Subject: [PATCH 28/32] Apply suggestions from code review Co-authored-by: Hamza Remmal --- compiler/src/dotty/tools/dotc/transform/SyntheticMembers.scala | 2 -- library/src/scala/Tuple.scala | 2 +- project/Build.scala | 1 - 3 files changed, 1 insertion(+), 4 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/transform/SyntheticMembers.scala b/compiler/src/dotty/tools/dotc/transform/SyntheticMembers.scala index 6ea8773f4664..fbff51acb514 100644 --- a/compiler/src/dotty/tools/dotc/transform/SyntheticMembers.scala +++ b/compiler/src/dotty/tools/dotc/transform/SyntheticMembers.scala @@ -17,8 +17,6 @@ import util.Spans.Span import config.Printers.derive import NullOpsDecorator.* import scala.runtime.Statics -import dotty.tools.dotc.config.Feature -import dotty.tools.dotc.cc.CapturingType object SyntheticMembers { diff --git a/library/src/scala/Tuple.scala b/library/src/scala/Tuple.scala index 2f865f9037ba..6d6f234a817a 100644 --- a/library/src/scala/Tuple.scala +++ b/library/src/scala/Tuple.scala @@ -175,7 +175,7 @@ object Tuple { case h *: t => F[h, Fold[t, Z, F]] /** Converts a tuple `(T1, ..., Tn)` to `(F[T1], ..., F[Tn])` */ - type Map[Tup <: Tuple, F <: [_ <: Union[Tup]] =>> Any] <: Tuple = Tup match { + type Map[Tup <: Tuple, F[_ <: Union[Tup]]] <: Tuple = Tup match { case EmptyTuple => EmptyTuple case h *: t => F[h] *: Map[t, F] } diff --git a/project/Build.scala b/project/Build.scala index 33e7a83e7ce0..9acb1c7d55aa 100644 --- a/project/Build.scala +++ b/project/Build.scala @@ -1083,7 +1083,6 @@ object Build { // NOTE: Do not use `sourceDirectories` since `sources` are currently pinned until `3.8.0` "-sourcepath", (Compile / sources).value.map(_.getCanonicalPath).distinct.mkString(File.pathSeparator), "-Yexplicit-nulls", - "-explain", ), (Compile / doc / scalacOptions) ++= ScaladocConfigs.DefaultGenerationSettings.value.settings, (Compile / packageSrc / mappings) ++= { From 9b0fd11b665b1c09e3ed301e1ddfb667fe29d461 Mon Sep 17 00:00:00 2001 From: Natsu Kagami Date: Sat, 16 Aug 2025 01:21:08 +0200 Subject: [PATCH 29/32] Update output of boundary test --- tests/neg-custom-args/captures/boundary.check | 20 ++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/tests/neg-custom-args/captures/boundary.check b/tests/neg-custom-args/captures/boundary.check index a795f131998a..c2b87bf5baa9 100644 --- a/tests/neg-custom-args/captures/boundary.check +++ b/tests/neg-custom-args/captures/boundary.check @@ -2,15 +2,15 @@ 4 | boundary[AnyRef^]: 5 | l1 ?=> // error // error | ^ - |Found: scala.util.boundary.Label[Object^?]^{cap.rd} + |Found: scala.util.boundary.Label[Object^'s1]^{cap.rd} |Required: scala.util.boundary.Label[Object^]^² | - |where: ^ refers to the universal root capability - | ^² refers to a fresh root capability classified as Control in the type of value local - | cap is a fresh root capability classified as Control created in value local when constructing Capability instance scala.util.boundary.Label[Object^?] + |Note that capability cap² cannot be included in outer capture set 's1. | - |Note that capability cap - |cannot be included in outer capture set ?. + |where: ^ refers to the universal root capability + | ^² refers to a fresh root capability classified as Control in the type of value local + | cap is a fresh root capability classified as Control created in value local when constructing Capability instance scala.util.boundary.Label[Object^'s1] + | cap² is the universal root capability 6 | boundary[Unit]: l2 ?=> 7 | boundary.break(l2)(using l1) 8 | ??? @@ -30,10 +30,12 @@ | Found: scala.util.boundary.Break[AnyRef^] @unchecked | Required: scala.util.boundary.Break[Object^²] @unchecked | - | where: ^ refers to the universal root capability - | ^² refers to a fresh root capability created in package + | Note that capability cap is not included in capture set {cap²}. | - | Note that capability cap is not included in capture set {cap}. + | where: ^ refers to the universal root capability + | ^² refers to a fresh root capability created in package + | cap is a fresh root capability created in package + | cap² is the universal root capability 6 | boundary[Unit]: l2 ?=> 7 | boundary.break(l2)(using l1) 8 | ??? From 84bc4e37af899fec19e884a264a87709e87267a2 Mon Sep 17 00:00:00 2001 From: Natsu Kagami Date: Sat, 16 Aug 2025 16:44:56 +0200 Subject: [PATCH 30/32] Make Break.label public again Avoid source-breaking changes for now. Co-authored-by: Hamza Remmal --- library/src/scala/util/boundary.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/src/scala/util/boundary.scala b/library/src/scala/util/boundary.scala index e589618f008d..bbdc0d94098c 100644 --- a/library/src/scala/util/boundary.scala +++ b/library/src/scala/util/boundary.scala @@ -33,7 +33,7 @@ object boundary: /** User code should call `break.apply` instead of throwing this exception * directly. */ - final class Break[T] private[boundary](private[boundary] val label: Label[T]^{}, val value: T) + final class Break[T] private[boundary](val label: Label[T]^{}, val value: T) extends RuntimeException( /*message*/ null, /*cause*/ null, /*enableSuppression=*/ false, /*writableStackTrace*/ false): /** Compare the given [[Label]] to the one this [[Break]] was constructed with. */ From 78ef54152ad6f8e9835ef2b847592c3b4c6e8b5d Mon Sep 17 00:00:00 2001 From: Natsu Kagami Date: Sat, 16 Aug 2025 16:48:14 +0200 Subject: [PATCH 31/32] Add safety comment to `Boundary.label` --- library/src/scala/util/boundary.scala | 3 +++ 1 file changed, 3 insertions(+) diff --git a/library/src/scala/util/boundary.scala b/library/src/scala/util/boundary.scala index bbdc0d94098c..75df7f9b2121 100644 --- a/library/src/scala/util/boundary.scala +++ b/library/src/scala/util/boundary.scala @@ -32,6 +32,9 @@ object boundary: /** User code should call `break.apply` instead of throwing this exception * directly. + * + * Note that it is **capability unsafe** to access `label` from a `Break`. + * This field will be marked private in a future release. */ final class Break[T] private[boundary](val label: Label[T]^{}, val value: T) extends RuntimeException( From 6622e4c27176886cb941db4cd9cc17bc6caf8d8c Mon Sep 17 00:00:00 2001 From: Natsu Kagami Date: Sat, 16 Aug 2025 19:14:54 +0200 Subject: [PATCH 32/32] Fix boundary test error line number --- tests/neg-custom-args/captures/boundary.check | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/neg-custom-args/captures/boundary.check b/tests/neg-custom-args/captures/boundary.check index c2b87bf5baa9..dd0b6716adc7 100644 --- a/tests/neg-custom-args/captures/boundary.check +++ b/tests/neg-custom-args/captures/boundary.check @@ -17,8 +17,8 @@ |-------------------------------------------------------------------------------------------------------------------- |Inline stack trace |- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - |This location contains code that was inlined from boundary.scala:70 -70 | val local = Label[T]() + |This location contains code that was inlined from boundary.scala:73 +73 | val local = Label[T]() | ^^^^^^^^^^ -------------------------------------------------------------------------------------------------------------------- | @@ -42,8 +42,8 @@ |-------------------------------------------------------------------------------------------------------------------- |Inline stack trace |- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - |This location contains code that was inlined from boundary.scala:72 -72 | catch case ex: Break[T] @unchecked => + |This location contains code that was inlined from boundary.scala:75 +75 | catch case ex: Break[T] @unchecked => | ^ -------------------------------------------------------------------------------------------------------------------- |