Skip to content

Commit 2ef533f

Browse files
szeigerretronym
authored andcommitted
Use proxy-based serialization for modules
This avoids serializing any state of serializable singletons which would be discarded anyway after deserializing (SI-10412). Use ClassValue to cache instances, which is significantly faster for subsequent deserialization of a given module. ClassValue entries only weakly reference the key and value so the class can be unloaded. Wrap use of reflection in AccessControler to play nicely under SecurityManager. A security manager will only walk up the stack to this point to check permissions, so if users grant scala-library permissions in the policy, the call will be allowed regardless of the code higher in the stack that has triggered deserialization.
1 parent e99f3b9 commit 2ef533f

34 files changed

+162
-204
lines changed

src/compiler/scala/tools/nsc/typechecker/SyntheticMethods.scala

+14-12
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ import symtab.Flags._
3636
* def toString(): String
3737
*
3838
* Special handling:
39-
* protected def readResolve(): AnyRef
39+
* protected def writeReplace(): AnyRef
4040
*/
4141
trait SyntheticMethods extends ast.TreeDSL {
4242
self: Analyzer =>
@@ -331,16 +331,17 @@ trait SyntheticMethods extends ast.TreeDSL {
331331
// Object_equals -> (() => createMethod(Object_equals)(m => This(clazz) ANY_EQ Ident(m.firstParam)))
332332
)
333333

334-
/* If you serialize a singleton and then deserialize it twice,
335-
* you will have two instances of your singleton unless you implement
336-
* readResolve. Here it is implemented for all objects which have
337-
* no implementation and which are marked serializable (which is true
338-
* for all case objects.)
334+
/* If you serialize a singleton you will get an additional
335+
* instance of the singleton, unless you implement
336+
* special serialization logic. Here we use a serialization proxy that prevents
337+
* serialization of state and will, on deserialization by replaced by the object
338+
* via use of readResolve. This is done for all top level objects which extend
339+
* `java.io.Serializable` (such as case objects)
339340
*/
340-
def needsReadResolve = (
341+
def needsModuleSerializationProxy = (
341342
clazz.isModuleClass
342343
&& clazz.isSerializable
343-
&& !hasConcreteImpl(nme.readResolve)
344+
&& !hasConcreteImpl(nme.writeReplace)
344345
&& clazz.isStatic
345346
)
346347

@@ -374,13 +375,14 @@ trait SyntheticMethods extends ast.TreeDSL {
374375
for ((m, impl) <- methods ; if shouldGenerate(m)) yield impl()
375376
}
376377
def extras = {
377-
if (needsReadResolve) {
378+
if (needsModuleSerializationProxy) {
378379
// Aha, I finally decoded the original comment.
379380
// This method should be generated as private, but apparently if it is, then
380381
// it is name mangled afterward. (Wonder why that is.) So it's only protected.
381-
// For sure special methods like "readResolve" should not be mangled.
382-
List(createMethod(nme.readResolve, Nil, ObjectTpe)(m => {
383-
m setFlag PRIVATE; REF(clazz.sourceModule)
382+
// For sure special methods like "writeReplace" should not be mangled.
383+
List(createMethod(nme.writeReplace, Nil, ObjectTpe)(m => {
384+
m setFlag PRIVATE
385+
New(ModuleSerializationProxyClass, gen.mkClassOf(clazz.typeOfThis))
384386
}))
385387
}
386388
else Nil

src/library/scala/collection/Iterator.scala

-5
Original file line numberDiff line numberDiff line change
@@ -1190,11 +1190,6 @@ object Iterator extends IterableFactory[Iterator] {
11901190
} else Iterator.empty.next()
11911191
}
11921192
}
1193-
1194-
// scalac generates a `readReplace` method to discard the deserialized state (see https://github.com/scala/bug/issues/10412).
1195-
// This prevents it from serializing it in the first place:
1196-
private[this] def writeObject(out: ObjectOutputStream): Unit = ()
1197-
private[this] def readObject(in: ObjectInputStream): Unit = ()
11981193
}
11991194

12001195
/** Explicit instantiation of the `Iterator` trait to reduce class file size in subclasses. */

src/library/scala/collection/View.scala

-5
Original file line numberDiff line numberDiff line change
@@ -441,11 +441,6 @@ object View extends IterableFactory[View] {
441441
}
442442
override def isEmpty: Boolean = underlying.isEmpty && len <= 0
443443
}
444-
445-
// scalac generates a `readReplace` method to discard the deserialized state (see https://github.com/scala/bug/issues/10412).
446-
// This prevents it from serializing it in the first place:
447-
private[this] def writeObject(out: ObjectOutputStream): Unit = ()
448-
private[this] def readObject(in: ObjectInputStream): Unit = ()
449444
}
450445

451446
/** Explicit instantiation of the `View` trait to reduce class file size in subclasses. */

src/library/scala/collection/concurrent/TrieMap.scala

-5
Original file line numberDiff line numberDiff line change
@@ -1019,11 +1019,6 @@ object TrieMap extends MapFactory[TrieMap] {
10191019
class MangledHashing[K] extends Hashing[K] {
10201020
def hash(k: K)= scala.util.hashing.byteswap32(k.##)
10211021
}
1022-
1023-
// scalac generates a `readReplace` method to discard the deserialized state (see https://github.com/scala/bug/issues/10412).
1024-
// This prevents it from serializing it in the first place:
1025-
private[this] def writeObject(out: ObjectOutputStream): Unit = ()
1026-
private[this] def readObject(in: ObjectInputStream): Unit = ()
10271022
}
10281023

10291024

src/library/scala/collection/immutable/ArraySeq.scala

-5
Original file line numberDiff line numberDiff line change
@@ -423,9 +423,4 @@ object ArraySeq extends StrictOptimizedClassTagSeqFactory[ArraySeq] { self =>
423423
case _ => super.equals(that)
424424
}
425425
}
426-
427-
// scalac generates a `readReplace` method to discard the deserialized state (see https://github.com/scala/bug/issues/10412).
428-
// This prevents it from serializing it in the first place:
429-
private[this] def writeObject(out: ObjectOutputStream): Unit = ()
430-
private[this] def readObject(in: ObjectInputStream): Unit = ()
431426
}

src/library/scala/collection/immutable/BitSet.scala

-5
Original file line numberDiff line numberDiff line change
@@ -155,9 +155,4 @@ object BitSet extends SpecificIterableFactory[Int, BitSet] {
155155
private final class SerializationProxy(coll: BitSet) extends scala.collection.BitSet.SerializationProxy(coll) {
156156
protected[this] def readResolve(): Any = BitSet.fromBitMaskNoCopy(elems)
157157
}
158-
159-
// scalac generates a `readReplace` method to discard the deserialized state (see https://github.com/scala/bug/issues/10412).
160-
// This prevents it from serializing it in the first place:
161-
private[this] def writeObject(out: ObjectOutputStream): Unit = ()
162-
private[this] def readObject(in: ObjectInputStream): Unit = ()
163158
}

src/library/scala/collection/immutable/HashMap.scala

-5
Original file line numberDiff line numberDiff line change
@@ -1328,11 +1328,6 @@ object HashMap extends MapFactory[HashMap] {
13281328
}
13291329

13301330
def newBuilder[K, V]: Builder[(K, V), HashMap[K, V]] = new HashMapBuilder[K, V]
1331-
1332-
// scalac generates a `readReplace` method to discard the deserialized state (see https://github.com/scala/bug/issues/10412).
1333-
// This prevents it from serializing it in the first place:
1334-
private[this] def writeObject(out: ObjectOutputStream): Unit = ()
1335-
private[this] def readObject(in: ObjectInputStream): Unit = ()
13361331
}
13371332

13381333

src/library/scala/collection/immutable/HashSet.scala

-5
Original file line numberDiff line numberDiff line change
@@ -789,11 +789,6 @@ object HashSet extends IterableFactory[HashSet] {
789789
}
790790

791791
def newBuilder[A]: Builder[A, HashSet[A]] = new HashSetBuilder
792-
793-
// scalac generates a `readReplace` method to discard the deserialized state (see https://github.com/scala/bug/issues/10412).
794-
// This prevents it from serializing it in the first place:
795-
private[this] def writeObject(out: ObjectOutputStream): Unit = ()
796-
private[this] def readObject(in: ObjectInputStream): Unit = ()
797792
}
798793

799794
private[collection] final class HashSetBuilder[A] extends Builder[A, HashSet[A]] {

src/library/scala/collection/immutable/IntMap.scala

-5
Original file line numberDiff line numberDiff line change
@@ -104,11 +104,6 @@ object IntMap {
104104

105105
implicit def iterableFactory[V]: Factory[(Int, V), IntMap[V]] = toFactory(this)
106106
implicit def buildFromIntMap[V]: BuildFrom[IntMap[_], (Int, V), IntMap[V]] = toBuildFrom(this)
107-
108-
// scalac generates a `readReplace` method to discard the deserialized state (see https://github.com/scala/bug/issues/10412).
109-
// This prevents it from serializing it in the first place:
110-
private[this] def writeObject(out: ObjectOutputStream): Unit = ()
111-
private[this] def readObject(in: ObjectInputStream): Unit = ()
112107
}
113108

114109
// Iterator over a non-empty IntMap.

src/library/scala/collection/immutable/LazyList.scala

-5
Original file line numberDiff line numberDiff line change
@@ -869,11 +869,6 @@ object LazyList extends SeqFactory[LazyList] {
869869

870870
def newBuilder[A]: Builder[A, LazyList[A]] = ArrayBuffer.newBuilder[A].mapResult(array => from(array))
871871

872-
// scalac generates a `readReplace` method to discard the deserialized state (see https://github.com/scala/bug/issues/10412).
873-
// This prevents it from serializing it in the first place:
874-
private[this] def writeObject(out: ObjectOutputStream): Unit = ()
875-
private[this] def readObject(in: ObjectInputStream): Unit = ()
876-
877872
/** This serialization proxy is used for LazyLists which start with a sequence of evaluated cons cells.
878873
* The forced sequence is serialized in a compact, sequential format, followed by the unevaluated tail, which uses
879874
* standard Java serialization to store the complete structure of unevaluated thunks. This allows the serialization

src/library/scala/collection/immutable/List.scala

-5
Original file line numberDiff line numberDiff line change
@@ -618,9 +618,4 @@ object List extends StrictOptimizedSeqFactory[List] {
618618
def empty[A]: List[A] = Nil
619619

620620
private[collection] val partialNotApplied = new Function1[Any, Any] { def apply(x: Any): Any = this }
621-
622-
// scalac generates a `readReplace` method to discard the deserialized state (see https://github.com/scala/bug/issues/10412).
623-
// This prevents it from serializing it in the first place:
624-
private[this] def writeObject(out: ObjectOutputStream): Unit = ()
625-
private[this] def readObject(in: ObjectInputStream): Unit = ()
626621
}

src/library/scala/collection/immutable/ListMap.scala

-5
Original file line numberDiff line numberDiff line change
@@ -175,9 +175,4 @@ object ListMap extends MapFactory[ListMap] {
175175
new ImmutableBuilder[(K, V), ListMap[K, V]](empty) {
176176
def addOne(elem: (K, V)): this.type = { elems = elems + elem; this }
177177
}
178-
179-
// scalac generates a `readReplace` method to discard the deserialized state (see https://github.com/scala/bug/issues/10412).
180-
// This prevents it from serializing it in the first place:
181-
private[this] def writeObject(out: ObjectOutputStream): Unit = ()
182-
private[this] def readObject(in: ObjectInputStream): Unit = ()
183178
}

src/library/scala/collection/immutable/ListSet.scala

-5
Original file line numberDiff line numberDiff line change
@@ -138,9 +138,4 @@ object ListSet extends IterableFactory[ListSet] {
138138
new ImmutableBuilder[A, ListSet[A]](empty) {
139139
def addOne(elem: A): this.type = { elems = elems + elem; this }
140140
}
141-
142-
// scalac generates a `readReplace` method to discard the deserialized state (see https://github.com/scala/bug/issues/10412).
143-
// This prevents it from serializing it in the first place:
144-
private[this] def writeObject(out: ObjectOutputStream): Unit = ()
145-
private[this] def readObject(in: ObjectInputStream): Unit = ()
146141
}

src/library/scala/collection/immutable/LongMap.scala

-5
Original file line numberDiff line numberDiff line change
@@ -101,11 +101,6 @@ object LongMap {
101101

102102
implicit def iterableFactory[V]: Factory[(Long, V), LongMap[V]] = toFactory(this)
103103
implicit def buildFromLongMap[V]: BuildFrom[LongMap[_], (Long, V), LongMap[V]] = toBuildFrom(this)
104-
105-
// scalac generates a `readReplace` method to discard the deserialized state (see https://github.com/scala/bug/issues/10412).
106-
// This prevents it from serializing it in the first place:
107-
private[this] def writeObject(out: ObjectOutputStream): Unit = ()
108-
private[this] def readObject(in: ObjectInputStream): Unit = ()
109104
}
110105

111106
// Iterator over a non-empty LongMap.

src/library/scala/collection/immutable/Map.scala

-5
Original file line numberDiff line numberDiff line change
@@ -410,11 +410,6 @@ object Map extends MapFactory[Map] {
410410
private[immutable] def buildTo[V1 >: V](builder: HashMapBuilder[K, V1]): builder.type =
411411
builder.addOne(key1, value1).addOne(key2, value2).addOne(key3, value3).addOne(key4, value4)
412412
}
413-
414-
// scalac generates a `readReplace` method to discard the deserialized state (see https://github.com/scala/bug/issues/10412).
415-
// This prevents it from serializing it in the first place:
416-
private[this] def writeObject(out: ObjectOutputStream): Unit = ()
417-
private[this] def readObject(in: ObjectInputStream): Unit = ()
418413
}
419414

420415
/** Explicit instantiation of the `Map` trait to reduce class file size in subclasses. */

src/library/scala/collection/immutable/Queue.scala

-5
Original file line numberDiff line numberDiff line change
@@ -189,9 +189,4 @@ object Queue extends StrictOptimizedSeqFactory[Queue] {
189189
override def apply[A](xs: A*): Queue[A] = new Queue[A](Nil, xs.toList)
190190

191191
private object EmptyQueue extends Queue[Nothing](Nil, Nil) { }
192-
193-
// scalac generates a `readReplace` method to discard the deserialized state (see https://github.com/scala/bug/issues/10412).
194-
// This prevents it from serializing it in the first place:
195-
private[this] def writeObject(out: ObjectOutputStream): Unit = ()
196-
private[this] def readObject(in: ObjectInputStream): Unit = ()
197192
}

src/library/scala/collection/immutable/SeqMap.scala

-6
Original file line numberDiff line numberDiff line change
@@ -203,10 +203,4 @@ object SeqMap extends MapFactory[SeqMap] {
203203
f((key1, value1)); f((key2, value2)); f((key3, value3)); f((key4, value4))
204204
}
205205
}
206-
207-
// scalac generates a `readReplace` method to discard the deserialized state (see https://github.com/scala/bug/issues/10412).
208-
// This prevents it from serializing it in the first place:
209-
private[this] def writeObject(out: ObjectOutputStream): Unit = ()
210-
private[this] def readObject(in: ObjectInputStream): Unit = ()
211-
212206
}

src/library/scala/collection/immutable/Set.scala

-5
Original file line numberDiff line numberDiff line change
@@ -249,11 +249,6 @@ object Set extends IterableFactory[Set] {
249249
private[immutable] def buildTo(builder: Builder[A, Set[A]]): builder.type =
250250
builder.addOne(elem1).addOne(elem2).addOne(elem3).addOne(elem4)
251251
}
252-
253-
// scalac generates a `readReplace` method to discard the deserialized state (see https://github.com/scala/bug/issues/10412).
254-
// This prevents it from serializing it in the first place:
255-
private[this] def writeObject(out: ObjectOutputStream): Unit = ()
256-
private[this] def readObject(in: ObjectInputStream): Unit = ()
257252
}
258253

259254
/** Explicit instantiation of the `Set` trait to reduce class file size in subclasses. */

src/library/scala/collection/immutable/Stream.scala

-5
Original file line numberDiff line numberDiff line change
@@ -451,11 +451,6 @@ object Stream extends SeqFactory[Stream] {
451451

452452
def empty[A]: Stream[A] = Empty
453453

454-
// scalac generates a `readReplace` method to discard the deserialized state (see https://github.com/scala/bug/issues/10412).
455-
// This prevents it from serializing it in the first place:
456-
private[this] def writeObject(out: ObjectOutputStream): Unit = ()
457-
private[this] def readObject(in: ObjectInputStream): Unit = ()
458-
459454
override def newBuilder[A]: mutable.Builder[A, Stream[A]] = ArrayBuffer.newBuilder[A].mapResult(array => from(array))
460455

461456
private[immutable] def withFilter[A](l: Stream[A] @uncheckedVariance, p: A => Boolean): collection.WithFilter[A, Stream] =

src/library/scala/collection/immutable/Vector.scala

-5
Original file line numberDiff line numberDiff line change
@@ -51,11 +51,6 @@ object Vector extends StrictOptimizedSeqFactory[Vector] {
5151
// Constants governing concat strategy for performance
5252
private final val Log2ConcatFaster = 5
5353
private final val TinyAppendFaster = 2
54-
55-
// scalac generates a `readReplace` method to discard the deserialized state (see https://github.com/scala/bug/issues/10412).
56-
// This prevents it from serializing it in the first place:
57-
private[this] def writeObject(out: ObjectOutputStream): Unit = ()
58-
private[this] def readObject(in: ObjectInputStream): Unit = ()
5954
}
6055

6156
// in principle, most members should be private. however, access privileges must

src/library/scala/collection/mutable/AnyRefMap.scala

-5
Original file line numberDiff line numberDiff line change
@@ -565,9 +565,4 @@ object AnyRefMap {
565565

566566
implicit def iterableFactory[K <: AnyRef, V]: Factory[(K, V), AnyRefMap[K, V]] = toFactory[K, V](this)
567567
implicit def buildFromAnyRefMap[K <: AnyRef, V]: BuildFrom[AnyRefMap[_, _], (K, V), AnyRefMap[K, V]] = toBuildFrom(this)
568-
569-
// scalac generates a `readReplace` method to discard the deserialized state (see https://github.com/scala/bug/issues/10412).
570-
// This prevents it from serializing it in the first place:
571-
private[this] def writeObject(out: ObjectOutputStream): Unit = ()
572-
private[this] def readObject(in: ObjectInputStream): Unit = ()
573568
}

src/library/scala/collection/mutable/ArrayDeque.scala

-5
Original file line numberDiff line numberDiff line change
@@ -603,9 +603,4 @@ object ArrayDeque extends StrictOptimizedSeqFactory[ArrayDeque] {
603603
require(size >= 0, s"ArrayDeque too big - cannot allocate ArrayDeque of length $len")
604604
new Array[AnyRef](Math.max(size, DefaultInitialSize))
605605
}
606-
607-
// scalac generates a `readReplace` method to discard the deserialized state (see https://github.com/scala/bug/issues/10412).
608-
// This prevents it from serializing it in the first place:
609-
private[this] def writeObject(out: ObjectOutputStream): Unit = ()
610-
private[this] def readObject(in: ObjectInputStream): Unit = ()
611606
}

src/library/scala/collection/mutable/ArraySeq.scala

-5
Original file line numberDiff line numberDiff line change
@@ -304,9 +304,4 @@ object ArraySeq extends StrictOptimizedClassTagSeqFactory[ArraySeq] { self =>
304304
case _ => super.equals(that)
305305
}
306306
}
307-
308-
// scalac generates a `readReplace` method to discard the deserialized state (see https://github.com/scala/bug/issues/10412).
309-
// This prevents it from serializing it in the first place:
310-
private[this] def writeObject(out: ObjectOutputStream): Unit = ()
311-
private[this] def readObject(in: ObjectInputStream): Unit = ()
312307
}

src/library/scala/collection/mutable/BitSet.scala

-5
Original file line numberDiff line numberDiff line change
@@ -205,9 +205,4 @@ object BitSet extends SpecificIterableFactory[Int, BitSet] {
205205
private final class SerializationProxy(coll: BitSet) extends scala.collection.BitSet.SerializationProxy(coll) {
206206
protected[this] def readResolve(): Any = BitSet.fromBitMaskNoCopy(elems)
207207
}
208-
209-
// scalac generates a `readReplace` method to discard the deserialized state (see https://github.com/scala/bug/issues/10412).
210-
// This prevents it from serializing it in the first place:
211-
private[this] def writeObject(out: ObjectOutputStream): Unit = ()
212-
private[this] def readObject(in: ObjectInputStream): Unit = ()
213208
}

