summaryrefslogtreecommitdiff
path: root/src/compiler/scala/tools/nsc/typechecker/Typers.scala
diff options
context:
space:
mode:
authorMartin Odersky <odersky@gmail.com>2007-04-10 17:51:34 +0000
committerMartin Odersky <odersky@gmail.com>2007-04-10 17:51:34 +0000
commit28d40d21d0d29ff4c2f002090eeafd2c53817c64 (patch)
tree2db2d5a6bd0b8f611d2e73f6ba68415d155605c4 /src/compiler/scala/tools/nsc/typechecker/Typers.scala
parente732589d1d33d298b0df6d7e8dc6caaaf446d8f8 (diff)
downloadscala-28d40d21d0d29ff4c2f002090eeafd2c53817c64.tar.gz
scala-28d40d21d0d29ff4c2f002090eeafd2c53817c64.tar.bz2
scala-28d40d21d0d29ff4c2f002090eeafd2c53817c64.zip
more changes to support early inits.
Diffstat (limited to 'src/compiler/scala/tools/nsc/typechecker/Typers.scala')
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Typers.scala121
1 files changed, 74 insertions, 47 deletions
diff --git a/src/compiler/scala/tools/nsc/typechecker/Typers.scala b/src/compiler/scala/tools/nsc/typechecker/Typers.scala
index 60cfcac73f..326597fe99 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Typers.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Typers.scala
@@ -125,8 +125,7 @@ trait Typers requires Analyzer {
private def funMode(mode: int) = mode & (stickyModes | SCCmode) | FUNmode | POLYmode
private def argMode(fun: Tree, mode: int) =
- if (treeInfo.isSelfConstrCall(fun) || treeInfo.isSuperConstrCall(fun)) mode | SCCmode
- else mode
+ if (treeInfo.isSelfOrSuperConstrCall(fun)) mode | SCCmode else mode
private var xxx = 10;
class Typer(context0: Context) {
@@ -566,7 +565,7 @@ trait Typers requires Analyzer {
inferExprInstance(tree, tparams, pt)
adapt(tree, mode, pt)
} else {
- val typer1 = constrTyperIf(treeInfo.isSelfConstrCall(tree) || treeInfo.isSuperConstrCall(tree))
+ val typer1 = constrTyperIf(treeInfo.isSelfOrSuperConstrCall(tree))
typer1.typed(typer1.applyImplicitArgs(tree), mode, pt)
}
case mt: MethodType
@@ -738,19 +737,18 @@ trait Typers requires Analyzer {
if (member(qual, name) != NoSymbol) qual
else adaptToMember(qual, name, WildcardType)
- private def completeParentType(tpt: Tree, tparams: List[Symbol], enclTparams: List[Symbol], vparamss: List[List[ValDef]], superargs: List[Tree]): Type = {
+ private def typePrimaryConstrBody(cbody: Tree, tparams: List[Symbol], enclTparams: List[Symbol], vparamss: List[List[ValDef]]): Tree = {
enclTparams foreach context.scope.enter
namer.enterValueParams(context.owner, vparamss)
- val newTree = New(tpt)
- .setType(PolyType(tparams, appliedType(tpt.tpe, tparams map (.tpe))))
- val tree = typed(atPos(tpt.pos)(Apply(Select(newTree, nme.CONSTRUCTOR), superargs)))
- if (settings.debug.value) log("superconstr "+tree+" co = "+context.owner);//debug
- tree.tpe
+ typed(cbody)
}
- def parentTypes(templ: Template): List[Tree] = try {
+ def parentTypes(templ: Template): List[Tree] =
if (templ.parents.isEmpty) List()
- else {
+ else try {
+ val clazz = context.owner
+
+ // Normalize supertype and mixins so that supertype is always a class, not a trait.
var supertpt = typedTypeConstructor(templ.parents.head)
val firstParent = supertpt.tpe.symbol
var mixins = templ.parents.tail map typedType
@@ -762,43 +760,71 @@ trait Typers requires Analyzer {
supertpt = TypeTree(supertpt1.tpe.parents.head) setOriginal supertpt /* setPos supertpt.pos */
}
}
- val constr = treeInfo.firstConstructor(templ.body)
- if (supertpt.tpe.symbol != firstParent) {
- constr match {
- case DefDef(_, _, _, _, _, Block(List(Apply(_, superargs)), _)) =>
- if (!superargs.isEmpty)
- error(superargs.head.pos, firstParent+" is a trait; does not take constructor arguments")
- case _ =>
- }
+
+ // Determine
+ // - supertparams: Missing type parameters from supertype
+ // - supertpe: Given supertype, polymorphic in supertparams
+ val supertparams = if (supertpt.hasSymbol) supertpt.symbol.typeParams else List()
+ var supertpe = supertpt.tpe
+ if (!supertparams.isEmpty)
+ supertpe = PolyType(supertparams, appliedType(supertpe, supertparams map (.tpe)))
+
+ // A method to replace a super reference by a New in a supercall
+ def transformSuperCall(scall: Tree): Tree = (scall: @unchecked) match {
+ case Apply(fn, args) =>
+ copy.Apply(scall, transformSuperCall(fn), args)
+ case Select(Super(_, _), nme.CONSTRUCTOR) =>
+ copy.Select(
+ scall,
+ New(TypeTree(supertpe) setOriginal supertpt) setType supertpe setPos supertpt.pos,
+ nme.CONSTRUCTOR)
}
- if (supertpt.hasSymbol) {
- val tparams = supertpt.symbol.typeParams
- if (!tparams.isEmpty) {
- constr match {
- case EmptyTree =>
- error(supertpt.pos, "missing type arguments")
- case DefDef(_, _, _, vparamss, _, Block(List(Apply(_, superargs)), _)) =>
- val outercontext = context.outer
- supertpt = TypeTree(
- newTyper(makeNewScope(outercontext, constr, outercontext.owner))
- .completeParentType(
- supertpt,
- tparams,
- context.owner.unsafeTypeParams,
- vparamss map (.map(.duplicate)),
- superargs map (.duplicate))) setOriginal supertpt /* setPos supertpt.pos */
+
+ treeInfo.firstConstructor(templ.body) match {
+ case constr @ DefDef(_, _, _, vparamss, _, cbody @ Block(cstats, cunit)) =>
+ // Convert constructor body to block in environment and typecheck it
+ val cstats1: List[Tree] = cstats map (.duplicate)
+ val scall = if (cstats.isEmpty) EmptyTree else cstats.last
+ val cbody1 = scall match {
+ case Apply(_, _) =>
+ copy.Block(cbody, cstats1.init,
+ if (supertparams.isEmpty) cunit.duplicate
+ else transformSuperCall(scall))
+ case _ =>
+ copy.Block(cbody, cstats1, cunit.duplicate)
}
- }
+
+ val outercontext = context.outer
+ val cbody2 =
+ newTyper(makeNewScope(outercontext, constr, outercontext.owner))
+ .typePrimaryConstrBody(
+ cbody1, supertparams, clazz.unsafeTypeParams, vparamss map (.map(.duplicate)))
+
+ scall match {
+ case Apply(_, _) =>
+ val sarg = treeInfo.firstArgument(scall)
+ if (sarg != EmptyTree && supertpe.symbol != firstParent)
+ error(sarg.pos, firstParent+" is a trait; does not take constructor arguments")
+ if (!supertparams.isEmpty) supertpt = TypeTree(cbody2.tpe) setPos supertpt.pos
+ case _ =>
+ if (!supertparams.isEmpty) error(supertpt.pos, "missing type arguments")
+ }
+
+ List.map2(cstats1, treeInfo.preSuperFields(templ.body)) {
+ (ldef, gdef) => gdef.tpt.tpe = ldef.symbol.tpe
+ }
+ case _ =>
+ if (!supertparams.isEmpty) error(supertpt.pos, "missing type arguments")
}
- //Console.println("parents("+context.owner+") = "+supertpt :: mixins);//DEBUG
- List.mapConserve(supertpt :: mixins)(tpt => checkNoEscaping.privates(context.owner, tpt))
+
+ //Console.println("parents("+clazz") = "+supertpt :: mixins);//DEBUG
+ List.mapConserve(supertpt :: mixins)(tpt => checkNoEscaping.privates(clazz, tpt))
+ } catch {
+ case ex: TypeError =>
+ templ.tpe = null
+ reportTypeError(templ.pos, ex)
+ List(TypeTree(AnyRefClass.tpe))
}
- } catch {
- case ex: TypeError =>
- templ.tpe = null
- reportTypeError(templ.pos, ex)
- List(TypeTree(AnyRefClass.tpe))
- }
/** <p>Check that</p>
* <ul>
@@ -1339,10 +1365,11 @@ trait Typers requires Analyzer {
val localTyper = if (inBlock || (stat.isDef && !stat.isInstanceOf[LabelDef])) this
else newTyper(context.make(stat, exprOwner))
val result = checkDead(localTyper.typed(stat))
- if (treeInfo.isSelfConstrCall(stat) || treeInfo.isSuperConstrCall(stat))
+ if (treeInfo.isSelfOrSuperConstrCall(result)) {
context.inConstructorSuffix = true
- if (treeInfo.isSelfConstrCall(result) && result.symbol.pos >= exprOwner.enclMethod.pos)
- error(stat.pos, "called constructor's definition must precede calling constructor's definition")
+ if (treeInfo.isSelfConstrCall(result) && result.symbol.pos >= exprOwner.enclMethod.pos)
+ error(stat.pos, "called constructor's definition must precede calling constructor's definition")
+ }
result
}
}