diff options
author | Jason Zaugg <jzaugg@gmail.com> | 2013-04-07 14:08:14 +0200 |
---|---|---|
committer | Jason Zaugg <jzaugg@gmail.com> | 2013-04-08 16:24:12 +0200 |
commit | d43f5ce5aa10e39ad05a385c31fc7178eba997c1 (patch) | |
tree | 2bb767924d2c9adb7811a970201df976de2e704d /src | |
parent | c57c4f8c6227cff8ff9c1392428f97f036a34f2c (diff) | |
download | scala-d43f5ce5aa10e39ad05a385c31fc7178eba997c1.tar.gz scala-d43f5ce5aa10e39ad05a385c31fc7178eba997c1.tar.bz2 scala-d43f5ce5aa10e39ad05a385c31fc7178eba997c1.zip |
SI-7335 Mandate that parents of Predef must be defined in Predef.scala
This avoids thorny issues of cyclic references and/or missing symbol errors
due to the way Predef is completed earlier than user classes, and due to the
addition of `import Predef._` to LowPriorityImplicits.scala. More details in
Lukas's comments in [2].
How did we bootstrap originally? Manually ordering source files,
either in the Ant Build [1], or later in Global [2]. But neither mechanism
remains in place (due, I suppose, to the difficulty in defending them
with a test case.) The reordering in Global was removed in [3].
After the change, we can compile the standard library without the
results of a prior compilation run on the classpath.
rm -rf target/locker/library/classes/scala && export LIB=build/pack/lib; java -Xmx1G -cp $LIB/scala-library.jar:$LIB/scala-reflect.jar:$LIB/scala-compiler.jar:$LIB/forkjoin.jar scala.tools.nsc.Main @args.txt
src/library/scala/SerialVersionUID.scala:15: warning: Implementation restriction: subclassing Classfile does not
make your annotation visible at runtime. If that is what
you want, you must write the annotation class in Java.
class SerialVersionUID(value: Long) extends scala.annotation.ClassfileAnnotation
^
warning: there were 75 deprecation warning(s); re-run with -deprecation for details
warning: there were 1 unchecked warning(s); re-run with -unchecked for details
warning: there were 5 feature warning(s); re-run with -feature for details
four warnings found
Where @args.txt contains:
-classpath
lib/forkjoin.jar:target/locker/library/classes
-sourcepath
src/library
-d
target/locker/library/classes
src/library/scala/Function3.scala
src/library/scala/Console.scala
<more of src/library/**, unsorted>
This change will break scala-virtualized, which will need to move
the contents of StandardEmbeddings.scala into Predef.scala.
[1] https://github.com/scala/scala/commit/c5441dc
[2] https://github.com/scala/scala/commit/e72f0c7
[3] https://github.com/scala/scala/pull/968
Diffstat (limited to 'src')
-rw-r--r-- | src/compiler/scala/tools/nsc/typechecker/Typers.scala | 9 | ||||
-rw-r--r-- | src/library/scala/LowPriorityImplicits.scala | 95 | ||||
-rw-r--r-- | src/library/scala/Predef.scala | 86 |
3 files changed, 95 insertions, 95 deletions
diff --git a/src/compiler/scala/tools/nsc/typechecker/Typers.scala b/src/compiler/scala/tools/nsc/typechecker/Typers.scala index 0be7192471..be59b4e86b 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Typers.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Typers.scala @@ -1856,6 +1856,9 @@ trait Typers extends Adaptations with Tags { } val impl2 = finishMethodSynthesis(impl1, clazz, context) + if (mdef.symbol == PredefModule) + ensurePredefParentsAreInSameSourceFile(impl2) + // SI-5954. On second compile of a companion class contained in a package object we end up // with some confusion of names which leads to having two symbols with the same name in the // same owner. Until that can be straightened out we will warn on companion objects in package @@ -1884,6 +1887,12 @@ trait Typers extends Adaptations with Tags { treeCopy.ModuleDef(mdef, typedMods, mdef.name, impl2) setType NoType } + + private def ensurePredefParentsAreInSameSourceFile(template: Template) = { + val parentSyms = template.parents map (_.symbol) filterNot (_ == AnyRefClass) + if (parentSyms exists (_.associatedFile != PredefModule.associatedFile)) + unit.error(template.pos, s"All parents of Predef must be defined in ${PredefModule.associatedFile}.") + } /** In order to override this in the TreeCheckers Typer so synthetics aren't re-added * all the time, it is exposed here the module/class typing methods go through it. * ...but it turns out it's also the ideal spot for namer/typer coordination for diff --git a/src/library/scala/LowPriorityImplicits.scala b/src/library/scala/LowPriorityImplicits.scala deleted file mode 100644 index 535f1ac699..0000000000 --- a/src/library/scala/LowPriorityImplicits.scala +++ /dev/null @@ -1,95 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2002-2013, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - -package scala - -import scala.collection.{ mutable, immutable, generic } -import mutable.WrappedArray -import immutable.WrappedString -import generic.CanBuildFrom -import scala.language.implicitConversions - -/** The `LowPriorityImplicits` class provides implicit values that - * are valid in all Scala compilation units without explicit qualification, - * but that are partially overridden by higher-priority conversions in object - * `Predef`. - * - * @author Martin Odersky - * @since 2.8 - */ -private[scala] abstract class LowPriorityImplicits { - /** We prefer the java.lang.* boxed types to these wrappers in - * any potential conflicts. Conflicts do exist because the wrappers - * need to implement ScalaNumber in order to have a symmetric equals - * method, but that implies implementing java.lang.Number as well. - * - * Note - these are inlined because they are value classes, but - * the call to xxxWrapper is not eliminated even though it does nothing. - * Even inlined, every call site does a no-op retrieval of Predef's MODULE$ - * because maybe loading Predef has side effects! - */ - @inline implicit def byteWrapper(x: Byte) = new runtime.RichByte(x) - @inline implicit def shortWrapper(x: Short) = new runtime.RichShort(x) - @inline implicit def intWrapper(x: Int) = new runtime.RichInt(x) - @inline implicit def charWrapper(c: Char) = new runtime.RichChar(c) - @inline implicit def longWrapper(x: Long) = new runtime.RichLong(x) - @inline implicit def floatWrapper(x: Float) = new runtime.RichFloat(x) - @inline implicit def doubleWrapper(x: Double) = new runtime.RichDouble(x) - @inline implicit def booleanWrapper(x: Boolean) = new runtime.RichBoolean(x) - - // These eight implicits exist solely to exclude Null from the domain of - // the boxed types, so that e.g. "var x: Int = null" is a compile time - // error rather than a delayed null pointer exception by way of the - // conversion from java.lang.Integer. If defined in the same file as - // Integer2int, they would have higher priority because Null is a subtype - // of Integer. We balance that out and create conflict by moving the - // definition into the superclass. - // - // Caution: do not adjust tightrope tension without safety goggles in place. - implicit def Byte2byteNullConflict(x: Null): Byte = sys.error("value error") - implicit def Short2shortNullConflict(x: Null): Short = sys.error("value error") - implicit def Character2charNullConflict(x: Null): Char = sys.error("value error") - implicit def Integer2intNullConflict(x: Null): Int = sys.error("value error") - implicit def Long2longNullConflict(x: Null): Long = sys.error("value error") - implicit def Float2floatNullConflict(x: Null): Float = sys.error("value error") - implicit def Double2doubleNullConflict(x: Null): Double = sys.error("value error") - implicit def Boolean2booleanNullConflict(x: Null): Boolean = sys.error("value error") - - implicit def genericWrapArray[T](xs: Array[T]): WrappedArray[T] = - if (xs eq null) null - else WrappedArray.make(xs) - - // Since the JVM thinks arrays are covariant, one 0-length Array[AnyRef] - // is as good as another for all T <: AnyRef. Instead of creating 100,000,000 - // unique ones by way of this implicit, let's share one. - implicit def wrapRefArray[T <: AnyRef](xs: Array[T]): WrappedArray[T] = { - if (xs eq null) null - else if (xs.length == 0) WrappedArray.empty[T] - else new WrappedArray.ofRef[T](xs) - } - - implicit def wrapIntArray(xs: Array[Int]): WrappedArray[Int] = if (xs ne null) new WrappedArray.ofInt(xs) else null - implicit def wrapDoubleArray(xs: Array[Double]): WrappedArray[Double] = if (xs ne null) new WrappedArray.ofDouble(xs) else null - implicit def wrapLongArray(xs: Array[Long]): WrappedArray[Long] = if (xs ne null) new WrappedArray.ofLong(xs) else null - implicit def wrapFloatArray(xs: Array[Float]): WrappedArray[Float] = if (xs ne null) new WrappedArray.ofFloat(xs) else null - implicit def wrapCharArray(xs: Array[Char]): WrappedArray[Char] = if (xs ne null) new WrappedArray.ofChar(xs) else null - implicit def wrapByteArray(xs: Array[Byte]): WrappedArray[Byte] = if (xs ne null) new WrappedArray.ofByte(xs) else null - implicit def wrapShortArray(xs: Array[Short]): WrappedArray[Short] = if (xs ne null) new WrappedArray.ofShort(xs) else null - implicit def wrapBooleanArray(xs: Array[Boolean]): WrappedArray[Boolean] = if (xs ne null) new WrappedArray.ofBoolean(xs) else null - implicit def wrapUnitArray(xs: Array[Unit]): WrappedArray[Unit] = if (xs ne null) new WrappedArray.ofUnit(xs) else null - - implicit def wrapString(s: String): WrappedString = if (s ne null) new WrappedString(s) else null - implicit def unwrapString(ws: WrappedString): String = if (ws ne null) ws.self else null - - implicit def fallbackStringCanBuildFrom[T]: CanBuildFrom[String, T, immutable.IndexedSeq[T]] = - new CanBuildFrom[String, T, immutable.IndexedSeq[T]] { - def apply(from: String) = immutable.IndexedSeq.newBuilder[T] - def apply() = immutable.IndexedSeq.newBuilder[T] - } -} - diff --git a/src/library/scala/Predef.scala b/src/library/scala/Predef.scala index 9a468489a2..511e5b842a 100644 --- a/src/library/scala/Predef.scala +++ b/src/library/scala/Predef.scala @@ -446,3 +446,89 @@ private[scala] trait DeprecatedPredef { @deprecated("Use the method in `scala.io.ReadStdin`", "2.11.0") def readf2(format: String) = ReadStdin.readf2(format) @deprecated("Use the method in `scala.io.ReadStdin`", "2.11.0") def readf3(format: String) = ReadStdin.readf3(format) } + +/** The `LowPriorityImplicits` class provides implicit values that +* are valid in all Scala compilation units without explicit qualification, +* but that are partially overridden by higher-priority conversions in object +* `Predef`. +* +* @author Martin Odersky +* @since 2.8 +*/ +// SI-7335 Parents of Predef are defined in the same compilation unit to avoid +// cyclic reference errors compiling the standard library *without* a previously +// compiled copy on the classpath. +private[scala] abstract class LowPriorityImplicits { + import mutable.WrappedArray + import immutable.WrappedString + + /** We prefer the java.lang.* boxed types to these wrappers in + * any potential conflicts. Conflicts do exist because the wrappers + * need to implement ScalaNumber in order to have a symmetric equals + * method, but that implies implementing java.lang.Number as well. + * + * Note - these are inlined because they are value classes, but + * the call to xxxWrapper is not eliminated even though it does nothing. + * Even inlined, every call site does a no-op retrieval of Predef's MODULE$ + * because maybe loading Predef has side effects! + */ + @inline implicit def byteWrapper(x: Byte) = new runtime.RichByte(x) + @inline implicit def shortWrapper(x: Short) = new runtime.RichShort(x) + @inline implicit def intWrapper(x: Int) = new runtime.RichInt(x) + @inline implicit def charWrapper(c: Char) = new runtime.RichChar(c) + @inline implicit def longWrapper(x: Long) = new runtime.RichLong(x) + @inline implicit def floatWrapper(x: Float) = new runtime.RichFloat(x) + @inline implicit def doubleWrapper(x: Double) = new runtime.RichDouble(x) + @inline implicit def booleanWrapper(x: Boolean) = new runtime.RichBoolean(x) + + // These eight implicits exist solely to exclude Null from the domain of + // the boxed types, so that e.g. "var x: Int = null" is a compile time + // error rather than a delayed null pointer exception by way of the + // conversion from java.lang.Integer. If defined in the same file as + // Integer2int, they would have higher priority because Null is a subtype + // of Integer. We balance that out and create conflict by moving the + // definition into the superclass. + // + // Caution: do not adjust tightrope tension without safety goggles in place. + implicit def Byte2byteNullConflict(x: Null): Byte = sys.error("value error") + implicit def Short2shortNullConflict(x: Null): Short = sys.error("value error") + implicit def Character2charNullConflict(x: Null): Char = sys.error("value error") + implicit def Integer2intNullConflict(x: Null): Int = sys.error("value error") + implicit def Long2longNullConflict(x: Null): Long = sys.error("value error") + implicit def Float2floatNullConflict(x: Null): Float = sys.error("value error") + implicit def Double2doubleNullConflict(x: Null): Double = sys.error("value error") + implicit def Boolean2booleanNullConflict(x: Null): Boolean = sys.error("value error") + + implicit def genericWrapArray[T](xs: Array[T]): WrappedArray[T] = + if (xs eq null) null + else WrappedArray.make(xs) + + // Since the JVM thinks arrays are covariant, one 0-length Array[AnyRef] + // is as good as another for all T <: AnyRef. Instead of creating 100,000,000 + // unique ones by way of this implicit, let's share one. + implicit def wrapRefArray[T <: AnyRef](xs: Array[T]): WrappedArray[T] = { + if (xs eq null) null + else if (xs.length == 0) WrappedArray.empty[T] + else new WrappedArray.ofRef[T](xs) + } + + implicit def wrapIntArray(xs: Array[Int]): WrappedArray[Int] = if (xs ne null) new WrappedArray.ofInt(xs) else null + implicit def wrapDoubleArray(xs: Array[Double]): WrappedArray[Double] = if (xs ne null) new WrappedArray.ofDouble(xs) else null + implicit def wrapLongArray(xs: Array[Long]): WrappedArray[Long] = if (xs ne null) new WrappedArray.ofLong(xs) else null + implicit def wrapFloatArray(xs: Array[Float]): WrappedArray[Float] = if (xs ne null) new WrappedArray.ofFloat(xs) else null + implicit def wrapCharArray(xs: Array[Char]): WrappedArray[Char] = if (xs ne null) new WrappedArray.ofChar(xs) else null + implicit def wrapByteArray(xs: Array[Byte]): WrappedArray[Byte] = if (xs ne null) new WrappedArray.ofByte(xs) else null + implicit def wrapShortArray(xs: Array[Short]): WrappedArray[Short] = if (xs ne null) new WrappedArray.ofShort(xs) else null + implicit def wrapBooleanArray(xs: Array[Boolean]): WrappedArray[Boolean] = if (xs ne null) new WrappedArray.ofBoolean(xs) else null + implicit def wrapUnitArray(xs: Array[Unit]): WrappedArray[Unit] = if (xs ne null) new WrappedArray.ofUnit(xs) else null + + implicit def wrapString(s: String): WrappedString = if (s ne null) new WrappedString(s) else null + implicit def unwrapString(ws: WrappedString): String = if (ws ne null) ws.self else null + + implicit def fallbackStringCanBuildFrom[T]: CanBuildFrom[String, T, immutable.IndexedSeq[T]] = + new CanBuildFrom[String, T, immutable.IndexedSeq[T]] { + def apply(from: String) = immutable.IndexedSeq.newBuilder[T] + def apply() = immutable.IndexedSeq.newBuilder[T] + } +} + |