diff options
-rw-r--r-- | lib/scala-compiler.jar.desired.sha1 | 2 | ||||
-rw-r--r-- | lib/scala-library-src.jar.desired.sha1 | 2 | ||||
-rw-r--r-- | lib/scala-library.jar.desired.sha1 | 2 | ||||
-rw-r--r-- | src/compiler/scala/tools/nsc/symtab/Definitions.scala | 1 | ||||
-rw-r--r-- | src/compiler/scala/tools/nsc/symtab/StdNames.scala | 4 | ||||
-rw-r--r-- | src/compiler/scala/tools/nsc/typechecker/Implicits.scala | 16 | ||||
-rw-r--r-- | src/compiler/scala/tools/nsc/typechecker/NamesDefaults.scala | 9 | ||||
-rw-r--r-- | src/compiler/scala/tools/nsc/typechecker/Typers.scala | 7 | ||||
-rw-r--r-- | src/library/scala/Predef.scala | 14 | ||||
-rw-r--r-- | test/files/neg/t0590.check | 5 |
10 files changed, 44 insertions, 18 deletions
diff --git a/lib/scala-compiler.jar.desired.sha1 b/lib/scala-compiler.jar.desired.sha1 index d3bbd16629..c125aae2c9 100644 --- a/lib/scala-compiler.jar.desired.sha1 +++ b/lib/scala-compiler.jar.desired.sha1 @@ -1 +1 @@ -972d3a12779e2cee43fc4f0085710f5a5f908479 ?scala-compiler.jar +8295eeb50cc3863605e6bf774fe06b464e416262 ?scala-compiler.jar diff --git a/lib/scala-library-src.jar.desired.sha1 b/lib/scala-library-src.jar.desired.sha1 index fac8ce0f24..d841bc5f28 100644 --- a/lib/scala-library-src.jar.desired.sha1 +++ b/lib/scala-library-src.jar.desired.sha1 @@ -1 +1 @@ -874a57a6804e974f66aa71014d6823fb88e6a12a ?scala-library-src.jar +77a930b105649c63bab0894fb44c633d3d915f58 ?scala-library-src.jar diff --git a/lib/scala-library.jar.desired.sha1 b/lib/scala-library.jar.desired.sha1 index b29dd577af..5c46624893 100644 --- a/lib/scala-library.jar.desired.sha1 +++ b/lib/scala-library.jar.desired.sha1 @@ -1 +1 @@ -065eca5c251e3750915ea6e8ea9409653a5e5490 ?scala-library.jar +bdfb4d0bc539178810d030d85089ed18eb89d403 ?scala-library.jar diff --git a/src/compiler/scala/tools/nsc/symtab/Definitions.scala b/src/compiler/scala/tools/nsc/symtab/Definitions.scala index 150cc9a12d..0f6fd6a944 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..885af91fdb 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") @@ -403,6 +402,9 @@ trait StdNames { // Stores Java annotations on parameters with RetentionPolicy.RUNTIME val RuntimeParamAnnotationATTR = newTermName("RuntimeVisibleParameterAnnotations") val ScalaATTR = newTermName("Scala") + + newTermName("utterweirdness") // (adriaan) removed newTermName("identity"), + // but if I don't give something in return, quick.lib (after newstarr) fails with "error: not found: value Nil" } def encode(str: String): Name = newTermName(NameTransformer.encode(str)) diff --git a/src/compiler/scala/tools/nsc/typechecker/Implicits.scala b/src/compiler/scala/tools/nsc/typechecker/Implicits.scala index dc00955e0b..bce3c4a5ee 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,17 @@ 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})) //@M this condition prevents no-op conversions, which are a problem (besides efficiency), + // one example is removeNames in NamesDefaults, which relies on the type checker failing in case of ambiguity between an assignment/named arg + ) 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/NamesDefaults.scala b/src/compiler/scala/tools/nsc/typechecker/NamesDefaults.scala index 482c53fac5..9d485cc730 100644 --- a/src/compiler/scala/tools/nsc/typechecker/NamesDefaults.scala +++ b/src/compiler/scala/tools/nsc/typechecker/NamesDefaults.scala @@ -390,9 +390,16 @@ trait NamesDefaults { self: Analyzer => argPos(index) = pos rhs case t: Tree => - errorTree(arg, "reference to "+ name +" is ambiguous; it is both, a parameter\n"+ + //@M was: errorTree(arg, ...) + // this throws an exception that's caught in `tryTypedApply` (as it uses `silent`) + // unfortunately, tryTypedApply recovers from the exception if you use errorTree(arg, ...) and conforms is allowed as a view (see tryImplicit in Implicits) + // because it tries to produce a new qualifier (if the old one was P, the new one will be conforms.apply(P)), and if that works, it pretends nothing happened + // so, to make sure tryTypedApply fails, pass EmptyTree instead + errorTree(EmptyTree, "reference to "+ name +" is ambiguous; it is both, a parameter\n"+ "name of the method and the name of a variable currently in scope.") } + //@M note that we don't get here when an ambiguity was detected (during the computation of res), + // as errorTree throws an exception typer.context.undetparams = udp res } diff --git a/src/compiler/scala/tools/nsc/typechecker/Typers.scala b/src/compiler/scala/tools/nsc/typechecker/Typers.scala index 745d1c8241..b609f1f24b 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Typers.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Typers.scala @@ -991,7 +991,12 @@ 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 adapt a top-level type that's the subject of an implicit search + // this happens because, if isView, typedImplicit tries to apply the "current" implicit value to + // a value that needs to be coerced, so we check whether the implicit value has an `apply` method + // (if we allow this, 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..aa718e1892 100644 --- a/src/library/scala/Predef.scala +++ b/src/library/scala/Predef.scala @@ -76,6 +76,10 @@ 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) + // @see `conforms` for the implicit version + def identity[A](x: A): A = x + // errors and asserts ------------------------------------------------- def error(message: String): Nothing = throw new RuntimeException(message) @@ -180,8 +184,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) implicit def intWrapper(x: Int) = new runtime.RichInt(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() } diff --git a/test/files/neg/t0590.check b/test/files/neg/t0590.check index b928c1cb76..a3ef70c6cd 100644 --- a/test/files/neg/t0590.check +++ b/test/files/neg/t0590.check @@ -1,5 +1,6 @@ -t0590.scala:2: error: diverging implicit expansion for type (Null(null)) => T -starting with method foo in object Test +t0590.scala:2: error: type mismatch; + found : Null(null) + required: T implicit def foo[T] : T = null ^ one error found |