src/library/scala/collection/mutable/LongMap.scala

-5
Original file line numberDiff line numberDiff line change
@@ -646,9 +646,4 @@ object LongMap {
646646

647647
implicit def iterableFactory[V]: Factory[(Long, V), LongMap[V]] = toFactory(this)
648648
implicit def buildFromLongMap[V]: BuildFrom[LongMap[_], (Long, V), LongMap[V]] = toBuildFrom(this)
649-
650-
// scalac generates a `readReplace` method to discard the deserialized state (see https://github.com/scala/bug/issues/10412).
651-
// This prevents it from serializing it in the first place:
652-
private[this] def writeObject(out: ObjectOutputStream): Unit = ()
653-
private[this] def readObject(in: ObjectInputStream): Unit = ()
654649
}

src/library/scala/collection/mutable/UnrolledBuffer.scala

-5
Original file line numberDiff line numberDiff line change
@@ -422,9 +422,4 @@ object UnrolledBuffer extends StrictOptimizedClassTagSeqFactory[UnrolledBuffer]
422422
override def toString: String =
423423
array.take(size).mkString("Unrolled@%08x".format(System.identityHashCode(this)) + "[" + size + "/" + array.length + "](", ", ", ")") + " -> " + (if (next ne null) next.toString else "")
424424
}
425-
426-
// scalac generates a `readReplace` method to discard the deserialized state (see https://github.com/scala/bug/issues/10412).
427-
// This prevents it from serializing it in the first place:
428-
private[this] def writeObject(out: ObjectOutputStream): Unit = ()
429-
private[this] def readObject(in: ObjectInputStream): Unit = ()
430425
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
/*
2+
* Scala (https://www.scala-lang.org)
3+
*
4+
* Copyright EPFL and Lightbend, Inc.
5+
*
6+
* Licensed under Apache License 2.0
7+
* (http://www.apache.org/licenses/LICENSE-2.0).
8+
*
9+
* See the NOTICE file distributed with this work for
10+
* additional information regarding copyright ownership.
11+
*/
12+
13+
package scala.runtime;
14+
15+
import java.io.Serializable;
16+
import java.security.AccessController;
17+
import java.security.PrivilegedActionException;
18+
import java.security.PrivilegedExceptionAction;
19+
import java.util.HashSet;
20+
import java.util.Set;
21+
22+
/** A serialization proxy for singleton objects */
23+
public final class ModuleSerializationProxy implements Serializable {
24+
private static final long serialVersionUID = 1L;
25+
private final Class<?> moduleClass;
26+
private static final ClassValue<Object> instances = new ClassValue<Object>() {
27+
@Override
28+
protected Object computeValue(Class<?> type) {
29+
try {
30+
return AccessController.doPrivileged((PrivilegedExceptionAction<Object>) () -> type.getField("MODULE$").get(null));
31+
} catch (PrivilegedActionException e) {
32+
return rethrowRuntime(e.getCause());
33+
}
34+
}
35+
};
36+
37+
private static Object rethrowRuntime(Throwable e) {
38+
Throwable cause = e.getCause();
39+
if (cause instanceof RuntimeException) throw (RuntimeException) cause;
40+
else throw new RuntimeException(cause);
41+
}
42+
43+
public ModuleSerializationProxy(Class<?> moduleClass) {
44+
this.moduleClass = moduleClass;
45+
}
46+
47+
@SuppressWarnings("unused")
48+
private Object readResolve() {
49+
return instances.get(moduleClass);
50+
}
51+
}

