refchecks.scala

来自「JAVA 语言的函数式编程扩展」· SCALA 代码 · 共 841 行 · 第 1/3 页

SCALA
841
字号
/* NSC -- new Scala compiler * Copyright 2005-2007 LAMP/EPFL * @author  Martin Odersky */// $Id: RefChecks.scala 14118 2008-02-23 21:56:27Z odersky $package scala.tools.nsc.typecheckerimport symtab.Flags._import collection.mutable.{HashSet, HashMap}import transform.InfoTransformimport scala.tools.nsc.util.{Position, NoPosition}/** <p> *    Post-attribution checking and transformation. *  </p> *  <p> *    This phase performs the following checks. *  </p> *  <ul> *    <li>All overrides conform to rules.</li> *    <li>All type arguments conform to bounds.</li> *    <li>All type variable uses conform to variance annotations.</li> *    <li>No forward reference to a term symbol extends beyond a value definition.</li> *  </ul> *  <p> *    It performs the following transformations. *  </p> *  <ul> *   <li>Local modules are replaced by variables and classes</li> *   <li>Calls to case factory methods are replaced by new's.</li> *   <li>Eliminate branches in a conditional if the condition is a constant</li> *  </ul> * *  @author  Martin Odersky *  @version 1.0 * *  @todo    Check whether we always check type parameter bounds. */abstract class RefChecks extends InfoTransform {  import global._  import definitions._  import typer.{typed, typedOperator, atOwner}  import posAssigner.atPos      /** the following two members override abstract members in Transform */  val phaseName: String = "refchecks"  override def phaseNewFlags: Long = lateMETHOD  def newTransformer(unit: CompilationUnit): RefCheckTransformer =    new RefCheckTransformer(unit)  override def changesBaseClasses = false  def transformInfo(sym: Symbol, tp: Type): Type =    if (sym.isModule && !sym.isStatic) {      sym setFlag (lateMETHOD | STABLE)      PolyType(List(), tp)    } else tp  class RefCheckTransformer(unit: CompilationUnit) extends Transformer {     var localTyper: analyzer.Typer = typer;    var currentApplication: Tree = EmptyTree// Override checking ------------------------------------------------------------    /** 1. Check all members of class `clazz' for overriding conditions.     *  That is for overriding member M and overridden member O:     *     *    1.1. M must have the same or stronger access privileges as O.     *    1.2. O must not be final.     *    1.3. O is deferred, or M has `override' modifier.     *    1.4. If O is an immutable value, then so is M.     *     // @M: LIFTED 1.5. Neither M nor O are a parameterized type alias     *    1.6. If O is a type alias, then M is an alias of O.      *    1.7. If O is an abstract type then      *       1.7.1 either M is an abstract type, and M's bounds are sharper than O's bounds.     *             or M is a type alias or class which conforms to O's bounds.     *       1.7.2 higher-order type arguments must respect bounds on higher-order type parameters  -- @M     *              (explicit bounds and those implied by variance annotations) -- @see checkKindBounds     *    1.8. If O and M are values, then      *    1.8.1  M's type is a subtype of O's type, or     *    1.8.2  M is of type []S, O is of type ()T and S <: T, or     *    1.8.3  M is of type ()S, O is of type []T and S <: T, or     *  2. Check that only abstract classes have deferred members     *  3. Check that concrete classes do not have deferred definitions     *     that are not implemented in a subclass.     *  4. Check that every member with an `override' modifier     *     overrides some other member.     */    private def checkAllOverrides(clazz: Symbol) {      val self = clazz.thisType       def infoString(sym: Symbol) = {        val sym1 = analyzer.underlying(sym)        sym1.toString() +         (if (sym1.owner == clazz) ""         else (sym1.locationString +                (if (sym1.isAliasType) ", which equals "+self.memberInfo(sym1)                else if (sym1.isAbstractType) " with bounds "+self.memberInfo(sym1)                else if (sym1.isTerm) " of type "+self.memberInfo(sym1)                else "")))      }      def overridesType(tp1: Type, tp2: Type): Boolean = (tp1.normalize, tp2.normalize) match {        case (MethodType(List(), rtp1), PolyType(List(), rtp2)) =>           rtp1 <:< rtp2        case (PolyType(List(), rtp1), MethodType(List(), rtp2)) =>           rtp1 <:< rtp2        case (TypeRef(_, sym, _),  _) if (sym.isModuleClass) =>           overridesType(PolyType(List(), tp1), tp2)        case _ =>           tp1 <:< tp2      }      /** Check that all conditions for overriding <code>other</code> by       *  <code>member</code> are met.       */      def checkOverride(clazz: Symbol, member: Symbol, other: Symbol) {        val pos = if (member.owner == clazz) member.pos else clazz.pos        def overrideError(msg: String) {          if (other.tpe != ErrorType && member.tpe != ErrorType)            unit.error(pos, "error overriding " + infoString(other) +                        ";\n " + infoString(member) + " " + msg);        }        def overrideTypeError() {          if (other.tpe != ErrorType && member.tpe != ErrorType) {            overrideError("has incompatible type "+analyzer.underlying(member).tpe.normalize)          }        }        def overrideAccessError() {          val pwString = if (other.privateWithin == NoSymbol) ""                          else other.privateWithin.name.toString          val otherAccess = flagsToString(other getFlag (PRIVATE | PROTECTED), pwString)          overrideError("has weaker access privileges; it should be "+                        (if (otherAccess == "") "public" else "at least "+otherAccess))        }        //Console.println(infoString(member) + " overrides " + infoString(other) + " in " + clazz);//DEBUG                // return if we already checked this combination elsewhere        if (member.owner != clazz) {          if ((member.owner isSubClass other.owner) && (member.isDeferred || !other.isDeferred)) {                //Console.println(infoString(member) + " shadows1 " + infoString(other) " in " + clazz);//DEBUG                return;               }          if (clazz.info.parents exists (parent =>            (parent.typeSymbol isSubClass other.owner) && (parent.typeSymbol isSubClass member.owner) &&            (member.isDeferred || !other.isDeferred))) {              //Console.println(infoString(member) + " shadows2 " + infoString(other) + " in " + clazz);//DEBUG                return;             }          if (clazz.info.parents forall (parent =>            (parent.typeSymbol isSubClass other.owner) == (parent.typeSymbol isSubClass member.owner))) {              //Console.println(infoString(member) + " shadows " + infoString(other) + " in " + clazz);//DEBUG              return;            }        }        if (member hasFlag PRIVATE) { // (1.1)          overrideError("has weaker access privileges; it should not be private")        }        val mb = member.accessBoundary(member.owner)        val ob = other.accessBoundary(member.owner)        if (mb != RootClass && mb != NoSymbol && // todo: change            (ob == RootClass || ob == NoSymbol || !ob.hasTransOwner(mb) ||             (other hasFlag PROTECTED) && !(member hasFlag PROTECTED))) {          overrideAccessError()        } else if (other hasFlag FINAL) { // (1.2)          overrideError("cannot override final member");        } else if (!other.isDeferred && !(member hasFlag (OVERRIDE | ABSOVERRIDE))) { // (1.3)          overrideError("needs `override' modifier");        } else if ((other hasFlag ABSOVERRIDE) && other.isIncompleteIn(clazz) && !(member hasFlag ABSOVERRIDE)) {          overrideError("needs `abstract override' modifiers")        } else if ((member hasFlag (OVERRIDE | ABSOVERRIDE)) &&                    (other hasFlag ACCESSOR) && other.accessed.isVariable && !other.accessed.hasFlag(LAZY)) {          overrideError("cannot override a mutable variable")        } else if (other.isStable && !member.isStable) { // (1.4)          overrideError("needs to be an immutable value")//        } else if (other.isStable && !other.isDeferred && other.owner.isTrait && (member hasFlag OVERRIDE)) {//          overrideError("cannot override a value or variable definition in a trait " +//                        "\n (this is an implementation restriction)")        } else {          if (other.isAliasType) {              //if (!member.typeParams.isEmpty) // (1.5)  @MAT            //  overrideError("may not be parameterized");            //if (!other.typeParams.isEmpty) // (1.5)   @MAT            //  overrideError("may not override parameterized type");            // @M: substSym            if (!(self.memberType(member).substSym(member.typeParams, other.typeParams) =:= self.memberType(other))) // (1.6)              overrideTypeError();          } else if (other.isAbstractType) {            //if (!member.typeParams.isEmpty) // (1.7)  @MAT            //  overrideError("may not be parameterized");            var memberTp = self.memberType(member)            if (!(self.memberInfo(other).bounds containsType memberTp)) { // (1.7.1) {              overrideTypeError(); // todo: do an explaintypes with bounds here            }                        // check overriding (abstract type --> abstract type or abstract type --> concrete type member (a type alias))            // making an abstract type member concrete is like passing a type argument            val kindErrors = typer.infer.checkKindBounds(List(other), List(memberTp), self, member.owner) // (1.7.2)                       if(!kindErrors.isEmpty)              unit.error(member.pos,                 "The kind of "+member.keyString+" "+member.varianceString + member.nameString+                " does not conform to the expected kind of " + other.defString + other.locationString + "." +                kindErrors.toList.mkString("\n", ", ", ""))                         // check a type alias's RHS corresponds to its declaration            // this overlaps somewhat with validateVariance            if(member.isAliasType) {              val kindErrors = typer.infer.checkKindBounds(List(member), List(memberTp.normalize), self, member.owner)                         if(!kindErrors.isEmpty)                unit.error(member.pos,                   "The kind of the right-hand side "+memberTp.normalize+" of "+member.keyString+" "+                  member.varianceString + member.nameString+ " does not conform to its expected kind."+                  kindErrors.toList.mkString("\n", ", ", ""))             }          } else if (other.isTerm) {            if (!overridesType(self.memberInfo(member), self.memberInfo(other))) { // 8              overrideTypeError()              explainTypes(self.memberInfo(member), self.memberInfo(other))            }          }        }      }      val opc = new overridingPairs.Cursor(clazz)      while (opc.hasNext) {        //Console.println("overrides " + opc.overriding/* + ":" + opc.overriding.tpe*/ + opc.overriding.locationString + " " + opc.overridden/* + ":" + opc.overridden.tpe*/ + opc.overridden.locationString + opc.overridden.hasFlag(DEFERRED));//DEBUG        if (!opc.overridden.isClass) checkOverride(clazz, opc.overriding, opc.overridden);                opc.next      }      // 2. Check that only abstract classes have deferred members      if (clazz.isClass && !clazz.isTrait) {        def abstractClassError(mustBeMixin: Boolean, msg: String) {          unit.error(clazz.pos,            (if (clazz.isAnonymousClass || clazz.isModuleClass) "object creation impossible"             else if (mustBeMixin) clazz.toString() + " needs to be a mixin"             else clazz.toString() + " needs to be abstract") + ", since " + msg);          clazz.setFlag(ABSTRACT)        }        for (val member <- clazz.tpe.nonPrivateMembers)          if (member.isDeferred && !(clazz hasFlag ABSTRACT)) {            abstractClassError(              false, infoString(member) + " is not defined" + analyzer.varNotice(member))          } else if ((member hasFlag ABSOVERRIDE) && member.isIncompleteIn(clazz)) {            val other = member.superSymbol(clazz);            abstractClassError(true,              infoString(member) + " is marked `abstract' and `override'" +              (if (other != NoSymbol)                 " and overrides incomplete superclass member " + infoString(other)               else ""))          }        // 3. Check that concrete classes do not have deferred definitions        // that are not implemented in a subclass.        def checkNoAbstractDecls(bc: Symbol) {          for (val decl <- bc.info.decls.elements) {            if (decl.isDeferred) {              val impl = decl.matchingSymbol(clazz.thisType)              if (impl == NoSymbol || (decl.owner isSubClass impl.owner)) {                abstractClassError(false, "there is a deferred declaration of "+infoString(decl)+                                   " which is not implemented in a subclass"+analyzer.varNotice(decl))              }            }          }          val parents = bc.info.parents          if (!parents.isEmpty && parents.head.typeSymbol.hasFlag(ABSTRACT))             checkNoAbstractDecls(parents.head.typeSymbol)        }        if (!(clazz hasFlag ABSTRACT)) checkNoAbstractDecls(clazz)      }

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?