Skip to content

Port Capture-checked Scala 2 collections #23769

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 76 commits into
base: main
Choose a base branch
from

Conversation

natsukagami
Copy link
Contributor

@natsukagami natsukagami commented Aug 16, 2025

Changes:

  • New final class collection.immutable.LazyListIterable[A], implements Iterable and IterableOps. LazyList and Stream are not capture-checked. Note added to LazyList.
  • New trait collection.StrictSeqOps[A, CC[_] <: Pure, C], which extends SeqOps (which can now be impure) and requires the implementation to be pure. Seq and other data structures extend this.
  • Similarly, collection.StrictIndexedSeqOps, collection.StrictMapOps, collection.StrictFactory.
    • Note that collection.SetOps is pure by default. Maybe we want a StrictSetOps as well?
    • Sorted versions of Ops (SortedSeq, SortedSet, SortedMap) are also pure by default.

Suspicious changes:

  • Might be suspicious: MapOps.keySet changes implementation to be always strict. This means it is less efficient, as it always copy the keys into a new list.
    • StrictMapOps however overrides this behavior back to a lazy KeySet.
    • Why? keySet returns a Set[K], which requires strictness. We cannot lie to the compiler about this case, as we can take a keySet out of an impure MapView, which may capture map/filter function bodies.
    • In reality this should only affect code taking keysets of a MapView, or directly using MapOps (should be rare).

Not capture-checked (yet?)

  • Generated functions and tuples files. I tried turning CC on for functions and it hung the compiler. Maybe not a problem.
  • collection.convert.impl a.k.a Steppers, due to some purity problems (maybe because we don't compile steppers and rely on Scala 2, for specialization?).
  • LazyList and Streams.

@natsukagami natsukagami requested a review from bracevac August 16, 2025 19:13
@@ -7,5 +7,5 @@ import language.experimental.captureChecking
* sense that their values retain no capabilities including capabilities needed
* to perform effects. This has formal meaning only under capture checking.
*/
trait Pure:
trait Pure extends Any:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I thought I left a comment about this somewhere but I'm glad it is a universal trait now.

@@ -711,7 +713,7 @@ final class TrieMap[K, V] private (r: AnyRef, rtupd: AtomicReferenceFieldUpdater

def this() = this(Hashing.default, Equiv.universal)

override def mapFactory: MapFactory[TrieMap] = TrieMap
override def mapFactory: StrictMapFactory[TrieMap] = TrieMap
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It might be a good idea if we created a changelog?

@@ -91,7 +94,7 @@ trait AsScalaConverters {
*/
def asScala[A](c: ju.Collection[A]): Iterable[A] = c match {
case null => null
case wrapper: IterableWrapper[A @uc] => wrapper.underlying
case wrapper: IterableWrapper[A @uc] => wrapper.underlying.unsafeAssumePure // TODO: Remove when pattern matching recognizes this is safe
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we have an issue ticket for those?

@natsukagami
Copy link
Contributor Author

natsukagami commented Aug 17, 2025

CC test is failing because scala2-library-cc doesn't have PartialFunctions capture-checked. @hamzaremmal can we move the test to use the unified lib instead?

We can also just disable it for now, since it only test scala2-library-cc which we will soon remove after this.

@hamzaremmal
Copy link
Member

CC test is failing because scala2-library-cc doesn't have PartialFunctions capture-checked. @hamzaremmal can we move the test to use the unified lib instead?

We can also just disable it for now, since it only test scala2-library-cc which we will soon remove after this.

I will see what I can do this morning.

The compiler can properly figure out the return types based on the Pure upper bound on CC
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants