summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMartin Odersky <odersky@gmail.com>2008-04-02 16:42:48 +0000
committerMartin Odersky <odersky@gmail.com>2008-04-02 16:42:48 +0000
commit1258a12712ca48907e70c4e870571eff30f4bfbb (patch)
tree654bdcd292485429a62238cd489118ed6a1934fd
parentfd417cfa960542d72e54cafd44eff8941fff8f1e (diff)
downloadscala-1258a12712ca48907e70c4e870571eff30f4bfbb.tar.gz
scala-1258a12712ca48907e70c4e870571eff30f4bfbb.tar.bz2
scala-1258a12712ca48907e70c4e870571eff30f4bfbb.zip
removed contractiveness requirement for implici...
removed contractiveness requirement for implicit methods
-rw-r--r--src/compiler/scala/tools/nsc/symtab/Names.scala4
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Namers.scala6
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Typers.scala44
-rw-r--r--src/library/scala/Predef.scala16
-rw-r--r--test/files/neg/bug696.check7
5 files changed, 56 insertions, 21 deletions
diff --git a/src/compiler/scala/tools/nsc/symtab/Names.scala b/src/compiler/scala/tools/nsc/symtab/Names.scala
index 70da3a3cb5..83ba15d128 100644
--- a/src/compiler/scala/tools/nsc/symtab/Names.scala
+++ b/src/compiler/scala/tools/nsc/symtab/Names.scala
@@ -22,8 +22,8 @@ class Names {
private final val HASH_SIZE = 0x8000
private final val HASH_MASK = 0x7FFF
private final val NAME_SIZE = 0x20000
- private final val MAX_LEN = 255 // for longer names use a partial MD5 hash
- private final val PREFIX_LEN = 128 // the length of the prefix to keep unhashed
+ private final val MAX_LEN = 240 // for longer names use a partial MD5 hash
+ private final val PREFIX_LEN = 100 // the length of the prefix to keep unhashed
private final val SUFFIX_LEN = 64 // the length of the suffix to keep unhashed
final val nameDebug = false
diff --git a/src/compiler/scala/tools/nsc/typechecker/Namers.scala b/src/compiler/scala/tools/nsc/typechecker/Namers.scala
index b3538763d7..5ed868d779 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Namers.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Namers.scala
@@ -810,9 +810,9 @@ trait Namers { self: Analyzer =>
clazz.tpe
case DefDef(_, _, tparams, vparamss, tpt, rhs) =>
- val result =
- newNamer(context.makeNewScope(tree, sym)).methodSig(tparams, vparamss, tpt, rhs);
- checkContractive(sym, result)
+ //val result =
+ newNamer(context.makeNewScope(tree, sym)).methodSig(tparams, vparamss, tpt, rhs)
+ //checkContractive(sym, result)
case vdef @ ValDef(mods, _, tpt, rhs) =>
val typer1 = typer.constrTyperIf(sym.hasFlag(PARAM | PRESUPER) && sym.owner.isConstructor)
diff --git a/src/compiler/scala/tools/nsc/typechecker/Typers.scala b/src/compiler/scala/tools/nsc/typechecker/Typers.scala
index a43418f6bd..c34212cd8d 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Typers.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Typers.scala
@@ -134,6 +134,8 @@ trait Typers { self: Analyzer =>
private def argMode(fun: Tree, mode: Int) =
if (treeInfo.isSelfOrSuperConstrCall(fun)) mode | SCCmode else mode
+ private var pendingImplicits: List[Type] = List()
+
abstract class Typer(context0: Context) {
import context0.unit
@@ -3294,18 +3296,56 @@ trait Typers { self: Analyzer =>
case _ => tp.isError
}
+ private def dominates(dtor: Type, dted: Type): Boolean = {
+ def simplify(tp: Type): Type = tp match {
+ case RefinedType(parents, defs) => intersectionType(parents, tp.typeSymbol.owner)
+ case AnnotatedType(attribs, tp, selfsym) => tp
+ case _ => tp
+ }
+ def sum(xs: List[Int]) = (0 /: xs)(_ + _)
+ def complexity(tp: Type): Int = tp match {
+ case SingleType(pre, sym) => complexity(pre) + 1
+ case TypeRef(pre, sym, args) => complexity(pre) + sum(args map complexity) + 1
+ case TypeBounds(lo, hi) => complexity(lo) + complexity(hi)
+ case ClassInfoType(parents, defs, clazz) => sum(parents map complexity) + 1
+ case MethodType(paramtypes, result) => sum(paramtypes map complexity) + complexity(result) + 1
+ case PolyType(tparams, result) => sum(tparams map (_.info) map complexity) + complexity(result) + 1
+ case ExistentialType(tparams, result) => sum(tparams map (_.info) map complexity) + complexity(result) + 1
+ case _ => 1
+ }
+ val dtor1 = simplify(dtor)
+ val dted1 = simplify(dted)
+ (dtor1.typeSymbol == dted1.typeSymbol) &&
+ (dtor1 =:= dted1 || complexity(dtor1) > complexity(dted1))
+ }
+
/** Try to construct a typed tree from given implicit info with given
* expected type.
*
* @param pos Position for error reporting
* @param info The given implicit info describing the implicit definition
- * @param pt The expected type
+ * @param pt0 The unnormalized expected type
+ * @param pt The normalized expected type
* @param isLocal Is implicit definition visible without prefix?
* @return A typed tree if the implicit info can be made to conform
* to <code>pt</code>, EmptyTree otherwise.
* @pre <code>info.tpe</code> does not contain an error
*/
- private def typedImplicit(pos: Position, info: ImplicitInfo, pt0: Type, pt: Type, isLocal: Boolean): Tree = {
+ private def typedImplicit(pos: Position, info: ImplicitInfo, pt0: Type, pt: Type, isLocal: Boolean): Tree =
+ pendingImplicits find (dominates(pt, _)) match {
+ case Some(pending) =>
+ context.error(pos, "diverging implicit expansion for type "+pending)
+ EmptyTree
+ case None =>
+ try {
+ pendingImplicits = pt :: pendingImplicits
+ typedImplicit0(pos, info, pt0, pt, isLocal)
+ } finally {
+ pendingImplicits = pendingImplicits.tail
+ }
+ }
+
+ private def typedImplicit0(pos: Position, info: ImplicitInfo, pt0: Type, pt: Type, isLocal: Boolean): Tree = {
def isStable(tp: Type): Boolean = tp match {
case TypeRef(pre, sym, _) => sym.isPackageClass || sym.isModuleClass && isStable(pre)
case _ => tp.isStable
diff --git a/src/library/scala/Predef.scala b/src/library/scala/Predef.scala
index 6db07a6bd6..74409b1e4b 100644
--- a/src/library/scala/Predef.scala
+++ b/src/library/scala/Predef.scala
@@ -126,6 +126,14 @@ object Predef {
def unapply[A, B, C](x: Tuple3[A, B, C]): Option[Tuple3[A, B, C]] = Some(x)
}
+ class Ensuring[A](x: A) {
+ def ensuring(cond: Boolean): A = { assert(cond); x }
+ def ensuring(cond: Boolean, msg: Any): A = { assert(cond, msg); x }
+ def ensuring(cond: A => Boolean): A = { assert(cond(x)); x }
+ def ensuring(cond: A => Boolean, msg: Any): A = { assert(cond(x), msg); x }
+ }
+ implicit def any2Ensuring[A](x: A): Ensuring[A] = new Ensuring(x)
+
class ArrowAssoc[A](x: A) {
def -> [B](y: B): Tuple2[A, B] = Tuple2(x, y)
}
@@ -183,14 +191,6 @@ object Predef {
implicit def any2stringadd(x: Any) = new runtime.StringAdd(x)
- class Ensuring[A](x: A) {
- def ensuring(cond: Boolean): A = { assert(cond); x }
- def ensuring(cond: Boolean, msg: Any): A = { assert(cond, msg); x }
- def ensuring(cond: A => Boolean): A = { assert(cond(x)); x }
- def ensuring(cond: A => Boolean, msg: Any): A = { assert(cond(x), msg); x }
- }
- implicit def any2Ensuring[A](x: A): Ensuring[A] = new Ensuring(x)
-
implicit def exceptionWrapper(exc: Throwable) = new runtime.RichException(exc)
implicit def unit2ordered(x: Unit): Ordered[Unit] = new Ordered[Unit] with Proxy {
diff --git a/test/files/neg/bug696.check b/test/files/neg/bug696.check
index 2bc09820ed..7d9d2687b0 100644
--- a/test/files/neg/bug696.check
+++ b/test/files/neg/bug696.check
@@ -1,9 +1,4 @@
-bug696.scala:3: error: implicit method WithType is not contractive,
- because the implicit parameter type TypeUtil0.Type[S]
- is not strictly contained in the signature TypeUtil0.Type[S with T]
- implicit def WithType[S,T](implicit tpeS : Type[S], tpeT : Type[T]) : Type[S with T] = null
- ^
bug696.scala:4: error: no implicit argument matching parameter type TypeUtil0.Type[Any] was found.
as[Any](null);
^
-two errors found
+one error found