diff options
author | Paul Phillips <paulp@improving.org> | 2011-09-19 15:48:23 +0000 |
---|---|---|
committer | Paul Phillips <paulp@improving.org> | 2011-09-19 15:48:23 +0000 |
commit | e21d9b0a3907ee59b4d05489ecaf0fbf6467e27f (patch) | |
tree | d5d614e57cf207a8c43755ba7abeccbcc122725e /src/compiler/scala/tools/nsc/typechecker/RefChecks.scala | |
parent | 5637b22d21ccc1abe70e16e87c1607cd3acb9b3c (diff) | |
download | scala-e21d9b0a3907ee59b4d05489ecaf0fbf6467e27f.tar.gz scala-e21d9b0a3907ee59b4d05489ecaf0fbf6467e27f.tar.bz2 scala-e21d9b0a3907ee59b4d05489ecaf0fbf6467e27f.zip |
Added tool for analyzing forwarder classes.
If you build and then run
tools/proxy-report <outdir>
you will be given files revealing interesting things like:
/** With respect to trait SetLike, trait SetProxyLike does NOT wrap:
*/
trait Unwrapped {
def +(elem1: A,elem2: A,elems: A*): This
def ++(elems: scala.collection.GenTraversableOnce[A]): This
def subsets(len: Int): Iterator[This]
def subsets: Iterator[This]
protected override def newBuilder: scala.collection.mutable.Builder[A,This]
protected override def parCombiner: scala.collection.parallel.Combiner[A,scala.collection.parallel.ParSet[A]]
}
Lots more possible here, for now I just want to get a backstop
against our worst transgressions (not just in the library -- look
at SimpleTypeProxy, if you dare!) I will inquire about the results
separately, so no review.
Diffstat (limited to 'src/compiler/scala/tools/nsc/typechecker/RefChecks.scala')
-rw-r--r-- | src/compiler/scala/tools/nsc/typechecker/RefChecks.scala | 56 |
1 files changed, 30 insertions, 26 deletions
diff --git a/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala b/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala index 8828889231..68cc6db2fe 100644 --- a/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala +++ b/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala @@ -82,6 +82,28 @@ abstract class RefChecks extends InfoTransform with reflect.internal.transform.R if (sym.hasAccessBoundary) "" + sym.privateWithin.name else "" ) + def overridesTypeInPrefix(tp1: Type, tp2: Type, prefix: Type): Boolean = (tp1.normalize, tp2.normalize) match { + case (MethodType(List(), rtp1), NullaryMethodType(rtp2)) => + rtp1 <:< rtp2 + case (NullaryMethodType(rtp1), MethodType(List(), rtp2)) => + rtp1 <:< rtp2 + case (TypeRef(_, sym, _), _) if sym.isModuleClass => + overridesTypeInPrefix(NullaryMethodType(tp1), tp2, prefix) + case _ => + def classBoundAsSeen(tp: Type) = tp.typeSymbol.classBound.asSeenFrom(prefix, tp.typeSymbol.owner) + + (tp1 <:< tp2) || ( // object override check + tp1.typeSymbol.isModuleClass && tp2.typeSymbol.isModuleClass && { + val cb1 = classBoundAsSeen(tp1) + val cb2 = classBoundAsSeen(tp2) + (cb1 <:< cb2) && { + log("Allowing %s to override %s because %s <:< %s".format(tp1, tp2, cb1, cb2)) + true + } + } + ) + } + class RefCheckTransformer(unit: CompilationUnit) extends Transformer { var localTyper: analyzer.Typer = typer; @@ -227,17 +249,6 @@ abstract class RefChecks extends InfoTransform with reflect.internal.transform.R } } - def isConformingObjectOverride(tp1: Type, tp2: Type) = { - tp1.typeSymbol.isModuleClass && tp2.typeSymbol.isModuleClass && { - val cb1 = classBoundAsSeen(tp1) - val cb2 = classBoundAsSeen(tp2) - - (cb1 <:< cb2) && { - log("Allowing %s to override %s because %s <:< %s".format(tp1, tp2, cb1, cb2)) - true - } - } - } def isAbstractTypeWithoutFBound(sym: Symbol) = // (part of DEVIRTUALIZE) sym.isAbstractType && !sym.isFBounded @@ -256,21 +267,12 @@ abstract class RefChecks extends InfoTransform with reflect.internal.transform.R else "") } - def overridesType(tp1: Type, tp2: Type): Boolean = (tp1.normalize, tp2.normalize) match { - case (MethodType(List(), rtp1), NullaryMethodType(rtp2)) => - rtp1 <:< rtp2 - case (NullaryMethodType(rtp1), MethodType(List(), rtp2)) => - rtp1 <:< rtp2 - case (TypeRef(_, sym, _), _) if sym.isModuleClass => - overridesType(NullaryMethodType(tp1), tp2) - case _ => - (tp1 <:< tp2) || isConformingObjectOverride(tp1, tp2) - } - /** Check that all conditions for overriding `other` by `member` * of class `clazz` are met. */ - def checkOverride(clazz: Symbol, member: Symbol, other: Symbol) { + def checkOverride(member: Symbol, other: Symbol) { + def memberTp = self.memberType(member) + def otherTp = self.memberType(other) def noErrorType = other.tpe != ErrorType && member.tpe != ErrorType def isRootOrNone(sym: Symbol) = sym == RootClass || sym == NoSymbol def objectOverrideErrorMsg = ( @@ -400,6 +402,8 @@ abstract class RefChecks extends InfoTransform with reflect.internal.transform.R } } + + def checkOverrideTypes() { if (other.isAliasType) { //if (!member.typeParams.isEmpty) (1.5) @MAT @@ -449,13 +453,13 @@ abstract class RefChecks extends InfoTransform with reflect.internal.transform.R other.cookJavaRawInfo() // #2454 val memberTp = self.memberType(member) val otherTp = self.memberType(other) - if (!overridesType(memberTp, otherTp)) { // 8 + if (!overridesTypeInPrefix(memberTp, otherTp, self)) { // 8 overrideTypeError() explainTypes(memberTp, otherTp) } if (member.isStable && !otherTp.isVolatile) { - if (memberTp.isVolatile) + if (memberTp.isVolatile) overrideError("has a volatile type; cannot override a member with non-volatile type") else memberTp.normalize.resultType match { case rt: RefinedType if !(rt =:= otherTp) && !(checkedCombinations contains rt.parents) => @@ -474,7 +478,7 @@ abstract class RefChecks extends InfoTransform with reflect.internal.transform.R val opc = new overridingPairs.Cursor(clazz) while (opc.hasNext) { //Console.println(opc.overriding/* + ":" + opc.overriding.tpe*/ + " in "+opc.overriding.fullName + " overrides " + opc.overridden/* + ":" + opc.overridden.tpe*/ + " in "+opc.overridden.fullName + "/"+ opc.overridden.hasFlag(DEFERRED));//debug - if (!opc.overridden.isClass) checkOverride(clazz, opc.overriding, opc.overridden); + if (!opc.overridden.isClass) checkOverride(opc.overriding, opc.overridden); opc.next } |