summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMartin Odersky <odersky@gmail.com>2006-07-28 11:09:25 +0000
committerMartin Odersky <odersky@gmail.com>2006-07-28 11:09:25 +0000
commita3be6043783a91e1035847207831eb1305da78bb (patch)
tree9e9325761a54880d935ef78b47cb56866ed77979
parentcb62884e391c50f36849a71d96c816cecb4aea31 (diff)
downloadscala-a3be6043783a91e1035847207831eb1305da78bb.tar.gz
scala-a3be6043783a91e1035847207831eb1305da78bb.tar.bz2
scala-a3be6043783a91e1035847207831eb1305da78bb.zip
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Infer.scala43
1 files changed, 39 insertions, 4 deletions
diff --git a/src/compiler/scala/tools/nsc/typechecker/Infer.scala b/src/compiler/scala/tools/nsc/typechecker/Infer.scala
index 4ba14aa147..b2cc60b3be 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Infer.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Infer.scala
@@ -505,6 +505,37 @@ trait Infer requires Analyzer {
}
}
+ /** Is given type populated? */
+ def isPopulated(tp: Type) = tp match {
+ case RefinedType(parents, _) => intersectionIsPopulated(parents)
+ case _ => true
+ }
+
+ /** Is intersection of given types populated? That is,
+ * for all types tp1, tp2 in intersection
+ * for all common base classes bc of tp1 and tp2
+ * let bt1, bt2 be the base types of tp1, tp2 relative to class bc
+ * Then:
+ * bt1 and bt2 have the same prefix, and
+ * any correspondiong non-variant type arguments of bt1 and bt2 are the same
+ */
+ def intersectionIsPopulated(tps: List[Type]) =
+ tps.isEmpty || {
+ def isConsistent(tp1: Type, tp2: Type): boolean = Pair(tp1, tp2) match {
+ case Pair(TypeRef(pre1, sym1, args1), TypeRef(pre2, sym2, args2)) =>
+ assert(sym1 == sym2)
+ pre1 =:= pre2 &&
+ !(List.map3(args1, args2, sym1.typeParams)
+ ((arg1, arg2, tparam) => tparam.variance != 0 || arg1 =:= arg2) contains false)
+ }
+ tps.head.baseClasses forall { bc =>
+ tps.tail forall { tp =>
+ tp.closurePos(bc) < 0 ||
+ isConsistent(tps.head.baseType(bc), tp.baseType(bc))
+ }
+ }
+ }
+
/** Substitite free type variables `undetparams' of type constructor `tree' in pattern,
* given prototype `pt'.
*/
@@ -534,8 +565,9 @@ trait Infer requires Analyzer {
if (restpe.subst(undetparams, tvars) <:< pt) {
computeArgs
} else if (isFullyDefined(pt)) {
+
if (settings.debug.value) log("infer constr " + tree + ":" + restpe + ", pt = " + pt);
- val ptparams = freeTypeParams.collect(pt);
+ var ptparams = freeTypeParams.collect(pt);
if (settings.debug.value) log("free type params = " + ptparams);
val ptWithWildcards = pt.subst(ptparams, ptparams map (ptparam => WildcardType));
tvars = undetparams map freshVar;
@@ -544,14 +576,17 @@ trait Infer requires Analyzer {
restpe = skipImplicit(tree.tpe.resultType);
if (settings.debug.value) log("new tree = " + tree + ":" + restpe);
val ptvars = ptparams map freshVar;
- if (restpe <:< pt.subst(ptparams, ptvars)) {
+ val pt1 = pt.subst(ptparams, ptvars)
+ val isCompatible = if (restpe.symbol.hasFlag(FINAL)) restpe <:< pt1
+ else intersectionIsPopulated(List(restpe, pt1))
+ if (isCompatible) {
for (val tvar <- ptvars) {
val tparam = tvar.origin.symbol;
val Pair(loBounds, hiBounds) =
- if (tvar.constr.inst != NoType && isFullyDefined(tvar.constr.inst))
+ if (tvar.constr.inst != NoType && isFullyDefined(tvar.constr.inst))
Pair(List(tvar.constr.inst), List(tvar.constr.inst))
else
- Pair(tvar.constr.lobounds, tvar.constr.hibounds);
+ Pair(tvar.constr.lobounds, tvar.constr.hibounds)
if (!loBounds.isEmpty || !hiBounds.isEmpty) {
context.nextEnclosing(.tree.isInstanceOf[CaseDef]).pushTypeBounds(tparam);
tparam setInfo TypeBounds(