diff --git a/build.sbt b/build.sbt index aedb04e93ec9..10920336da89 100644 --- a/build.sbt +++ b/build.sbt @@ -9,6 +9,7 @@ val `scala3-compiler-nonbootstrapped` = Build.`scala3-compiler-nonbootstrapped` val `scala3-compiler-bootstrapped-new` = Build.`scala3-compiler-bootstrapped-new` val `scala3-repl` = Build.`scala3-repl` +val `scala3-repl-embedded` = Build.`scala3-repl-embedded` // The Standard Library val `scala-library-nonbootstrapped` = Build.`scala-library-nonbootstrapped` diff --git a/project/Build.scala b/project/Build.scala index 9fc41203f816..3e21224e4288 100644 --- a/project/Build.scala +++ b/project/Build.scala @@ -26,6 +26,9 @@ import dotty.tools.sbtplugin.ScalaLibraryPlugin import dotty.tools.sbtplugin.ScalaLibraryPlugin.autoImport._ import dotty.tools.sbtplugin.DottyJSPlugin import dotty.tools.sbtplugin.DottyJSPlugin.autoImport._ +import sbtassembly.AssemblyPlugin.autoImport._ +import sbtassembly.{MergeStrategy, PathList} +import com.eed3si9n.jarjarabrams.ShadeRule import sbt.plugins.SbtPlugin import sbt.ScriptedPlugin.autoImport._ @@ -1107,9 +1110,6 @@ object Build { "org.jline" % "jline-reader" % "3.29.0", "org.jline" % "jline-terminal" % "3.29.0", "org.jline" % "jline-terminal-jni" % "3.29.0", - "com.lihaoyi" %% "pprint" % "0.9.3", - "com.lihaoyi" %% "fansi" % "0.5.1", - "com.lihaoyi" %% "sourcecode" % "0.4.4", "com.github.sbt" % "junit-interface" % "0.13.3" % Test, "io.get-coursier" % "interface" % "1.0.28", // used by the REPL for dependency resolution "org.virtuslab" % "using_directives" % "1.1.4", // used by the REPL for parsing magic comments @@ -1177,6 +1177,176 @@ object Build { (Compile / run).toTask(" -usejavacp").value }, bspEnabled := false, + (Compile / sourceGenerators) += Def.task { + val s = streams.value + val cacheDir = s.cacheDirectory + val dest = (Compile / sourceManaged).value / "downloaded" + val lm = dependencyResolution.value + + val dependencies = Seq( + ("com.lihaoyi", "pprint_3", "0.9.5"), + ("com.lihaoyi", "fansi_3", "0.5.1"), + ("com.lihaoyi", "sourcecode_3", "0.4.4"), + ) + + // Create a marker file that tracks the dependencies for cache invalidation + val markerFile = cacheDir / "shaded-sources-marker" + val markerContent = dependencies.map { case (org, name, version) => s"$org:$name:$version:sources" }.mkString("\n") + if (!markerFile.exists || IO.read(markerFile) != markerContent) { + IO.write(markerFile, markerContent) + } + + FileFunction.cached(cacheDir / "fetchShadedSources", + FilesInfo.lastModified, FilesInfo.exists) { _ => + s.log.info(s"Downloading and processing shaded sources to $dest...") + + if (dest.exists) IO.delete(dest) + IO.createDirectory(dest) + + for((org, name, version) <- dependencies) { + import sbt.librarymanagement._ + + val moduleId = ModuleID(org, name, version).sources() + val retrieveDir = cacheDir / "retrieved" / s"$org-$name-$version-sources" + + s.log.info(s"Retrieving $org:$name:$version:sources...") + val retrieved = lm.retrieve(moduleId, scalaModuleInfo = None, retrieveDir, s.log) + val jarFiles = retrieved.fold( + w => throw w.resolveException, + files => files.filter(_.getName.contains("-sources.jar")) + ) + + jarFiles.foreach { jarFile => + s.log.info(s"Extracting ${jarFile.getName}...") + IO.unzip(jarFile, dest) + } + } + + val scalaFiles = (dest ** "*.scala").get + + val patches = Map( // Define patches as a map from search text to replacement text + "import scala" -> "import _root_.scala", + " scala.collection." -> " _root_.scala.collection.", + "def apply(c: Char): Trie[T]" -> "def apply(c: Char): Trie[T] | Null", + "var head: Iterator[T] = null" -> "var head: Iterator[T] | Null = null", + "if (head != null && head.hasNext) true" -> "if (head != null && head.nn.hasNext) true", + "head.next()" -> "head.nn.next()", + "abstract class Walker" -> "@scala.annotation.nowarn abstract class Walker", + "object TPrintLowPri" -> "@scala.annotation.nowarn object TPrintLowPri", + "x.toString match{" -> "scala.runtime.ScalaRunTime.stringOf(x) match{" + ) + + val patchUsageCounter = scala.collection.mutable.Map(patches.keys.map(_ -> 0).toSeq: _*) + + scalaFiles.foreach { file => + val text = IO.read(file) + if (!file.getName.equals("CollectionName.scala")) { + var processedText = "package dotty.shaded\n" + text + + // Apply patches and count usage + for((search, replacement) <- patches if processedText.contains(search)){ + processedText = processedText.replace(search, replacement) + patchUsageCounter(search) += 1 + } + + IO.write(file, processedText) + } + } + + // Assert that all patches were applied at least once + val unappliedPatches = patchUsageCounter.filter(_._2 == 0).keys + if (unappliedPatches.nonEmpty) { + throw new RuntimeException(s"Patches were not applied: ${unappliedPatches.mkString(", ")}") + } + + scalaFiles.toSet + } (Set(markerFile)).toSeq + + } + ) + + lazy val `scala3-repl-embedded` = project.in(file("repl-embedded")) + .dependsOn(`scala-library-bootstrapped`) + .enablePlugins(sbtassembly.AssemblyPlugin) + .settings(publishSettings) + .settings( + name := "scala3-repl-embedded", + moduleName := "scala3-repl-embedded", + version := dottyVersion, + versionScheme := Some("semver-spec"), + scalaVersion := referenceVersion, + crossPaths := true, + autoScalaLibrary := true, + libraryDependencies ++= Seq( + "org.jline" % "jline-reader" % "3.29.0", + "org.jline" % "jline-terminal" % "3.29.0", + "org.jline" % "jline-terminal-jni" % "3.29.0", + ), + Compile / unmanagedSourceDirectories := Seq(baseDirectory.value / "src"), + // Assembly configuration for shading + assembly / assemblyJarName := s"scala3-repl-embedded-${version.value}.jar", + // Add scala3-repl to assembly classpath without making it a published dependency + assembly / fullClasspath := { + (Compile / fullClasspath).value ++ (`scala3-repl` / assembly / fullClasspath).value + }, + assembly / test := {}, // Don't run tests for assembly + // Exclude scala-library and jline from assembly (users provide them on classpath) + assembly / assemblyExcludedJars := { + (assembly / fullClasspath).value.filter { jar => + val name = jar.data.getName + // Filter out the `scala-library` here otherwise it conflicts with the + // `scala-library` pulled in via `assembly / fullClasspath` + name.contains("scala-library") || + // Avoid shading JLine because shading it causes problems with + // its service discovery and JNI-related logic + // This is the entrypoint to the embedded Scala REPL so don't shade it + name.contains("jline") + } + }, + + assembly := { + val originalJar = assembly.value + val log = streams.value.log + + log.info(s"Post-processing assembly to relocate files into shaded subfolder...") + + val tmpDir = IO.createTemporaryDirectory + try { + IO.unzip(originalJar, tmpDir) + val shadedDir = tmpDir / "dotty" / "isolated" + IO.createDirectory(shadedDir) + + for(file <- (tmpDir ** "*").get if file.isFile) { + val relativePath = file.relativeTo(tmpDir).get.getPath + + val shouldKeepInPlace = + relativePath.startsWith("dotty/embedded/")|| + // These are manually shaded when vendored/patched so leave them alone + relativePath.startsWith("dotty/shaded/") || + // This needs to be inside scala/collection so cannot be moved + relativePath.startsWith("scala/collection/internal/pprint/") + + if (!shouldKeepInPlace) { + val newPath = shadedDir / relativePath + IO.createDirectory(newPath.getParentFile) + IO.move(file, newPath) + } + } + + val filesToZip = + for(f <- (tmpDir ** "*").get if f.isFile) + yield (f, f.relativeTo(tmpDir).get.getPath) + + IO.zip(filesToZip, originalJar, None) + + log.info(s"Assembly post-processing complete") + } finally IO.delete(tmpDir) + + originalJar + }, + // Use the shaded assembly jar as our packageBin for publishing + Compile / packageBin := (Compile / assembly).value, + publish / skip := false, ) // ============================================================================================== diff --git a/project/plugins.sbt b/project/plugins.sbt index 241dda64f69b..277c5017a061 100644 --- a/project/plugins.sbt +++ b/project/plugins.sbt @@ -25,3 +25,5 @@ addSbtPlugin("com.gradle" % "sbt-develocity" % "1.3.1") addSbtPlugin("com.gradle" % "sbt-develocity-common-custom-user-data" % "1.1") addSbtPlugin("com.github.sbt" % "sbt-jdi-tools" % "1.2.0") + +addSbtPlugin("com.eed3si9n" % "sbt-assembly" % "2.1.5") diff --git a/repl-embedded/src/dotty/embedded/EmbeddedReplMain.scala b/repl-embedded/src/dotty/embedded/EmbeddedReplMain.scala new file mode 100644 index 000000000000..92b19640ea91 --- /dev/null +++ b/repl-embedded/src/dotty/embedded/EmbeddedReplMain.scala @@ -0,0 +1,80 @@ +package dotty.embedded + +import java.net.{URL, URLClassLoader} +import java.io.InputStream + +/** + * A classloader that remaps shaded classes back to their original package names. + */ +class UnshadingClassLoader(parent: ClassLoader) extends ClassLoader(parent) { + + // dotty.isolated classes are loaded only within the REPL impl classloader. + // They exist in the enclosing classpath relocated within the dotty.isolated + // package, but are relocated to their proper package when the REPL impl + // classloader loads them + private val ISOLATED_PREFIX = "dotty.isolated." + + override def loadClass(name: String, resolve: Boolean): Class[?] = { + val loaded = findLoadedClass(name) + if (loaded != null) return loaded + + // dotty.shaded classes are loaded separately between the REPL line classloader + // and the REPL impl classloader, but at the same path because the REPL line + // classloader doesn't tolerate relocating classfiles + val shadedPath = (if (name.startsWith("dotty.shaded.")) name else ISOLATED_PREFIX + name) + .replace('.', '/') + ".class" + + val is0 = scala.util.Try(Option(super.getResourceAsStream(shadedPath))).toOption.flatten + + is0 match{ + case Some(is) => + try { + val bytes = is.readAllBytes() + val clazz = defineClass(name, bytes, 0, bytes.length) + if (resolve) resolveClass(clazz) + clazz + } finally is.close() + case None => + // These classes are loaded shared between all classloaders, because + // they misbehave if loaded multiple times in separate classloaders + if (name.startsWith("java.") || name.startsWith("org.jline.")) parent.loadClass(name) + // Other classes loaded by the `UnshadingClassLoader` *must* be found in the + // `dotty.isolated` package. If they're not there, throw an error rather than + // trying to look for them at their normal package path, to ensure we're not + // accidentally pulling stuff in from the enclosing classloader + else throw new ClassNotFoundException(name) + } + } + + override def getResourceAsStream(name: String): InputStream | Null = { + super.getResourceAsStream(ISOLATED_PREFIX.replace('.', '/') + name) + } +} + +/** + * Main entry point for the embedded shaded REPL. + * + * This creates an isolated classloader that loads the shaded REPL classes + * as if they were unshaded, instantiates a ReplDriver, and runs it. + */ +object EmbeddedReplMain { + def main(args: Array[String]): Unit = { + val argsWithClasspath = + if (args.exists(arg => arg == "-classpath" || arg == "-cp")) args + else Array("-classpath", System.getProperty("java.class.path")) ++ args + + val unshadingClassLoader = new UnshadingClassLoader(getClass.getClassLoader) + val replDriverClass = unshadingClassLoader.loadClass("dotty.tools.repl.ReplDriver") + val someCls = unshadingClassLoader.loadClass("scala.Some") + val pprintImport = replDriverClass.getMethod("pprintImport").invoke(null) + + val replDriver = replDriverClass.getConstructors().head.newInstance( + /*settings*/ argsWithClasspath, + /*out*/ System.out, + /*classLoader*/ someCls.getConstructors().head.newInstance(getClass.getClassLoader), + /*extraPredef*/ pprintImport + ) + + replDriverClass.getMethod("tryRunning").invoke(replDriver) + } +} diff --git a/repl/src/dotty/tools/repl/Rendering.scala b/repl/src/dotty/tools/repl/Rendering.scala index fde300bcf39d..7b71d16ed5d1 100644 --- a/repl/src/dotty/tools/repl/Rendering.scala +++ b/repl/src/dotty/tools/repl/Rendering.scala @@ -9,7 +9,7 @@ import printing.ReplPrinter import printing.SyntaxHighlighting import reporting.Diagnostic import StackTraceOps.* - +import dotty.shaded.* import scala.compiletime.uninitialized import scala.util.control.NonFatal @@ -31,21 +31,16 @@ private[repl] class Rendering(parentClassLoader: Option[ClassLoader] = None): def fallback() = pprint.PPrinter.Color .apply(value, width = width, height = height, initialOffset = initialOffset) - .plainText + .render + try - // normally, if we used vanilla JDK and layered classloaders, we wouldnt need reflection. - // however PPrint works by runtime type testing to deconstruct values. This is - // sensitive to which classloader instantiates the object under test, i.e. - // `value` is constructed inside the repl classloader. Testing for - // `value.isInstanceOf[scala.Product]` in this classloader fails (JDK AppClassLoader), - // because repl classloader has two layers where it can redefine `scala.Product`: - // - `new URLClassLoader` constructed with contents of the `-classpath` setting - // - `AbstractFileClassLoader` also might instrument the library code to support interrupt. - // Due the possible interruption instrumentation, it is unlikely that we can get - // rid of reflection here. + // PPrint needs to do type-tests against scala-library classes, but the `classLoader()` + // used in the REPL typically has a its own copy of such classes to support + // `-XreplInterruptInstrumentation`. Thus we need to use the copy of PPrint from the + // REPL-line `classLoader()` rather than our own REPL-impl classloader in order for it + // to work val cl = classLoader() - val pprintCls = Class.forName("pprint.PPrinter$Color$", false, cl) - val fansiStrCls = Class.forName("fansi.Str", false, cl) + val pprintCls = Class.forName("dotty.shaded.pprint.PPrinter$Color$", false, cl) val Color = pprintCls.getField("MODULE$").get(null) val Color_apply = pprintCls.getMethod("apply", classOf[Any], // value @@ -56,12 +51,12 @@ private[repl] class Rendering(parentClassLoader: Option[ClassLoader] = None): classOf[Boolean], // escape Unicode classOf[Boolean], // show field names ) - val FansiStr_render = fansiStrCls.getMethod("render") - val fansiStr = Color_apply.invoke( - Color, value, width, height, 2, initialOffset, false, true - ) - FansiStr_render.invoke(fansiStr).asInstanceOf[String] + + val fansiStr = Color_apply.invoke(Color, value, width, height, 2, initialOffset, false, true) + fansiStr.toString catch + // If classloading fails for whatever reason, try to fallback to our own version + // of PPrint. Won't be as good, but better than blowing up with an exception case ex: ClassNotFoundException => fallback() case ex: NoSuchMethodException => fallback() } diff --git a/repl/src/dotty/tools/repl/ReplDriver.scala b/repl/src/dotty/tools/repl/ReplDriver.scala index 298c44487f2e..4c54b2959c32 100644 --- a/repl/src/dotty/tools/repl/ReplDriver.scala +++ b/repl/src/dotty/tools/repl/ReplDriver.scala @@ -706,4 +706,4 @@ class ReplDriver(settings: Array[String], end ReplDriver object ReplDriver: - def pprintImport = "import pprint.pprintln\n" \ No newline at end of file + def pprintImport = "import dotty.shaded.pprint.pprintln\n" \ No newline at end of file diff --git a/repl/src/dotty/tools/repl/StackTraceOps.scala b/repl/src/dotty/tools/repl/StackTraceOps.scala index 618bdd979688..c81d8c435dd7 100644 --- a/repl/src/dotty/tools/repl/StackTraceOps.scala +++ b/repl/src/dotty/tools/repl/StackTraceOps.scala @@ -16,6 +16,7 @@ import scala.language.unsafeNulls import collection.mutable, mutable.ListBuffer import dotty.tools.dotc.util.chaining.* import java.lang.System.lineSeparator +import dotty.shaded.* object StackTraceOps: diff --git a/repl/test-resources/repl/i1374 b/repl/test-resources/repl/i1374 index 2e0b5be900af..4346c92bb9b7 100644 --- a/repl/test-resources/repl/i1374 +++ b/repl/test-resources/repl/i1374 @@ -2,8 +2,40 @@ scala> implicit class Padder(val sb: StringBuilder) extends AnyVal { infix def p // defined class Padder def Padder(sb: StringBuilder): Padder scala> val greeting = new StringBuilder("Hello, kitteh!") -val greeting: StringBuilder = Hello, kitteh! +val greeting: StringBuilder = IndexedSeq( + 'H', + 'e', + 'l', + 'l', + 'o', + ',', + ' ', + 'k', + 'i', + 't', + 't', + 'e', + 'h', + '!' +) + scala> val a = greeting pad2 20 -val a: StringBuilder = Hello, kitteh!* +val a: StringBuilder = IndexedSeq( + 'H', + 'e', + 'l', + 'l', + 'o', + ',', + ' ', + 'k', + 'i', + 't', + 't', + 'e', + 'h', + '!', + '*' +) scala> val farewell = new StringBuilder("U go now.") // I hatez long bye-bye. -val farewell: StringBuilder = U go now. +val farewell: StringBuilder = IndexedSeq('U', ' ', 'g', 'o', ' ', 'n', 'o', 'w', '.') diff --git a/repl/test-resources/repl/i4852 b/repl/test-resources/repl/i4852 index 32c126578259..32ba96d053e1 100644 --- a/repl/test-resources/repl/i4852 +++ b/repl/test-resources/repl/i4852 @@ -1,6 +1,6 @@ scala> inline def foo[T](t : T*) : Any = t def foo[T](t: T*): Any scala> foo(1, "hi", false) -val res0: Any = ArraySeq(1, hi, false) +val res0: Any = ArraySeq(1, "hi", false) scala> foo() val res1: Any = ArraySeq() diff --git a/repl/test-resources/repl/i5218 b/repl/test-resources/repl/i5218 index abe63009ef74..9160df2fb7fb 100644 --- a/repl/test-resources/repl/i5218 +++ b/repl/test-resources/repl/i5218 @@ -1,6 +1,6 @@ scala> val tuple = (1, "2", 3L) -val tuple: (Int, String, Long) = (1,2,3) +val tuple: (Int, String, Long) = (1, "2", 3L) scala> 0.0 *: tuple -val res0: (Double, Int, String, Long) = (0.0,1,2,3) +val res0: (Double, Int, String, Long) = (0.0, 1, "2", 3L) scala> tuple ++ tuple -val res1: Int *: String *: Long *: tuple.type = (1,2,3,1,2,3) +val res1: Int *: String *: Long *: tuple.type = (1, "2", 3L, 1, "2", 3L) diff --git a/repl/test-resources/repl/i6474 b/repl/test-resources/repl/i6474 index 1390dce7042f..79e8cd83a28d 100644 --- a/repl/test-resources/repl/i6474 +++ b/repl/test-resources/repl/i6474 @@ -5,9 +5,9 @@ scala> object Foo2 { type T[+A] = [B] =>> (A, B) } scala> object Foo3 { type T[+A] = [B] =>> [C] =>> (A, B) } // defined object Foo3 scala> ((1, 2): Foo1.T[Int]): Foo1.T[Any] -val res0: Foo1.T[Any] = (1,2) +val res0: Foo1.T[Any] = (1, 2) scala> ((1, 2): Foo2.T[Int][Int]): Foo2.T[Any][Int] -val res1: Foo2.T[Any][Int] = (1,2) +val res1: Foo2.T[Any][Int] = (1, 2) scala> (1, 2): Foo3.T[Int][Int] -- [E056] Syntax Error: -------------------------------------------------------- 1 | (1, 2): Foo3.T[Int][Int] @@ -15,10 +15,10 @@ scala> (1, 2): Foo3.T[Int][Int] | Missing type parameter for Foo3.T[Int][Int] 1 error found scala> ((1, 2): Foo3.T[Int][Int][Int]): Foo3.T[Any][Int][Int] -val res2: Foo3.T[Any][Int][Int] = (1,2) +val res2: Foo3.T[Any][Int][Int] = (1, 2) scala> object Foo3 { type T[A] = [B] =>> [C] =>> (A, B) } // defined object Foo3 scala> ((1, 2): Foo3.T[Int][Int][Int]) -val res3: Foo3.T[Int][Int][Int] = (1,2) +val res3: Foo3.T[Int][Int][Int] = (1, 2) scala> ((1, 2): Foo3.T[Int][Int][Int]) -val res4: Foo3.T[Int][Int][Int] = (1,2) \ No newline at end of file +val res4: Foo3.T[Int][Int][Int] = (1, 2) \ No newline at end of file diff --git a/repl/test-resources/repl/settings-repl-max-print-elements b/repl/test-resources/repl/settings-repl-max-print-elements index 8afb244e1cf9..edb42d1f60a3 100644 --- a/repl/test-resources/repl/settings-repl-max-print-elements +++ b/repl/test-resources/repl/settings-repl-max-print-elements @@ -1,8 +1,106 @@ scala> 1.to(200).toList -val res0: List[Int] = List(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200) +val res0: List[Int] = List( + 1, + 2, + 3, + 4, + 5, + 6, + 7, + 8, + 9, + 10, + 11, + 12, + 13, + 14, + 15, + 16, + 17, + 18, + 19, + 20, + 21, + 22, + 23, + 24, + 25, + 26, + 27, + 28, + 29, + 30, + 31, + 32, + 33, + 34, + 35, + 36, + 37, + 38, + 39, + 40, + 41, + 42, + 43, + 44, + 45, + 46, + 47, + 48, +... scala>:settings -Vrepl-max-print-elements:20 scala> 1.to(300).toList -val res1: List[Int] = List(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, 286, 287, 288, 289, 290, 291, 292, 293, 294, 295, 296, 297, 298, 299, 300) +val res1: List[Int] = List( + 1, + 2, + 3, + 4, + 5, + 6, + 7, + 8, + 9, + 10, + 11, + 12, + 13, + 14, + 15, + 16, + 17, + 18, + 19, + 20, + 21, + 22, + 23, + 24, + 25, + 26, + 27, + 28, + 29, + 30, + 31, + 32, + 33, + 34, + 35, + 36, + 37, + 38, + 39, + 40, + 41, + 42, + 43, + 44, + 45, + 46, + 47, + 48, +... diff --git a/repl/test-resources/type-printer/prefixless b/repl/test-resources/type-printer/prefixless index 0ade08eb186b..df02b46988a2 100644 --- a/repl/test-resources/type-printer/prefixless +++ b/repl/test-resources/type-printer/prefixless @@ -1,10 +1,10 @@ scala> List(1,2,3) val res0: List[Int] = List(1, 2, 3) scala> Map("foo" -> 1) -val res1: Map[String, Int] = Map(foo -> 1) +val res1: Map[String, Int] = Map("foo" -> 1) scala> Seq('a','b') -val res2: Seq[Char] = List(a, b) +val res2: Seq[Char] = List('a', 'b') scala> Set(4, 5) val res3: Set[Int] = Set(4, 5) scala> Iterator(1) -val res4: Iterator[Int] = +val res4: Iterator[Int] = non-empty iterator diff --git a/repl/test-resources/type-printer/vals b/repl/test-resources/type-printer/vals index 21cd311cf284..cfffdf183c99 100644 --- a/repl/test-resources/type-printer/vals +++ b/repl/test-resources/type-printer/vals @@ -7,4 +7,4 @@ val xs: List[Int] = List(1) scala> scala.util.Try(1) val res0: scala.util.Try[Int] = Success(1) scala> Map(1 -> "one") -val res1: Map[Int, String] = Map(1 -> one) +val res1: Map[Int, String] = Map(1 -> "one") diff --git a/repl/test/dotty/tools/repl/ReplCompilerTests.scala b/repl/test/dotty/tools/repl/ReplCompilerTests.scala index c148be0d27ca..08917b8d02da 100644 --- a/repl/test/dotty/tools/repl/ReplCompilerTests.scala +++ b/repl/test/dotty/tools/repl/ReplCompilerTests.scala @@ -78,7 +78,7 @@ class ReplCompilerTests extends ReplTest: assertEquals(1, summon[State].imports.size) run("""mutable.Map("one" -> 1)""") assertEquals( - "val res0: scala.collection.mutable.Map[String, Int] = HashMap(one -> 1)", + "val res0: scala.collection.mutable.Map[String, Int] = HashMap(\"one\" -> 1)", storedOutput().trim ) }