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 + -
显示快捷键?