removed contractiveness requirement for implicit methods

git-svn-id: http://lampsvn.epfl.ch/svn-repos/scala/scala/trunk@14485 5e8d7ff9-d8ef-0310-90f0-a4852d11357a
This commit is contained in:
odersky 2008-04-02 16:42:48 +00:00
parent e1c6cfdb2b
commit f6f9dcf544
5 changed files with 56 additions and 21 deletions

View File

@ -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

View File

@ -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)

View File

@ -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

View File

@ -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 {

View File

@ -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