summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Implicits.scala2
-rw-r--r--src/library/scala/Predef.scala23
-rw-r--r--src/reflect/scala/reflect/internal/Definitions.scala3
-rw-r--r--src/reflect/scala/reflect/internal/StdNames.scala2
-rw-r--r--src/scaladoc/scala/tools/nsc/doc/Settings.scala2
-rw-r--r--test/files/neg/logImplicits.check2
-rw-r--r--test/files/neg/predef-masking.scala2
-rw-r--r--test/files/neg/t8229.check4
-rw-r--r--test/files/neg/t8229.scala6
-rw-r--r--test/files/pos/t7788.scala8
-rw-r--r--test/scaladoc/run/diagrams-base.scala2
-rw-r--r--test/scaladoc/run/diagrams-filtering.scala2
12 files changed, 44 insertions, 14 deletions
diff --git a/src/compiler/scala/tools/nsc/typechecker/Implicits.scala b/src/compiler/scala/tools/nsc/typechecker/Implicits.scala
index 2bb874a8aa..c8ac3622e2 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Implicits.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Implicits.scala
@@ -807,7 +807,7 @@ trait Implicits {
private def isIneligible(info: ImplicitInfo) = (
info.isCyclicOrErroneous
- || isView && (info.sym eq Predef_conforms)
+ || isView && (info.sym eq Predef_conforms) // as an implicit conversion, Predef.$conforms is a no-op, so exclude it
|| (!context.macrosEnabled && info.sym.isTermMacro)
)
diff --git a/src/library/scala/Predef.scala b/src/library/scala/Predef.scala
index 50577e710e..faeb1dcbe2 100644
--- a/src/library/scala/Predef.scala
+++ b/src/library/scala/Predef.scala
@@ -264,8 +264,16 @@ object Predef extends LowPriorityImplicits with DeprecatedPredef {
@inline def formatted(fmtstr: String): String = fmtstr format self
}
- implicit final class StringAdd[A](private val self: A) extends AnyVal {
- def +(other: String) = String.valueOf(self) + other
+ // TODO: remove, only needed for binary compatibility of 2.11.0-RC1 with 2.11.0-M8
+ // note that `private[scala]` becomes `public` in bytecode
+ private[scala] final class StringAdd[A](private val self: A) extends AnyVal {
+ def +(other: String): String = String.valueOf(self) + other
+ }
+ private[scala] def StringAdd(x: Any): Any = new StringAdd(x)
+
+ // SI-8229 retaining the pre 2.11 name for source compatibility in shadowing this implicit
+ implicit final class any2stringadd[A](private val self: A) extends AnyVal {
+ def +(other: String): String = String.valueOf(self) + other
}
implicit final class RichException(private val self: Throwable) extends AnyVal {
@@ -374,9 +382,13 @@ object Predef extends LowPriorityImplicits with DeprecatedPredef {
@implicitNotFound(msg = "Cannot prove that ${From} <:< ${To}.")
sealed abstract class <:<[-From, +To] extends (From => To) with Serializable
private[this] final val singleton_<:< = new <:<[Any,Any] { def apply(x: Any): Any = x }
- // not in the <:< companion object because it is also
- // intended to subsume identity (which is no longer implicit)
- implicit def conforms[A]: A <:< A = singleton_<:<.asInstanceOf[A <:< A]
+ // The dollar prefix is to dodge accidental shadowing of this method
+ // by a user-defined method of the same name (SI-7788).
+ // The collections rely on this method.
+ implicit def $conforms[A]: A <:< A = singleton_<:<.asInstanceOf[A <:< A]
+
+ @deprecated("Use `implicitly[T <:< U]` or `identity` instead.", "2.11.0")
+ def conforms[A]: A <:< A = $conforms[A]
/** An instance of `A =:= B` witnesses that the types `A` and `B` are equal.
*
@@ -410,7 +422,6 @@ private[scala] trait DeprecatedPredef {
@deprecated("Use `ArrowAssoc`", "2.11.0") def any2ArrowAssoc[A](x: A): ArrowAssoc[A] = new ArrowAssoc(x)
@deprecated("Use `Ensuring`", "2.11.0") def any2Ensuring[A](x: A): Ensuring[A] = new Ensuring(x)
@deprecated("Use `StringFormat`", "2.11.0") def any2stringfmt(x: Any): StringFormat[Any] = new StringFormat(x)
- @deprecated("Use String interpolation", "2.11.0") def any2stringadd(x: Any): StringAdd[Any] = new StringAdd(x)
@deprecated("Use `Throwable` directly", "2.11.0") def exceptionWrapper(exc: Throwable) = new RichException(exc)
@deprecated("Use `SeqCharSequence`", "2.11.0") def seqToCharSequence(xs: scala.collection.IndexedSeq[Char]): CharSequence = new SeqCharSequence(xs)
@deprecated("Use `ArrayCharSequence`", "2.11.0") def arrayToCharSequence(xs: Array[Char]): CharSequence = new ArrayCharSequence(xs)
diff --git a/src/reflect/scala/reflect/internal/Definitions.scala b/src/reflect/scala/reflect/internal/Definitions.scala
index 2567abe51d..e1d760a87a 100644
--- a/src/reflect/scala/reflect/internal/Definitions.scala
+++ b/src/reflect/scala/reflect/internal/Definitions.scala
@@ -1432,7 +1432,8 @@ trait Definitions extends api.StandardDefinitions {
TypeTagClass -> materializeTypeTag
)
lazy val TagSymbols = TagMaterializers.keySet
- lazy val Predef_conforms = getMemberMethod(PredefModule, nme.conforms)
+ lazy val Predef_conforms = (getMemberIfDefined(PredefModule, nme.conforms)
+ orElse getMemberMethod(PredefModule, "conforms": TermName)) // TODO: predicate on -Xsource:2.10 (for now, needed for transition from M8 -> RC1)
lazy val Predef_classOf = getMemberMethod(PredefModule, nme.classOf)
lazy val Predef_implicitly = getMemberMethod(PredefModule, nme.implicitly)
lazy val Predef_wrapRefArray = getMemberMethod(PredefModule, nme.wrapRefArray)
diff --git a/src/reflect/scala/reflect/internal/StdNames.scala b/src/reflect/scala/reflect/internal/StdNames.scala
index 0c28c4fba4..f3467ff9f4 100644
--- a/src/reflect/scala/reflect/internal/StdNames.scala
+++ b/src/reflect/scala/reflect/internal/StdNames.scala
@@ -671,7 +671,7 @@ trait StdNames {
val classOf: NameType = "classOf"
val clone_ : NameType = "clone"
val collection: NameType = "collection"
- val conforms: NameType = "conforms"
+ val conforms: NameType = "$conforms" // dollar prefix to avoid accidental shadowing
val copy: NameType = "copy"
val create: NameType = "create"
val currentMirror: NameType = "currentMirror"
diff --git a/src/scaladoc/scala/tools/nsc/doc/Settings.scala b/src/scaladoc/scala/tools/nsc/doc/Settings.scala
index 5ea1443a19..67529f4178 100644
--- a/src/scaladoc/scala/tools/nsc/doc/Settings.scala
+++ b/src/scaladoc/scala/tools/nsc/doc/Settings.scala
@@ -298,7 +298,7 @@ class Settings(error: String => Unit, val printMsg: String => Unit = println(_))
/** Common conversion targets that affect any class in Scala */
val commonConversionTargets = Set(
"scala.Predef.StringFormat",
- "scala.Predef.StringAdd",
+ "scala.Predef.any2stringadd",
"scala.Predef.ArrowAssoc",
"scala.Predef.Ensuring",
"scala.collection.TraversableOnce.alternateImplicit")
diff --git a/test/files/neg/logImplicits.check b/test/files/neg/logImplicits.check
index 2265614962..270882b71a 100644
--- a/test/files/neg/logImplicits.check
+++ b/test/files/neg/logImplicits.check
@@ -10,7 +10,7 @@ logImplicits.scala:15: inferred view from String("abc") to Int = C.this.convert:
logImplicits.scala:19: applied implicit conversion from Int(1) to ?{def ->: ?} = implicit def ArrowAssoc[A](self: A): ArrowAssoc[A]
def f = (1 -> 2) + "c"
^
-logImplicits.scala:19: applied implicit conversion from (Int, Int) to ?{def +: ?} = implicit def StringAdd[A](self: A): StringAdd[A]
+logImplicits.scala:19: applied implicit conversion from (Int, Int) to ?{def +: ?} = implicit def any2stringadd[A](self: A): any2stringadd[A]
def f = (1 -> 2) + "c"
^
logImplicits.scala:22: error: class Un needs to be abstract, since method unimplemented is not defined
diff --git a/test/files/neg/predef-masking.scala b/test/files/neg/predef-masking.scala
index 6f4f4859d0..67b69aa169 100644
--- a/test/files/neg/predef-masking.scala
+++ b/test/files/neg/predef-masking.scala
@@ -1,5 +1,5 @@
// Testing predef masking
-import Predef.{ StringAdd => _, _ }
+import Predef.{ any2stringadd => _, _ }
object StringPlusConfusion {
// Would love to do something about this error message, but by the
diff --git a/test/files/neg/t8229.check b/test/files/neg/t8229.check
new file mode 100644
index 0000000000..cc504fa34e
--- /dev/null
+++ b/test/files/neg/t8229.check
@@ -0,0 +1,4 @@
+t8229.scala:5: error: value + is not a member of Object
+ o + ""
+ ^
+one error found
diff --git a/test/files/neg/t8229.scala b/test/files/neg/t8229.scala
new file mode 100644
index 0000000000..91966311e2
--- /dev/null
+++ b/test/files/neg/t8229.scala
@@ -0,0 +1,6 @@
+import Predef.{any2stringadd => _, _}
+
+object Test {
+ val o = new Object()
+ o + ""
+}
diff --git a/test/files/pos/t7788.scala b/test/files/pos/t7788.scala
new file mode 100644
index 0000000000..81eada962b
--- /dev/null
+++ b/test/files/pos/t7788.scala
@@ -0,0 +1,8 @@
+class Test {
+ // Predef used to define a method `conforms` to produce the implicit evidence below
+ // all this does is ensure we don't rename Predef.$conforms back to conforms when $ goes out of fashion
+ // or that there is some other way of generating the implicit value that witnesses T => U for T <: U
+ def conforms(x: Int, y: Int) = x < y
+ def foo[A](implicit ev: Int => A) = ???
+ foo[Int]
+} \ No newline at end of file
diff --git a/test/scaladoc/run/diagrams-base.scala b/test/scaladoc/run/diagrams-base.scala
index b7aeed51d2..1e83a78b38 100644
--- a/test/scaladoc/run/diagrams-base.scala
+++ b/test/scaladoc/run/diagrams-base.scala
@@ -46,7 +46,7 @@ object Test extends ScaladocModelTest {
val (incoming, outgoing) = diag.edges.partition(!_._1.isThisNode)
assert(incoming.length == 5)
- assert(outgoing.head._2.length == 4)
+ assert(outgoing.head._2.length == 4, s"${outgoing.head._2} has length ${outgoing.head._2.length}, expecting 4")
val (outgoingSuperclass, outgoingImplicit) = outgoing.head._2.partition(_.isNormalNode)
assert(outgoingSuperclass.length == 3)
diff --git a/test/scaladoc/run/diagrams-filtering.scala b/test/scaladoc/run/diagrams-filtering.scala
index 54e3e9ac63..12b5f4caba 100644
--- a/test/scaladoc/run/diagrams-filtering.scala
+++ b/test/scaladoc/run/diagrams-filtering.scala
@@ -57,7 +57,7 @@ object Test extends ScaladocModelTest {
// Assert we have just 3 nodes and 2 edges
val A = base._trait("A")
val ADiag = A.inheritanceDiagram.get
- assert(ADiag.nodes.length == 3)
+ assert(ADiag.nodes.length == 3, s"${ADiag.nodes} has length ${ADiag.nodes.length}, expected 3")
assert(ADiag.edges.map(_._2.length).sum == 2)
// trait C