summaryrefslogtreecommitdiff
path: root/src/compiler/scala/tools/nsc/typechecker/SyntheticMethods.scala
diff options
context:
space:
mode:
authorPaul Phillips <paulp@improving.org>2011-08-04 19:56:48 +0000
committerPaul Phillips <paulp@improving.org>2011-08-04 19:56:48 +0000
commitc18878ab71d64b91adbfc3cff5778a0f340be520 (patch)
tree5d81c424a1b5fd8aa8e7662cbb9c204e0fdbef3c /src/compiler/scala/tools/nsc/typechecker/SyntheticMethods.scala
parente02eecbbadff2d5feccdfc81f8013e7433f10f4c (diff)
downloadscala-c18878ab71d64b91adbfc3cff5778a0f340be520.tar.gz
scala-c18878ab71d64b91adbfc3cff5778a0f340be520.tar.bz2
scala-c18878ab71d64b91adbfc3cff5778a0f340be520.zip
Cleanups in synthetic method generation, no rev...
Cleanups in synthetic method generation, no review.
Diffstat (limited to 'src/compiler/scala/tools/nsc/typechecker/SyntheticMethods.scala')
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/SyntheticMethods.scala115
1 files changed, 51 insertions, 64 deletions
diff --git a/src/compiler/scala/tools/nsc/typechecker/SyntheticMethods.scala b/src/compiler/scala/tools/nsc/typechecker/SyntheticMethods.scala
index 95a86b25c8..4972c6295a 100644
--- a/src/compiler/scala/tools/nsc/typechecker/SyntheticMethods.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/SyntheticMethods.scala
@@ -35,17 +35,16 @@ trait SyntheticMethods extends ast.TreeDSL {
import global._ // the global environment
import definitions._ // standard classes and methods
- /** Add the synthetic methods to case classes. Note that a lot of the
- * complexity herein is a consequence of case classes inheriting from
- * case classes, which has been deprecated as of Sep 11 2009. So when
- * the opportunity for removal arises, this can be simplified.
+ /** Add the synthetic methods to case classes.
*/
def addSyntheticMethods(templ: Template, clazz: Symbol, context: Context): Template = {
+ import CODE._
+
val localTyper = newTyper(
if (reporter.hasErrors) context makeSilent false else context
)
def accessorTypes = clazz.caseFieldAccessors map (_.tpe.finalResultType)
- def accessorLub = global.weakLub(accessorTypes)._1
+ def accessorLub = global.weakLub(accessorTypes)._1
def hasOverridingImplementation(meth: Symbol): Boolean = {
val sym = clazz.info nonPrivateMember meth.name
@@ -61,10 +60,13 @@ trait SyntheticMethods extends ast.TreeDSL {
def newSyntheticMethod(name: Name, flags: Int, tpeCons: Symbol => Type) = {
val method = clazz.newMethod(clazz.pos.focus, name.toTermName) setFlag flags
- method setInfo tpeCons(method)
- clazz.info.decls.enter(method)
+
+ clazz.info.decls enter (method setInfo tpeCons(method))
}
+ def newTypedMethod(method: Symbol)(body: Tree): Tree =
+ localTyper typed { DEF(method) === body }
+
def makeNoArgConstructor(res: Type) =
(sym: Symbol) => MethodType(Nil, res)
def makeTypeConstructor(args: List[Type], res: Type) =
@@ -72,16 +74,12 @@ trait SyntheticMethods extends ast.TreeDSL {
def makeEqualityMethod(name: Name) =
syntheticMethod(name, 0, makeTypeConstructor(List(AnyClass.tpe), BooleanClass.tpe))
- import CODE._
+ def newNullaryMethod(name: TermName, tpe: Type, body: Tree) = {
+ val flags = if (clazz.tpe.member(name) != NoSymbol) OVERRIDE else 0
+ val method = clazz.newMethod(clazz.pos.focus, name) setFlag flags
- def newNullaryMethod(name: Name, tpe: Type, body: Tree) = {
- val flags = if (clazz.tpe.member(name.toTermName) != NoSymbol) OVERRIDE else 0
- val method = clazz.newMethod(clazz.pos.focus, name.toTermName) setFlag flags
-
- method setInfo NullaryMethodType(tpe)
- clazz.info.decls enter method
-
- typer typed (DEF(method) === body)
+ clazz.info.decls enter (method setInfo NullaryMethodType(tpe))
+ newTypedMethod(method)(body)
}
def productPrefixMethod = newNullaryMethod(nme.productPrefix, StringClass.tpe, LIT(clazz.name.decode))
def productArityMethod(arity: Int) = newNullaryMethod(nme.productArity, IntClass.tpe, LIT(arity))
@@ -111,11 +109,7 @@ trait SyntheticMethods extends ast.TreeDSL {
for ((sym, i) <- accs.zipWithIndex) yield
CASE(LIT(i)) ==> caseFn(sym)
- typer typed {
- DEF(method) === {
- arg MATCH { cases ::: default : _* }
- }
- }
+ newTypedMethod(method)(arg MATCH { cases ::: default : _* })
}
def productElementMethod(accs: List[Symbol]): Tree =
perElementMethod(accs, nme.productElement, AnyClass.tpe, x => Ident(x))
@@ -125,14 +119,12 @@ trait SyntheticMethods extends ast.TreeDSL {
def moduleToStringMethod: Tree = {
val method = syntheticMethod(nme.toString_, FINAL, makeNoArgConstructor(StringClass.tpe))
- typer typed { DEF(method) === LIT(clazz.name.decode) }
+ newTypedMethod(method)(LIT(clazz.name.decode))
}
def moduleHashCodeMethod: Tree = {
val method = syntheticMethod(nme.hashCode_, FINAL, makeNoArgConstructor(IntClass.tpe))
// The string being used as hashcode basis is also productPrefix.
- val code = clazz.name.decode.hashCode
-
- typer typed { DEF(method) === LIT(code) }
+ newTypedMethod(method)(LIT(clazz.name.decode.hashCode))
}
def forwardingMethod(name: Name, targetName: Name): Tree = {
@@ -140,34 +132,25 @@ trait SyntheticMethods extends ast.TreeDSL {
val paramtypes = target.tpe.paramTypes drop 1
val method = syntheticMethod(name, 0, makeTypeConstructor(paramtypes, target.tpe.resultType))
- typer typed {
- DEF(method) === {
- Apply(REF(target), This(clazz) :: (method ARGNAMES))
- }
- }
+ newTypedMethod(method)(Apply(REF(target), This(clazz) :: (method ARGNAMES)))
}
/** The equality method for case modules:
- * def equals(that: Any) = this eq that
+ * def equals(that: Any) = this eq that
*/
def equalsModuleMethod: Tree = {
val method = makeEqualityMethod(nme.equals_)
- val that = method ARG 0
- localTyper typed {
- DEF(method) === (This(clazz) ANY_EQ that)
- }
+ newTypedMethod(method)(This(clazz) ANY_EQ (method ARG 0))
}
- /** The canEqual method for case classes. Note that if we spot
- * a user-supplied equals implementation, we simply return true
- * so as not to interfere.
+ /** The canEqual method for case classes.
+ * def canEqual(that: Any) = that.isInstanceOf[This]
*/
def canEqualMethod: Tree = {
val method = makeEqualityMethod(nme.canEqual_)
- val that = method ARG 0
- typer typed (DEF(method) === (that IS_OBJ clazz.tpe))
+ newTypedMethod(method)((method ARG 0) IS_OBJ clazz.tpe)
}
/** The equality method for case classes. The argument is an Any,
@@ -190,12 +173,15 @@ trait SyntheticMethods extends ast.TreeDSL {
def makeTrees(acc: Symbol, cpt: Type): (Tree, Bind) = {
val varName = context.unit.freshTermName(acc.name + "$")
val isRepeated = isRepeatedParamType(cpt)
- val binding = if (isRepeated) Star(WILD.empty) else WILD.empty
+ val binding = Bind(
+ varName,
+ if (isRepeated) Star(WILD.empty) else WILD.empty
+ )
val eqMethod: Tree =
if (isRepeated) gen.mkRuntimeCall(nme.sameElements, List(Ident(varName), Ident(acc)))
else (Ident(varName) DOT nme.EQ)(Ident(acc))
- (eqMethod, Bind(varName, binding))
+ (eqMethod, binding)
}
// Creates list of parameters and a guard for each
@@ -206,40 +192,41 @@ trait SyntheticMethods extends ast.TreeDSL {
val that: Tree = (method ARG 0) AS clazz.tpe
val canEqualOther: Symbol = clazz.info nonPrivateMember nme.canEqual_
- typer typed {
- (that DOT canEqualOther)(This(clazz))
- }
+ typer typed { (that DOT canEqualOther)(This(clazz)) }
}
// Pattern is classname applied to parameters, and guards are all logical and-ed
- val (guard, pat) = (AND(guards: _*), Ident(clazz.name.toTermName) APPLY params)
-
- localTyper typed {
- DEF(method) === {
- (This(clazz) ANY_EQ that) OR (that MATCH(
- (CASE(pat) IF guard) ==> canEqualCheck() ,
- DEFAULT ==> FALSE
- ))
- }
+ val guard = AND(guards: _*)
+ // You might think this next line could be written
+ // val pat = Ident(clazz.companionModule) APPLY params
+ // However this prevents the compiler from bootstrapping,
+ // possibly due to a bug in how case classes are handled when
+ // read from classfiles as opposed to from source.
+ val pat = Ident(clazz.name.toTermName) APPLY params
+
+ newTypedMethod(method) {
+ (This(clazz) ANY_EQ that) OR (that MATCH(
+ (CASE(pat) IF guard) ==> canEqualCheck() ,
+ DEFAULT ==> FALSE
+ ))
}
}
def newAccessorMethod(tree: Tree): Tree = tree match {
case DefDef(_, _, _, _, _, rhs) =>
- var newAcc = tree.symbol.cloneSymbol
+ val newAcc = tree.symbol.cloneSymbol
newAcc.name = context.unit.freshTermName(tree.symbol.name + "$")
newAcc setFlag SYNTHETIC resetFlag (ACCESSOR | PARAMACCESSOR | PRIVATE | PROTECTED)
newAcc.privateWithin = NoSymbol
- newAcc = newAcc.owner.info.decls enter newAcc
- val result = typer typed { DEF(newAcc) === rhs.duplicate }
- log("new accessor method " + result)
- result
+ newAcc.owner.info.decls enter newAcc
+ logResult("new accessor method")(newTypedMethod(newAcc)(rhs.duplicate))
}
def needsReadResolve = (
- // only nested objects inside objects should get readResolve automatically
- // otherwise after de-serialization we get null references for lazy accessors (nested object -> lazy val + class def)
- // since the bitmap gets serialized but the moduleVar not
+ // Only nested objects inside objects should get readResolve automatically.
+ // Otherwise, after de-serialization we get null references for lazy accessors
+ // (nested object -> lazy val + class def) since the bitmap gets serialized but
+ // the moduleVar not.
clazz.isSerializable && (clazz.owner.isPackageClass || clazz.owner.isModuleClass)
)
@@ -320,13 +307,13 @@ trait SyntheticMethods extends ast.TreeDSL {
* the readResolve() method (see http://www.javaworld.com/javaworld/
* jw-04-2003/jw-0425-designpatterns_p.html)
*/
- if (!hasReadResolve && needsReadResolve){
+ if (!hasReadResolve && needsReadResolve) {
// PP: To this day I really can't figure out what this next comment is getting at:
// the !!! normally means there is something broken, but if so, what is it?
//
// !!! the synthetic method "readResolve" should be private, but then it is renamed !!!
val method = newSyntheticMethod(nme.readResolve, PROTECTED, makeNoArgConstructor(ObjectClass.tpe))
- ts += typer typed (DEF(method) === REF(clazz.sourceModule))
+ ts += newTypedMethod(method)(REF(clazz.sourceModule))
}
}
} catch {