src/reflect/scala/reflect/internal/Definitions.scala

+3
Original file line numberDiff line numberDiff line change
@@ -582,6 +582,9 @@ trait Definitions extends api.StandardDefinitions {
582582
lazy val NoneModule: ModuleSymbol = requiredModule[scala.None.type]
583583
lazy val SomeModule: ModuleSymbol = requiredModule[scala.Some.type]
584584

585+
// Serialization
586+
lazy val ModuleSerializationProxyClass: ClassSymbol = requiredClass[scala.runtime.ModuleSerializationProxy]
587+
585588
def compilerTypeFromTag(tt: ApiUniverse # WeakTypeTag[_]): Type = tt.in(rootMirror).tpe
586589
def compilerSymbolFromTag(tt: ApiUniverse # WeakTypeTag[_]): Symbol = tt.in(rootMirror).tpe.typeSymbol
587590

src/reflect/scala/reflect/internal/StdNames.scala

+1
Original file line numberDiff line numberDiff line change
@@ -839,6 +839,7 @@ trait StdNames {
839839
val values : NameType = "values"
840840
val wait_ : NameType = "wait"
841841
val withFilter: NameType = "withFilter"
842+
val writeReplace: NameType = "writeReplace"
842843
val xml: NameType = "xml"
843844
val zero: NameType = "zero"
844845

0 commit comments

Comments
 (0)