diff options
author | Aleksandar Pokopec <aleksandar.prokopec@epfl.ch> | 2011-02-16 09:43:03 +0000 |
---|---|---|
committer | Aleksandar Pokopec <aleksandar.prokopec@epfl.ch> | 2011-02-16 09:43:03 +0000 |
commit | 82d3f68819d0b19171e0ee440f59cea578533854 (patch) | |
tree | cb5ffbcc8c0882e5db2ea347ca8fda728db47ea2 /src | |
parent | b8a23b072fa0467650be1b56672e0b830d7c8f99 (diff) | |
download | scala-82d3f68819d0b19171e0ee440f59cea578533854.tar.gz scala-82d3f68819d0b19171e0ee440f59cea578533854.tar.bz2 scala-82d3f68819d0b19171e0ee440f59cea578533854.zip |
Made the unification algorithm for specializati...
Made the unification algorithm for specialization stricter when checking
if a specialized member symbol conforms to a type application.
In particular, whereas the `strict` unification mode is concerned: -
when both types are typerefs, unification checks whether they have the
same number of type args, then unifies type args - when both types are
method types, unification checks whether they have the same number of
arguments, then unifies argument types and return types
- when both types are poly types, -- || --
- when unifying multiple types, strict mode will ensure there aren't any overlapping mappings.
Let's hope this fixes and closes #4257.
Review by dragos.
Diffstat (limited to 'src')
-rw-r--r-- | src/compiler/scala/tools/nsc/transform/SpecializeTypes.scala | 19 |
1 files changed, 14 insertions, 5 deletions
diff --git a/src/compiler/scala/tools/nsc/transform/SpecializeTypes.scala b/src/compiler/scala/tools/nsc/transform/SpecializeTypes.scala index 04ea443313..632d3787c9 100644 --- a/src/compiler/scala/tools/nsc/transform/SpecializeTypes.scala +++ b/src/compiler/scala/tools/nsc/transform/SpecializeTypes.scala @@ -528,7 +528,7 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers { if (p.typeSymbol.isTrait) res += stp else if (currentRun.compiles(clazz)) reporter.warning(clazz.pos, p.typeSymbol + " must be a trait. Specialized version of " - + clazz + " will inherit generic " + p) + + clazz + " will inherit generic " + p) // TODO change to error } res.reverse.toList } @@ -960,6 +960,7 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers { else if (strict) throw UnifyError else env case (TypeRef(_, sym1, args1), TypeRef(_, sym2, args2)) => + if (strict && args1.length != args2.length) throw UnifyError val e = unify(args1, args2, env, strict) log("Unify - both type refs: " + tp1 + " and " + tp2 + " with args " + (args1, args2) + " - " + e) e @@ -970,6 +971,8 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers { log("Unify - method types: " + tp1 + " and " + tp2) unify(res1 :: (params1 map (_.tpe)), res2 :: (params2 map (_.tpe)), env, strict) case (PolyType(tparams1, res1), PolyType(tparams2, res2)) => + if (strict && tparams1.length != tparams2.length) throw UnifyError + log("Unify - poly types: " + tp1 + " and " + tp2) unify(res1, res2, env, strict) case (PolyType(_, res), other) => unify(res, other, env, strict) @@ -984,12 +987,17 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers { case _ => log("don't know how to unify %s [%s] with %s [%s]".format(tp1, tp1.getClass, tp2, tp2.getClass)) env - } + } } private def unify(tp1: List[Type], tp2: List[Type], env: TypeEnv, strict: Boolean): TypeEnv = tp1.zip(tp2).foldLeft(env) { (env, args) => - unify(args._1, args._2, env, strict) + if (!strict) unify(args._1, args._2, env, strict) + else { + val nenv = unify(args._1, args._2, emptyEnv, strict) + if (env.keySet.intersect(nenv.keySet) == emptyEnv) env ++ nenv + else throw UnifyError + } } private def specializedTypes(tps: List[Symbol]) = tps.filter(_.hasAnnotation(SpecializedClass)) @@ -1249,8 +1257,9 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers { log("[specSym] checking for rerouting: %s with \n\tsym.tpe: %s, \n\ttree.tpe: %s \n\tenv: %s \n\tname: %s" .format(tree, symbol.tpe, tree.tpe, env, specializedName(symbol, env))) if (!env.isEmpty) { // a method? - val specMember = qual.tpe.member(specializedName(symbol, env)) suchThat (s => doesConform(symbol, tree.tpe, s.tpe, env)) - log("[specSym] found: " + qual.tpe.member(specializedName(symbol, env)).tpe + ", instantiated as: " + tree.tpe) + val specCandidates = qual.tpe.member(specializedName(symbol, env)) + val specMember = specCandidates suchThat (s => doesConform(symbol, tree.tpe, s.tpe, env)) + log("[specSym] found: " + specCandidates.tpe + ", instantiated as: " + tree.tpe) log("[specSym] found specMember: " + specMember) if (specMember ne NoSymbol) if (TypeEnv.includes(typeEnv(specMember), env)) Some(specMember) |