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