diff options
author | Adriaan Moors <adriaan.moors@epfl.ch> | 2009-08-20 15:39:12 +0000 |
---|---|---|
committer | Adriaan Moors <adriaan.moors@epfl.ch> | 2009-08-20 15:39:12 +0000 |
commit | c54bca38b0cfe007e33c4db7dcc5cc7a32a83c1f (patch) | |
tree | 58f61413373230290f99b0c5956f740c31c75b2e /src | |
parent | 6a9d9f379a6208397f96f0dc6d5c53e8e4a9bf64 (diff) | |
download | scala-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.scala | 1 | ||||
-rw-r--r-- | src/compiler/scala/tools/nsc/symtab/StdNames.scala | 1 | ||||
-rw-r--r-- | src/compiler/scala/tools/nsc/typechecker/Implicits.scala | 14 | ||||
-rw-r--r-- | src/compiler/scala/tools/nsc/typechecker/Typers.scala | 5 | ||||
-rw-r--r-- | src/library/scala/Predef.scala | 12 |
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() } |