erasure.scala
来自「JAVA 语言的函数式编程扩展」· SCALA 代码 · 共 919 行 · 第 1/3 页
SCALA
919 行
opc.overridden.locationString + " " + opc.overridden.infosString) doubleDefError(opc.overriding, opc.overridden) } opc.next } }/* for (val bc <- root.info.baseClasses.tail; val other <- bc.info.decls.toList) { if (other.isTerm && !other.isConstructor && !(other hasFlag (PRIVATE | BRIDGE))) { for (val member <- root.info.nonPrivateMember(other.name).alternatives) { if (member != other && !(member hasFlag BRIDGE) && atPhase(phase.next)(member.tpe =:= other.tpe) && !atPhase(refchecksPhase.next)( root.thisType.memberType(member) matches root.thisType.memberType(other))) { if (settings.debug.value) log("" + member.locationString + " " + member.infosString + other.locationString + " " + other.infosString); doubleDefError(member, other) } } } }*/ /** <p> * Add bridge definitions to a template. This means: * </p> * <p> * If there is a concrete member <code>m</code> which overrides a * member in a base class of the template, and the erased types of * the two members differ, and the two members are not inherited or * defined by some parent class of the template, then a bridge from * the overridden member <code>m1</code> to the member <code>m0</code> * is added. The bridge has the erased type of <code>m1</code> and * forwards to <code>m0</code>. * </p> * <p> * No bridge is added if there is already a bridge to <code>m0</code> * with the erased type of <code>m1</code> in the template. * </p> */ private def bridgeDefs(owner: Symbol): List[Tree] = { //Console.println("computing bridges for " + owner)//DEBUG assert(phase == currentRun.erasurePhase) val site = owner.thisType val bridgesScope = newScope val bridgeTarget = new HashMap[Symbol, Symbol] var bridges: List[Tree] = List() val opc = atPhase(currentRun.explicitOuterPhase) { new overridingPairs.Cursor(owner) { override def parents: List[Type] = List(owner.info.parents.head) override def exclude(sym: Symbol): Boolean = !sym.isMethod || sym.hasFlag(PRIVATE) || super.exclude(sym) } } while (opc.hasNext) { val member = opc.overriding val other = opc.overridden //Console.println("bridge? " + member + ":" + member.tpe + member.locationString + " to " + other + ":" + other.tpe + other.locationString);//DEBUG if (!atPhase(currentRun.explicitOuterPhase)(member.isDeferred)) { val otpe = erasure(other.tpe); val bridgeNeeded = atPhase(phase.next) ( !(other.tpe =:= member.tpe) && !(deconstMap(other.tpe) =:= deconstMap(member.tpe)) && { var e = bridgesScope.lookupEntry(member.name) while ((e ne null) && !((e.sym.tpe =:= otpe) && (bridgeTarget(e.sym) == member))) e = bridgesScope.lookupNextEntry(e); (e eq null) } ); if (bridgeNeeded) { val bridge = other.cloneSymbolImpl(owner) .setPos(owner.pos) .setFlag(member.flags | BRIDGE) .resetFlag(ACCESSOR | DEFERRED | LAZY | lateDEFERRED) .setInfo(otpe); bridgeTarget(bridge) = member atPhase(phase.next) { owner.info.decls.enter(bridge) } bridgesScope enter bridge bridges = atPhase(phase.next) { atPos(bridge.pos) { val bridgeDef = DefDef(bridge, vparamss => member.tpe match { case MethodType(List(), ConstantType(c)) => Literal(c) case _ => (((Select(This(owner), member): Tree) /: vparamss) ((fun, vparams) => Apply(fun, vparams map Ident))) }); if (settings.debug.value) log("generating bridge from " + other + "(" + Flags.flagsToString(bridge.flags) + ")" + ":" + otpe + other.locationString + " to " + member + ":" + erasure(member.tpe) + member.locationString + " =\n " + bridgeDef); bridgeDef } } :: bridges; } } opc.next } bridges }/* for (val bc <- site.baseClasses.tail; val other <- bc.info.decls.toList) { if (other.isMethod && !other.isConstructor) { for (val member <- site.nonPrivateMember(other.name).alternatives) { if (member != other && !(member hasFlag DEFERRED) && (site.memberType(member) matches site.memberType(other)) && !(site.parents exists (p => (p.symbol isSubClass member.owner) && (p.symbol isSubClass other.owner)))) {... } }*/ def addBridges(stats: List[Tree], base: Symbol): List[Tree] = if (base.isTrait) stats else { val bridges = bridgeDefs(base) if (bridges.isEmpty) stats else stats ::: bridges } /** <p> * Transform tree at phase <code>erasure</code> before retyping it. * This entails the following: * </p> * <ul> * <li>Remove all type parameters in class and method definitions.</li> * <li>Remove all abstract and alias type definitions.</li> * <li> * Remove all type applications other than those involving a type * test or cast. * </li> * <li> * Remove all empty trees in statements and definitions in a * <code>PackageDef</code>. * </li> * <li>Check that there are no double definitions in a template.</li> * <li>Add bridge definitions to a template.</li> * <li> * Replace all types in type nodes and the <code>EmptyTree</code> * object by their erasure. Type nodes of type <code>Unit</code> * representing result types of methods are left alone. * </li> * <li> * Reset all other type attributes to <code>null</code>, thus * enforcing a retyping. * </li> * </ul> */ private val preTransformer = new Transformer { override def transform(tree: Tree): Tree = { if (tree.symbol == ArrayClass && !tree.isType) return tree val tree1 = tree match { case ClassDef(mods, name, tparams, impl) => if (settings.debug.value) log("defs of " + tree.symbol + " = " + tree.symbol.info.decls) copy.ClassDef(tree, mods, name, List(), impl) case DefDef(mods, name, tparams, vparamss, tpt, rhs) => copy.DefDef(tree, mods, name, List(), vparamss, tpt, rhs) case TypeDef(_, _, _, _) => EmptyTree case TypeApply(fun, args) if (fun.symbol.owner != AnyClass && fun.symbol != Object_asInstanceOf && fun.symbol != Object_isInstanceOf) => // leave all other type tests/type casts, remove all other type applications fun case Apply(fn, args) => def isGenericArray(tpe: Type): Boolean = erasure(tpe).typeSymbol == BoxedArrayClass if (fn.hasSymbol && fn.symbol.name == nme.arraycopy && fn.symbol.owner.name == nme.System.toTypeName && fn.symbol.owner.owner == JavaLangPackage.tpe.typeSymbol && args.length == 5 && (isGenericArray(args(0).tpe) || isGenericArray(args(2).tpe))) unit.warning(tree.pos, "System.arraycopy should be applied only to arrays with fixed element types;\n" + "use Array.copy instead") if (fn.symbol == Any_asInstanceOf || fn.symbol == Any_asInstanceOfErased) fn match { case TypeApply(Select(qual, _), List(targ)) => if (qual.tpe <:< targ.tpe) { atPos(tree.pos) { Typed(qual, TypeTree(targ.tpe)) } } else if (isNumericValueClass(qual.tpe.typeSymbol) && isNumericValueClass(targ.tpe.typeSymbol)) { // convert numeric type casts val cname = newTermName("to" + targ.tpe.typeSymbol.name) val csym = qual.tpe.member(cname) assert(csym != NoSymbol) atPos(tree.pos) { Apply(Select(qual, csym), List()) } } else tree } // todo: get rid of instanceOfErased // todo: also handle the case where the singleton type is buried in a compound else if (fn.symbol == Any_isInstanceOf || fn.symbol == Any_isInstanceOfErased) fn match { case TypeApply(sel @ Select(qual, name), List(targ)) => def mkIsInstanceOf(q: () => Tree)(tp: Type): Tree = Apply( TypeApply( Select(q(), Object_isInstanceOf) setPos sel.pos, List(TypeTree(tp) setPos targ.pos)) setPos fn.pos, List()) setPos tree.pos targ.tpe match { case SingleType(_, _) | ThisType(_) | SuperType(_, _) => val cmpOp = if (targ.tpe <:< AnyValClass.tpe) Any_equals else Object_eq atPos(tree.pos) { Apply(Select(qual, cmpOp), List(gen.mkAttributedQualifier(targ.tpe))) } case RefinedType(parents, decls) if (parents.length >= 2) => gen.evalOnce(qual, currentOwner, unit) { q => atPos(tree.pos) { parents map mkIsInstanceOf(q) reduceRight gen.mkAnd } } case _ => if (isSeqClass(targ.tpe.typeSymbol)) { atPos(tree.pos) { gen.evalOnce(qual, currentOwner, unit) { q => gen.mkOr( mkIsInstanceOf(q)(targ.tpe), atPos(tree.pos) { Apply(gen.mkAttributedRef(isArrayMethod), List(q())) }) } } } else tree } case _ => tree } else { def doDynamic(fn: Tree, qual: Tree): Tree = { if (fn.symbol.owner.isRefinementClass && fn.symbol.allOverriddenSymbols.isEmpty) ApplyDynamic(qual, args) setSymbol fn.symbol setPos tree.pos else tree } fn match { case Select(qual, _) => doDynamic(fn, qual) case TypeApply(fni@Select(qual, _), _) => doDynamic(fni, qual)// type parameters are irrelevant in case of dynamic call case _ => tree } } case Select(_, _) => if (tree.symbol.owner.isRefinementClass) { val overridden = tree.symbol.allOverriddenSymbols assert(!overridden.isEmpty, tree.symbol) tree.symbol = overridden.head } tree case Template(parents, self, body) => assert(!currentOwner.isImplClass) //Console.println("checking no dble defs " + tree)//DEBUG checkNoDoubleDefs(tree.symbol.owner) copy.Template(tree, parents, emptyValDef, addBridges(body, currentOwner)) case Match(selector, cases) => Match(Typed(selector, TypeTree(selector.tpe)), cases) case _ => tree } tree1 match { case EmptyTree | TypeTree() => tree1 setType erasure(tree1.tpe) case DefDef(mods, name, tparams, vparamss, tpt, rhs) => val result = super.transform(tree1) setType null tpt.tpe = erasure(tree.symbol.tpe).resultType result case _ => case class MyError(count : Int, ex : AssertionError) extends Error(ex.getMessage) try { super.transform(tree1) setType null } catch { case e @ MyError(n, ex) if n > 5 => throw e case MyError(n,ex) => Console.println(tree1) throw MyError(n + 1, ex) case ex : AssertionError => Console.println(tree1) throw MyError(0, ex) case ex => throw ex } } } } /** The main transform function: Pretransfom the tree, and then * re-type it at phase erasure.next. */ override def transform(tree: Tree): Tree = { val tree1 = preTransformer.transform(tree) atPhase(phase.next) { val tree2 = mixinTransformer.transform(tree1) if (settings.debug.value) log("tree after addinterfaces: \n" + tree2) newTyper(rootContext(unit, tree, true)).typed(tree2) } } }}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?