summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorAdriaan Moors <adriaan.moors@epfl.ch>2009-08-20 15:39:12 +0000
committerAdriaan Moors <adriaan.moors@epfl.ch>2009-08-20 15:39:12 +0000
commitc54bca38b0cfe007e33c4db7dcc5cc7a32a83c1f (patch)
tree58f61413373230290f99b0c5956f740c31c75b2e /src
parent6a9d9f379a6208397f96f0dc6d5c53e8e4a9bf64 (diff)
downloadscala-c54bca38b0cfe007e33c4db7dcc5cc7a32a83c1f.tar.gz
scala-c54bca38b0cfe007e33c4db7dcc5cc7a32a83c1f.tar.bz2
scala-c54bca38b0cfe007e33c4db7dcc5cc7a32a83c1f.zip
replaced the implicit `identity` coercion by `c...
replaced the implicit `identity` coercion by `conforms`, which can be used to encode generalised constraints the introduction of `conforms` revealed a bug in adaptToMember, which was inferring views while already inferring one, which gave rise to diverging implicits. Predef.identity is no longer special as far as the compiler is concerned.
Diffstat (limited to 'src')
-rw-r--r--src/compiler/scala/tools/nsc/symtab/Definitions.scala1
-rw-r--r--src/compiler/scala/tools/nsc/symtab/StdNames.scala1
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Implicits.scala14
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Typers.scala5
-rw-r--r--src/library/scala/Predef.scala12
5 files changed, 22 insertions, 11 deletions
diff --git a/src/compiler/scala/tools/nsc/symtab/Definitions.scala b/src/compiler/scala/tools/nsc/symtab/Definitions.scala
index 60b30d8a00..a88603cf05 100644
--- a/src/compiler/scala/tools/nsc/symtab/Definitions.scala
+++ b/src/compiler/scala/tools/nsc/symtab/Definitions.scala
@@ -111,7 +111,6 @@ trait Definitions {
if (!ClassClass.unsafeTypeParams.isEmpty && !phase.erasedTypes)
appliedType(ClassClass.tpe, List(classType))
else ClassClass.tpe
- def Predef_identity = getMember(PredefModule, nme.identity)
def Predef_error = getMember(PredefModule, nme.error)
lazy val ConsoleModule: Symbol = getModule("scala.Console")
lazy val ScalaRunTimeModule: Symbol = getModule("scala.runtime.ScalaRunTime")
diff --git a/src/compiler/scala/tools/nsc/symtab/StdNames.scala b/src/compiler/scala/tools/nsc/symtab/StdNames.scala
index baeea7273a..4c05fe67ad 100644
--- a/src/compiler/scala/tools/nsc/symtab/StdNames.scala
+++ b/src/compiler/scala/tools/nsc/symtab/StdNames.scala
@@ -295,7 +295,6 @@ trait StdNames {
val hashCode_ = newTermName("hashCode")
val hasNext = newTermName("hasNext")
val head = newTermName("head")
- val identity = newTermName("identity")
val invoke_ = newTermName("invoke")
val isInstanceOf_ = newTermName("isInstanceOf")
val isDefinedAt = newTermName("isDefinedAt")
diff --git a/src/compiler/scala/tools/nsc/typechecker/Implicits.scala b/src/compiler/scala/tools/nsc/typechecker/Implicits.scala
index 6a6c3687e0..c23d29f159 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Implicits.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Implicits.scala
@@ -247,16 +247,17 @@ self: Analyzer =>
private def typedImplicit(info: ImplicitInfo): SearchResult =
context.openImplicits find (dominates(pt, _)) match {
case Some(pending) =>
- //println("Pending implicit "+pending+" dominates "+pt+"/"+undetParams)
+ // println("Pending implicit "+pending+" dominates "+pt+"/"+undetParams) //@MDEBUG
throw DivergentImplicit
SearchFailure
case None =>
try {
context.openImplicits = pt :: context.openImplicits
- //println(" "*context.openImplicits.length+"typed implicit "+info+" for "+pt)
+ // println(" "*context.openImplicits.length+"typed implicit "+info+" for "+pt) //@MDEBUG
typedImplicit0(info)
} catch {
case DivergentImplicit =>
+ // println("DivergentImplicit for pt:"+ pt +", open implicits:"+context.openImplicits) //@MDEBUG
if (context.openImplicits.tail.isEmpty) {
if (!(pt.isErroneous))
context.unit.error(
@@ -413,16 +414,15 @@ self: Analyzer =>
* This is the case if all of the following holds:
* - the info's type is not erroneous,
* - the info is not shadowed by another info with the same name,
- * - if the symbol is Predef.identity, then we are not looking for a view,
* - the result of typedImplicit is non-empty.
* @return A search result with an attributed tree containing the implicit if succeeded,
* SearchFailure if not.
*/
def tryImplicit(info: ImplicitInfo): SearchResult =
- if (!containsError(info.tpe) &&
- !(isLocal && shadowed.contains(info.name)) &&
- (!isView || info.sym != Predef_identity)) typedImplicit(info)
- else SearchFailure
+ if (containsError(info.tpe) ||
+ (isLocal && shadowed.contains(info.name)) // || (isView && (info.sym == Predef_identity || info.sym == Predef_conforms))
+ ) SearchFailure
+ else typedImplicit(info)
def appInfos(is: List[ImplicitInfo]): Map[ImplicitInfo, SearchResult] = {
var applicable = Map[ImplicitInfo, SearchResult]()
diff --git a/src/compiler/scala/tools/nsc/typechecker/Typers.scala b/src/compiler/scala/tools/nsc/typechecker/Typers.scala
index 745d1c8241..13a9d6e142 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Typers.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Typers.scala
@@ -991,7 +991,10 @@ trait Typers { self: Analyzer =>
if (qual.isTerm &&
((qual.symbol eq null) || !qual.symbol.isTerm || qual.symbol.isValue) &&
phase.id <= currentRun.typerPhase.id && !qtpe.isError && !tp.isError &&
- qtpe.typeSymbol != NullClass && qtpe.typeSymbol != NothingClass && qtpe != WildcardType) {
+ qtpe.typeSymbol != NullClass && qtpe.typeSymbol != NothingClass && qtpe != WildcardType &&
+ context.implicitsEnabled) { // don't try to convert a top-level type that's the subject of an implicit search
+ // (otherwise we get divergence, e.g., starting at `conforms` during ant quick.bin)
+ // note: implicit arguments are still inferred (this kind of "chaining" is allowed)
val coercion = inferView(qual, qtpe, name, tp)
if (coercion != EmptyTree)
typedQualifier(atPos(qual.pos)(Apply(coercion, List(qual))))
diff --git a/src/library/scala/Predef.scala b/src/library/scala/Predef.scala
index 565aa363e8..4932414457 100644
--- a/src/library/scala/Predef.scala
+++ b/src/library/scala/Predef.scala
@@ -76,6 +76,9 @@ object Predef {
val Map = collection.immutable.Map
val Set = collection.immutable.Set
+ // no longer a view: subsumed by `conforms` (which is less likely to give rise to ambiguities)
+ def identity[A](x: A): A = x
+
// errors and asserts -------------------------------------------------
def error(message: String): Nothing = throw new RuntimeException(message)
@@ -180,7 +183,6 @@ object Predef {
// views --------------------------------------------------------------
- implicit def identity[A](x: A): A = x
implicit def byteWrapper(x: Byte) = new runtime.RichByte(x)
implicit def shortWrapper(x: Short) = new runtime.RichShort(x)
@@ -249,5 +251,13 @@ object Predef {
override def toString: String = xs.mkString("")
}
+ // used, for example, in the encoding of generalized constraints
+ // we need a new type constructor `<:<` and evidence `conforms`, as
+ // reusing `Function2` and `identity` leads to ambiguities (any2stringadd is inferred)
+ // to constrain any abstract type T that's in scope in a method's argument list (not just the method's own type parameters)
+ // simply add an implicit argument of type `T <:< U`, where U is the required upper bound (for lower-bounds, use: `U <: T`)
+ sealed abstract class <:<[-From, +To] extends (From => To)
+ implicit def conforms[A]: A <:< A = new (A <:< A) {def apply(x: A) = x}
+
def currentThread = java.lang.Thread.currentThread()
}