Skip to content

Conversation

@lihaoyi
Copy link
Contributor

@lihaoyi lihaoyi commented Nov 20, 2025

  • repl contains the current implementation of the Scala3 REPL
  • repl-embedded is the assembly jar of repl, containing all the transitive classfiles, but moved under the dotty.isolated namespace.
  • repl-embedded contains three main un-isolated things:
    • scala.tools.repl.EmbeddedReplMain, which spawns an isolated classloader that knows how to load stuff from the dotty.tools.repol.shaded namespace, and uses that to instantiate a ReplDriver
    • The PPrint/Fansi/Sourcecode libraries, which are shaded manually to dotty.shaded.* via source code mangling but are not classloader-isolated from user code
    • scala-library.jar, which is guaranteed to be the same anyway

This approach allows anyone using the repl-embedded artifact to be confident there will not be classpath conflicts with their own classpath, since all the Scala compiler jars and transitive dependencies are isolated within a classloader and will not collide with user code. Furthermore, this allows us to begin using arbitrary third-party dependencies in the scala3-repl's implementation without them bleeding into user code inside or outside the REPL, with a few exceptions like PPrint/Fansi/Sourcecode below

The PPrint/Fansi/Sourcecode libraries cannot be isolated because they need to be present in the same classloader as user code in order for PPrint logic like case s: Seq[_] => to work correctly: if they were in a separate classloader, the Seq in PPrint would differ from the Seq in user code, and these type tests would all fail. And due to the REPL interrupt instrumentation implemented in #24194, the REPL-code-classloader will ~always be different from the external user code classloader, so the PPrint/Fansi/Sourcecode classes have to be in that classloader to make things work and the only way to make it work

Tested manually to verify that the REPL classes do not appear on the classpath

sbt scala3-compiler-bootstrapped-new/publishLocalBin scala3-library-bootstrapped-new/publishLocalBin scala-library-bootstrapped/publishLocalBin tasty-core-bootstrapped-new/publishLocalBin scala3-repl/publishLocalBin scala3-interfaces/publishLocalBin
sbt scala3-repl-embedded/publishLocalBin
java -cp $(cs fetch -p org.scala-lang:scala3-repl-embedded_3:3.8.1-RC1-bin-SNAPSHOT) scala.tools.repl.EmbeddedReplMain -cp $(cs fetch -p org.scala-lang:scala3-repl-embedded_3:3.8.1-RC1-bin-SNAPSHOT)
scala> 1 + 1
val res0: Int = 2

scala> dotty.tools.repl.Main
-- [E008] Not Found Error: -----------------------------------------------------
1 |dotty.tools.repl.Main
  |^^^^^^^^^^^^^^^^^^^^^
  |value Main is not a member of dotty.tools.repl
1 error found

scala> fansi.Str("")
-- [E006] Not Found Error: -----------------------------------------------------
1 |fansi.Str("")
  |^^^^^
  |Not found: fansi
  |
  | longer explanation available when compiling with `-explain`
1 error found

Fixes #24382

@lihaoyi lihaoyi changed the title Provided a repl-embedded artifact which shades everything to avoid conflicts [WIP] Provided a repl-embedded artifact which shades everything to avoid conflicts Nov 20, 2025
@lihaoyi lihaoyi changed the title [WIP] Provided a repl-embedded artifact which shades everything to avoid conflicts [WIP] Provided a repl-embedded artifact which shades and isolates everything to avoid conflicts Nov 21, 2025
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.

Re-isolate PPrint + REPL extra libs

1 participant