Permalink
Browse files

SI-7788 Avoid accidental shadowing of Predef.conforms

Rename `conforms` to `$conforms` and put in a minimal backstop: pos/t7788.scala

TODO: predicate the backwards compatibility shim for `Predef_conforms`
on `-Xsource:2.10`
  • Loading branch information...
1 parent bba0166 commit 4223bc2ddc497457c7dccd1b9b65e98244a9b4d1 @adriaanm adriaanm committed Feb 18, 2014
@@ -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)
)
@@ -382,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.
*
@@ -1429,7 +1429,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)
@@ -661,7 +661,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"
@@ -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]
+}

2 comments on commit 4223bc2

@huitseeker
Contributor

@adriaanm any news on the TODO for this one ?

@retronym
Member

It should work as is, IIUC. The TODO will tighten things up so that the compiler doesn't treat Predef.conforms specially in 2.11 mode, but that could only happen if you are using the old or a custom standard library.

Please sign in to comment.