From 0679da5440869d170df8a485db03532f9f49e04f Mon Sep 17 00:00:00 2001 From: Jason Zaugg Date: Tue, 29 Jan 2013 18:47:01 +0100 Subject: [backport] SI-6301 / SI-6572 specialization regressions Squashed commit of the following: commit a3680be29ccd5314c5d027d473b37940eaecd530 Author: Paul Phillips Date: Fri Aug 31 10:20:16 2012 -0700 Actual fix for SI-6301, specialized crasher. This means the workaround in the previous commit is no longer reached, but it should remain where it is as a much needed layer of robustness/useful error reporting. Conflicts: src/compiler/scala/tools/nsc/transform/SpecializeTypes.scala src/compiler/scala/tools/nsc/typechecker/Duplicators.scala commit f4c45ae204ce3ff3c16b19cab266d0b6515b6e0f Author: Paul Phillips Date: Fri Aug 31 10:49:24 2012 -0700 Rewrite of GenICode adapt. Started for debuggability, stayed for clarify/performance. Conflicts: src/compiler/scala/tools/nsc/backend/icode/GenICode.scala commit 74842f72a0af485e5def796f777f7003f969d75b Author: Paul Phillips Date: Fri Aug 31 08:45:34 2012 -0700 Workaround for SI-6301, @specialize crasher. SpecializeTypes is generating symbols with overloaded types which then proceed to crash in CleanUp or GenICode. Until I or someone works out why that is, take a look in case the overload is easily disambiguated by the argument list arity, in which case warn and proceed. --- .../tools/nsc/transform/SpecializeTypes.scala | 92 ++++++++++------------ 1 file changed, 41 insertions(+), 51 deletions(-) (limited to 'src/compiler/scala/tools/nsc/transform/SpecializeTypes.scala') diff --git a/src/compiler/scala/tools/nsc/transform/SpecializeTypes.scala b/src/compiler/scala/tools/nsc/transform/SpecializeTypes.scala index 64051b56ec..232148676c 100644 --- a/src/compiler/scala/tools/nsc/transform/SpecializeTypes.scala +++ b/src/compiler/scala/tools/nsc/transform/SpecializeTypes.scala @@ -178,6 +178,14 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers { case class Overload(sym: Symbol, env: TypeEnv) { override def toString = "specialized overload " + sym + " in " + env + def matchesSym(other: Symbol) = sym.tpe =:= other.tpe + def matchesEnv(env1: TypeEnv) = TypeEnv.includes(env, env1) + } + private def newOverload(method: Symbol, specializedMethod: Symbol, env: TypeEnv) = { + assert(!specializedMethod.isOverloaded, specializedMethod.defString) + val om = Overload(specializedMethod, env) + overloads(method) ::= om + om } /** Just to mark uncheckable */ @@ -289,10 +297,6 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers { } } - /** Return the specialized overload of sym in the given env, if any. */ - def overload(sym: Symbol, env: TypeEnv) = - overloads(sym).find(ov => TypeEnv.includes(ov.env, env)) - /** Return the specialized name of 'sym' in the given environment. It * guarantees the same result regardless of the map order by sorting * type variables alphabetically. @@ -628,7 +632,7 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers { info(om) = if (original.isDeferred) Forward(original) else Implementation(original) typeEnv(om) = env ++ typeEnv(m) // add the environment for any method tparams - overloads(specMember) ::= Overload(om, typeEnv(om)) + newOverload(specMember, om, typeEnv(om)) enterMember(om) } @@ -835,7 +839,7 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers { debuglog("%s expands to %s in %s".format(sym, specMember.name.decode, pp(env))) info(specMember) = NormalizedMember(sym) - overloads(sym) ::= Overload(specMember, env) + newOverload(sym, specMember, env) owner.info.decls.enter(specMember) specMember } @@ -877,9 +881,8 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers { if (wasSpec.nonEmpty) debuglog("specialized overload for %s in %s".format(specMember, pp(typeEnv(specMember)))) - overloads(sym) ::= Overload(specMember, spec) + newOverload(sym, specMember, spec) info(specMember) = SpecialOverload(sym, typeEnv(specMember)) - specMember } @@ -994,7 +997,7 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers { SpecialOverride(impl) } ) - overloads(overriding) ::= Overload(om, env) + newOverload(overriding, om, env) ifDebug(afterSpecialize(assert( overridden.owner.info.decl(om.name) != NoSymbol, "Could not find " + om.name + " in " + overridden.owner.info.decls)) @@ -1476,54 +1479,41 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers { } transformTypeApply - case Select(qual, name) => - def transformSelect = { - qual match { - case _: Super if illegalSpecializedInheritance(currentClass) => - val pos = tree.pos - debuglog(pos.source.file.name+":"+pos.line+": not specializing call to super inside illegal specialized inheritance class.") - debuglog(pos.lineContent) - tree - case _ => + case Select(Super(_, _), _) if illegalSpecializedInheritance(currentClass) => + val pos = tree.pos + debuglog(pos.source.file.name+":"+pos.line+": not specializing call to super inside illegal specialized inheritance class.\n" + pos.lineContent) + tree + case Select(qual, name) if name != nme.CONSTRUCTOR && specializedTypeVars(symbol.info).nonEmpty => debuglog("specializing Select %s [tree.tpe: %s]".format(symbol.defString, tree.tpe)) - - //log("!!! select " + tree + " -> " + symbol.info + " specTypeVars: " + specializedTypeVars(symbol.info)) - if (specializedTypeVars(symbol.info).nonEmpty && name != nme.CONSTRUCTOR) { - // log("!!! unifying " + (symbol, symbol.tpe) + " and " + (tree, tree.tpe)) - val env = unify(symbol.tpe, tree.tpe, emptyEnv, false) - // log("!!! found env: " + env + "; overloads: " + overloads(symbol)) - if (!env.isEmpty) { - // debuglog("checking for rerouting: " + tree + " with sym.tpe: " + symbol.tpe + " tree.tpe: " + tree.tpe + " env: " + env) - val specMember = overload(symbol, env) - if (specMember.isDefined) { - localTyper.typedOperator(atPos(tree.pos)(Select(transform(qual), specMember.get.sym.name))) - } - else { - val qual1 = transform(qual) + val env = unify(symbol.tpe, tree.tpe, emptyEnv, false) + if (env.isEmpty) super.transform(tree) + else { + val qual1 = transform(qual) + def reselect(member: Symbol) = { + val newSelect = atPos(tree.pos)(Select(qual1, member)) + if (member.isMethod) localTyper typedOperator newSelect + else localTyper typed newSelect + } + overloads(symbol) find (_ matchesEnv env) match { + case Some(Overload(member, _)) => reselect(member) + case _ => val specMember = qual1.tpe.member(specializedName(symbol, env)).suchThat(_.tpe matches subst(env, symbol.tpe)) - if (specMember ne NoSymbol) { - val tree1 = atPos(tree.pos)(Select(qual1, specMember)) - if (specMember.isMethod) - localTyper.typedOperator(tree1) - else - localTyper.typed(tree1) - } else + if (specMember ne NoSymbol) + reselect(specMember) + else treeCopy.Select(tree, qual1, name) - } - } else - super.transform(tree) - } else overloads(symbol).find(_.sym.info =:= symbol.info) match { - case Some(specMember) => - val qual1 = transform(qual) - debuglog("** routing " + tree + " to " + specMember.sym.fullName + " tree: " + Select(qual1, specMember.sym)) - localTyper.typedOperator(atPos(tree.pos)(Select(qual1, specMember.sym))) - case None => - super.transform(tree) - } + } } + case Select(qual, _) => + overloads(symbol) find (_ matchesSym symbol) match { + case Some(Overload(member, _)) => + val newTree = Select(transform(qual), member) + debuglog(s"** routing $tree to ${member.fullName} tree: $newTree") + localTyper.typedOperator(atPos(tree.pos)(newTree)) + case None => + super.transform(tree) } - transformSelect case PackageDef(pid, stats) => tree.symbol.info // make sure specializations have been performed -- cgit v1.2.3