summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorMartin Odersky <odersky@gmail.com>2007-04-10 10:30:43 +0000
committerMartin Odersky <odersky@gmail.com>2007-04-10 10:30:43 +0000
commitc5861d824317784efb52b52a60d4194960218bb3 (patch)
treeafbbda330bc838b3406fadb7c3b5c5c2c80fa13c /src
parent1f2a73f36b7e3334b03ea8d321e8b9058289fa0e (diff)
downloadscala-c5861d824317784efb52b52a60d4194960218bb3.tar.gz
scala-c5861d824317784efb52b52a60d4194960218bb3.tar.bz2
scala-c5861d824317784efb52b52a60d4194960218bb3.zip
check for variables in pattern alternatives; ch...
check for variables in pattern alternatives; changes to enable presupercall initialization.
Diffstat (limited to 'src')
-rw-r--r--src/compiler/scala/tools/nsc/ast/TreeInfo.scala32
-rw-r--r--src/compiler/scala/tools/nsc/ast/Trees.scala25
-rw-r--r--src/compiler/scala/tools/nsc/ast/parser/Parsers.scala73
-rw-r--r--src/compiler/scala/tools/nsc/ast/parser/Scanners.scala36
-rw-r--r--src/compiler/scala/tools/nsc/ast/parser/Tokens.scala1
-rw-r--r--src/compiler/scala/tools/nsc/transform/AddInterfaces.scala17
-rw-r--r--src/compiler/scala/tools/nsc/transform/Constructors.scala3
-rw-r--r--src/compiler/scala/tools/nsc/transform/ExplicitOuter.scala8
-rw-r--r--src/compiler/scala/tools/nsc/transform/UnCurry.scala6
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Contexts.scala15
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Namers.scala13
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Typers.scala112
12 files changed, 141 insertions, 200 deletions
diff --git a/src/compiler/scala/tools/nsc/ast/TreeInfo.scala b/src/compiler/scala/tools/nsc/ast/TreeInfo.scala
index 89ad2c1ac9..e47183f146 100644
--- a/src/compiler/scala/tools/nsc/ast/TreeInfo.scala
+++ b/src/compiler/scala/tools/nsc/ast/TreeInfo.scala
@@ -120,6 +120,8 @@ abstract class TreeInfo {
def isSelfConstrCall(tree: Tree): boolean = tree match {
case Ident(nme.CONSTRUCTOR) =>
true
+ case Select(This(_), nme.CONSTRUCTOR) =>
+ true
case TypeApply(constr, _) =>
isSelfConstrCall(constr)
case Apply(constr, _) =>
@@ -148,21 +150,27 @@ abstract class TreeInfo {
/** The first constructor definitions in `stats' */
def firstConstructor(stats: List[Tree]): Tree = stats match {
case List() => EmptyTree
- case (constr @ DefDef(_, nme.CONSTRUCTOR, _, _, _, _)) :: _ => constr
+ case (constr @ DefDef(_, name, _, _, _, _)) :: _
+ if (name == nme.CONSTRUCTOR || name == nme.MIXIN_CONSTRUCTOR) => constr
case _ :: stats1 => firstConstructor(stats1)
}
-/*
- /** The super call that calls mixin `mix' in stats */
- def superCall(stats: List[Tree], mix: Name): Tree = stats match {
- case scall @ Apply(Select(Super(_, mix1), name), List()) :: _
- if ((name == nme.CONSTRUCTOR || name == nme.MIXIN_CONSTRUCTOR) && mix1 == mix) =>
- scall
- case _ :: stats1 =>
- superCall(stats1, name)
- case _ =>
- assert(false, "no supercall to " + mix + " in " + stats)
+
+ /** The reference to super in the body of a primary constructor */
+ def superRef(tree: Tree): Tree = tree match {
+ case Block(stats, _) if !stats.isEmpty => superRef(stats.last)
+ case Apply(sr, _) => sr
+ case _ => EmptyTree
}
-*/
+
+ /** The value definitions marked PRESUPER in this statement sequence */
+ def preSuperFields(stats: List[Tree]) = stats filter isPreSuper
+
+ def isPreSuper(tree: Tree) = tree match {
+ case ValDef(mods, _, _, _) => mods hasFlag PRESUPER
+ case _ => false
+ }
+
+
/** Is name a left-associative operator? */
def isLeftAssoc(operator: Name): boolean =
operator.length > 0 && operator(operator.length - 1) != ':';
diff --git a/src/compiler/scala/tools/nsc/ast/Trees.scala b/src/compiler/scala/tools/nsc/ast/Trees.scala
index b49018b377..c94ed6c94e 100644
--- a/src/compiler/scala/tools/nsc/ast/Trees.scala
+++ b/src/compiler/scala/tools/nsc/ast/Trees.scala
@@ -451,15 +451,22 @@ trait Trees requires Global {
if (inIDE && vd.symbol != NoSymbol)
ret.symbol = vd.symbol
ret
- }));
- if (vparamss1.isEmpty ||
- !vparamss1.head.isEmpty && (vparamss1.head.head.mods.flags & IMPLICIT) != 0)
- vparamss1 = List() :: vparamss1;
- val superRef: Tree = Select(Super(nme.EMPTY.toTypeName, nme.EMPTY.toTypeName), nme.CONSTRUCTOR)
- val superCall = posAssigner.atPos(parents.head.pos) { (superRef /: argss) (Apply) }
- val constr: Tree =
- DefDef(constrMods, nme.CONSTRUCTOR, List(), vparamss1, TypeTree(), superCall)
- Template(parents, List.flatten(vparamss) ::: constr :: body)
+ }))
+ val constrs =
+ if (constrMods hasFlag TRAIT) {
+ if (body forall treeInfo.isInterfaceMember) List()
+ else List(
+ DefDef(NoMods, nme.MIXIN_CONSTRUCTOR, List(), List(List()), TypeTree(), Block(List(), Literal(()))))
+ } else {
+ if (vparamss1.isEmpty ||
+ !vparamss1.head.isEmpty && (vparamss1.head.head.mods.flags & IMPLICIT) != 0)
+ vparamss1 = List() :: vparamss1;
+ val superRef: Tree = Select(Super(nme.EMPTY.toTypeName, nme.EMPTY.toTypeName), nme.CONSTRUCTOR)
+ val superCall = posAssigner.atPos(parents.head.pos) { (superRef /: argss) (Apply) }
+ List(
+ DefDef(constrMods, nme.CONSTRUCTOR, List(), vparamss1, TypeTree(), Block(List(superCall), Literal(()))))
+ }
+ Template(parents, List.flatten(vparamss) ::: constrs ::: body)
}
/** Block of expressions (semicolon separated expressions) */
diff --git a/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala b/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala
index b38ed20e1d..061aab47a9 100644
--- a/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala
+++ b/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala
@@ -1057,10 +1057,9 @@ trait Parsers requires SyntaxAnalyzer {
parents += annotType(false)
}
newLineOptWhenFollowedBy(LBRACE)
- val (self, stats, superpos, superargss) =
- if (in.token == LBRACE) templateBody()
- else (emptyValDef, List(), Position.NOPOS, List(List()))
- makeNew(parents.toList, self, stats, superArgs(superpos, argss.toList, superargss))
+ val (self, stats) = if (in.token == LBRACE) templateBody()
+ else (emptyValDef, List())
+ makeNew(parents.toList, self, stats, argss.toList)
}
canApply = false
case _ =>
@@ -1076,17 +1075,6 @@ trait Parsers requires SyntaxAnalyzer {
simpleExprRest(t, canApply)
}
- private def isEmpty(argss: List[List[Tree]]) = argss.head.isEmpty && argss.tail.isEmpty
-
- private def superArgs(pos: int, extargss: List[List[Tree]], superargss: List[List[Tree]]) = {
- var argss = extargss
- if (isEmpty(argss))
- argss = superargss
- else if (!isEmpty(superargss))
- syntaxError(pos, "super call arguments are specified twice; once here and once in a subsequent super call", false)
- argss
- }
-
def simpleExprRest(t: Tree, canApply: boolean): Tree = {
if (canApply) newLineOptWhenFollowedBy(LBRACE)
in.token match {
@@ -1907,7 +1895,7 @@ trait Parsers requires SyntaxAnalyzer {
* | ConstrBlock
*/
def constrExpr(vparamss: List[List[ValDef]]): Tree =
- if (in.token == LBRACE) constrBlock(vparamss) else selfInvocation(vparamss)
+ if (in.token == LBRACE) constrBlock(vparamss) else Block(List(selfInvocation(vparamss)), Literal())
/** SelfInvocation ::= this ArgumentExprs {ArgumentExprs}
*/
@@ -1932,7 +1920,7 @@ trait Parsers requires SyntaxAnalyzer {
val stats = if (isStatSep) { in.nextToken(); blockStatSeq(statlist) }
else statlist.toList
accept(RBRACE)
- makeBlock(stats)
+ Block(stats, Literal(()))
}
/** TypeDef ::= Id [TypeParamClause] `=' Type
@@ -1999,9 +1987,8 @@ trait Parsers requires SyntaxAnalyzer {
}
val constrAnnots = annotations()
val (constrMods, vparamss) =
- if (mods.hasFlag(Flags.TRAIT)) (NoMods, List())
- else (accessModifierOpt(),
- paramClauses(name, implicitClassViews, mods.hasFlag(Flags.CASE)))
+ if (mods.hasFlag(Flags.TRAIT)) (Modifiers(Flags.TRAIT), List())
+ else (accessModifierOpt(), paramClauses(name, implicitClassViews, mods.hasFlag(Flags.CASE)))
val thistpe = requiresTypeOpt()
val (self0, template) =
classTemplate(mods, name, constrMods withAnnotations constrAnnots, vparamss)
@@ -2072,34 +2059,21 @@ trait Parsers requires SyntaxAnalyzer {
}
val ps = parents.toList
newLineOptWhenFollowedBy(LBRACE)
- val (self, body, superpos, superargss) =
+ val (self, body) =
if (in.token == LBRACE) templateBody()
- else {
- acceptEmptyTemplateBody("`{' expected")
- (emptyValDef, List(), Position.NOPOS, List(List()))
- }
- val argumentss = superArgs(pos, argss.toList, superargss)
- val impl = atPos(pos) {
- if (mods.hasFlag(Flags.TRAIT)) {
- if (!isEmpty(argumentss))
- syntaxError(superpos, "traits cannot have supercall arguments", false)
- Template(ps, body)
- } else {
- Template(ps, constrMods, vparamss, argumentss, body)
- }
- }
- (self, impl)
+ else { acceptEmptyTemplateBody("`{' expected"); (emptyValDef, List()) }
+ (self, atPos(pos) { Template(ps, constrMods, vparamss, argss.toList, body) })
}
////////// TEMPLATES ////////////////////////////////////////////////////////////
/** TemplateBody ::= [nl] `{' TemplateStatSeq `}'
*/
- def templateBody(): (ValDef, List[Tree], int, List[List[Tree]]) = {
+ def templateBody(): (ValDef, List[Tree]) = {
accept(LBRACE)
- val result @ (self, stats, superpos, superargss) = templateStatSeq()
+ val result @ (self, stats) = templateStatSeq()
accept(RBRACE)
- if (stats.isEmpty) (self, List(EmptyTree), Position.NOPOS, superargss) else result
+ if (stats.isEmpty) (self, List(EmptyTree)) else result
}
/** Refinement ::= [nl] `{' RefineStat {semi RefineStat} `}'
@@ -2165,11 +2139,9 @@ trait Parsers requires SyntaxAnalyzer {
* | super ArgumentExprs {ArgumentExprs}
* |
*/
- def templateStatSeq(): (ValDef, List[Tree], int, List[List[Tree]]) = {
+ def templateStatSeq(): (ValDef, List[Tree]) = {
var self: ValDef = emptyValDef
- var stats = new ListBuffer[Tree]
- var superpos = Position.NOPOS
- val superargss = new ListBuffer[List[Tree]]
+ val stats = new ListBuffer[Tree]
if (isExprIntro) {
val first = expr(InTemplate)
if (in.token == ARROW) {
@@ -2189,25 +2161,12 @@ trait Parsers requires SyntaxAnalyzer {
} else if (isDefIntro || isModifier || in.token == LBRACKET /*todo: remove */ || in.token == AT) {
val annots = annotations()
stats ++ joinComment(defOrDcl(modifiers() withAnnotations annots))
- } else if (in.token == SUPERCALL) {
- superpos = in.skipToken()
- stats = new ListBuffer[Tree] ++ (stats.toList map markPreSuper)
- while (in.token == LPAREN) { superargss += argumentExprs() }
} else if (!isStatSep) {
syntaxErrorOrIncomplete("illegal start of definition", true)
}
if (in.token != RBRACE && in.token != EOF) acceptStatSep()
}
- if (!superargss.hasNext) superargss += List()
- (self, stats.toList, superpos, superargss.toList)
- }
-
- private def markPreSuper(stat: Tree): Tree = stat match {
- case ValDef(mods, name, tpt, rhs) =>
- copy.ValDef(stat, mods | Flags.PRESUPER, name, tpt, rhs)
- case _ =>
- syntaxError(stat.pos, "only value definitions may precede super call", false)
- stat
+ (self, stats.toList)
}
/** RefineStatSeq ::= RefineStat {semi RefineStat}
diff --git a/src/compiler/scala/tools/nsc/ast/parser/Scanners.scala b/src/compiler/scala/tools/nsc/ast/parser/Scanners.scala
index 8eb785b38e..33f0c7db71 100644
--- a/src/compiler/scala/tools/nsc/ast/parser/Scanners.scala
+++ b/src/compiler/scala/tools/nsc/ast/parser/Scanners.scala
@@ -37,24 +37,12 @@ trait Scanners requires SyntaxAnalyzer {
/** the base of a number */
var base: int = 0
- /** further lookahead tokens after this one */
- var following: TokenData = null
-
- def copyFrom(td: TokenData) {
+ def copyFrom(td: TokenData) = {
this.token = td.token
this.pos = td.pos
this.lastPos = td.lastPos
this.name = td.name
this.base = td.base
- td.token = EMPTY
- }
-
- def pushFrom(td: TokenData) {
- if (token != EMPTY) {
- following = new TokenData
- following copyFrom this
- }
- this copyFrom td
}
}
@@ -158,44 +146,34 @@ trait Scanners requires SyntaxAnalyzer {
fetchToken()
} else {
this copyFrom next
- if (next.following != null) {
- next copyFrom next.following
- next.following = null
- }
+ next.token = EMPTY
}
if (token == CASE) {
prev copyFrom this
fetchToken()
if (token == CLASS) {
- this copyFrom prev
token = CASECLASS
+ lastPos = prev.lastPos
} else if (token == OBJECT) {
- this copyFrom prev
token = CASEOBJECT
+ lastPos = prev.lastPos
} else {
- next pushFrom this
+ next copyFrom this
this copyFrom prev
}
- } else if (token == SUPER && next.token == EMPTY) {
- prev copyFrom this
- fetchToken()
- val isSuperCall = token == LPAREN
- next pushFrom this
- this copyFrom prev
- if (isSuperCall) token = SUPERCALL
} else if (token == SEMI) {
prev copyFrom this
fetchToken()
if (token != ELSE) {
- next pushFrom this
+ next copyFrom this
this copyFrom prev
}
}
if (afterLineEnd() && inLastOfStat(lastToken) && inFirstOfStat(token) &&
(sepRegions.isEmpty || sepRegions.head == RBRACE)) {
- next pushFrom this
+ next copyFrom this
pos = in.lineStartPos
if (settings.migrate.value) newNewLine = lastToken != RBRACE && token != EOF;
token = if (in.lastBlankLinePos > lastPos) NEWLINES else NEWLINE
diff --git a/src/compiler/scala/tools/nsc/ast/parser/Tokens.scala b/src/compiler/scala/tools/nsc/ast/parser/Tokens.scala
index 8044744e6c..0aed4e8eae 100644
--- a/src/compiler/scala/tools/nsc/ast/parser/Tokens.scala
+++ b/src/compiler/scala/tools/nsc/ast/parser/Tokens.scala
@@ -69,7 +69,6 @@ object Tokens {
final val RETURN = 57
final val MATCH = 58
final val REQUIRES = 59
- final val SUPERCALL = 60
/** special symbols */
final val COMMA = 61
diff --git a/src/compiler/scala/tools/nsc/transform/AddInterfaces.scala b/src/compiler/scala/tools/nsc/transform/AddInterfaces.scala
index a184a1a0b7..0179580e05 100644
--- a/src/compiler/scala/tools/nsc/transform/AddInterfaces.scala
+++ b/src/compiler/scala/tools/nsc/transform/AddInterfaces.scala
@@ -129,8 +129,9 @@ abstract class AddInterfaces extends InfoTransform {
*/
private def implDecls(implClass: Symbol, ifaceDecls: Scope): Scope = {
val decls = newScope
- decls enter (implClass.newMethod(implClass.pos, nme.MIXIN_CONSTRUCTOR)
- setInfo MethodType(List(), UnitClass.tpe))
+ if ((ifaceDecls lookup nme.MIXIN_CONSTRUCTOR) == NoSymbol)
+ decls enter (implClass.newMethod(implClass.pos, nme.MIXIN_CONSTRUCTOR)
+ setInfo MethodType(List(), UnitClass.tpe))
for (val sym <- ifaceDecls.elements) {
if (isInterfaceMember(sym)) {
if (needsImplMethod(sym)) {
@@ -244,16 +245,18 @@ abstract class AddInterfaces extends InfoTransform {
else if (needsImplMethod(tree.symbol)) implMethodDef(tree, tree.symbol)
else EmptyTree
- /** The mixin constructor definition
+ /** Add mixin constructor definition
* def $init$(): Unit = ()
+ * to `stats' unless there is already one.
*/
- private def mixinConstructorDef(clazz: Symbol): Tree =
- DefDef(clazz.primaryConstructor, vparamss => Block(List(), Literal(())))
+ private def addMixinConstructorDef(clazz: Symbol, stats: List[Tree]): List[Tree] =
+ if (treeInfo.firstConstructor(stats) != EmptyTree) stats
+ else DefDef(clazz.primaryConstructor, vparamss => Block(List(), Literal(()))) :: stats
private def implTemplate(clazz: Symbol, templ: Template): Template = atPos(templ.pos) {
val templ1 = atPos(templ.pos) {
- Template(templ.parents, mixinConstructorDef(clazz) :: (templ.body map implMemberDef))
- .setSymbol(clazz.newLocalDummy(templ.pos))
+ Template(templ.parents, addMixinConstructorDef(clazz, templ.body map implMemberDef))
+ .setSymbol(clazz.newLocalDummy(templ.pos))
}
new ChangeOwnerTraverser(templ.symbol.owner, clazz)(
new ChangeOwnerTraverser(templ.symbol, templ1.symbol)(templ1))
diff --git a/src/compiler/scala/tools/nsc/transform/Constructors.scala b/src/compiler/scala/tools/nsc/transform/Constructors.scala
index 606a252b24..d9355bf24e 100644
--- a/src/compiler/scala/tools/nsc/transform/Constructors.scala
+++ b/src/compiler/scala/tools/nsc/transform/Constructors.scala
@@ -91,7 +91,8 @@ abstract class Constructors extends Transform {
new ChangeOwnerTraverser(oldowner, constr.symbol)(tree))
def canBeMoved(tree: Tree) = tree match {
- case ValDef(_, _, _, _) => !thisRefSeen
+ //todo: eliminate thisRefSeen
+ case ValDef(mods, _, _, _) => (mods hasFlag PRESUPER | PARAMACCESSOR) || !thisRefSeen
case _ => false
}
diff --git a/src/compiler/scala/tools/nsc/transform/ExplicitOuter.scala b/src/compiler/scala/tools/nsc/transform/ExplicitOuter.scala
index 03eccb9b39..a9f5242508 100644
--- a/src/compiler/scala/tools/nsc/transform/ExplicitOuter.scala
+++ b/src/compiler/scala/tools/nsc/transform/ExplicitOuter.scala
@@ -91,10 +91,6 @@ abstract class ExplicitOuter extends InfoTransform with TransMatcher with Patter
* </p>
* </li>
* <li>
- * Add a mixin constructor <code>$init$</code> to all mixins except interfaces
- * Leave all other types unchanged. todo: move to later
- * </li>
- * <li>
* Make all super accessors and modules in traits non-private, mangling
* their names.
* </li>
@@ -346,9 +342,7 @@ abstract class ExplicitOuter extends InfoTransform with TransMatcher with Patter
if (sym.isClassConstructor) {
rhs match {
case Literal(_) =>
- // replace unit rhs () by empty block {()}
- val rhs1 = Block(List(), rhs) setPos rhs.pos setType rhs.tpe
- transform(copy.DefDef(tree, mods, name, tparams, vparamss, tpt, rhs1))
+ Predef.error("unexpected case") //todo: remove
case _ =>
val clazz = sym.owner
val vparamss1 =
diff --git a/src/compiler/scala/tools/nsc/transform/UnCurry.scala b/src/compiler/scala/tools/nsc/transform/UnCurry.scala
index 824e20a56e..20bc433c2f 100644
--- a/src/compiler/scala/tools/nsc/transform/UnCurry.scala
+++ b/src/compiler/scala/tools/nsc/transform/UnCurry.scala
@@ -348,16 +348,14 @@ abstract class UnCurry extends InfoTransform with TypingTransformers {
tree match {
case DefDef(mods, name, tparams, vparamss, tpt, rhs) =>
withNeedLift(false) {
- if (tree.symbol.isConstructor) {
+ if (tree.symbol.isClassConstructor) {
atOwner(tree.symbol) {
- val rhs1 = rhs match {
+ val rhs1 = (rhs: @unchecked) match {
case Block(stat :: stats, expr) =>
copy.Block(
rhs,
withInConstructorFlag(INCONSTRUCTOR) { transform(stat) } :: transformTrees(stats),
transform(expr));
- case _ =>
- withInConstructorFlag(INCONSTRUCTOR) { transform(rhs) }
}
copy.DefDef(
tree, mods, name, transformAbsTypeDefs(tparams),
diff --git a/src/compiler/scala/tools/nsc/typechecker/Contexts.scala b/src/compiler/scala/tools/nsc/typechecker/Contexts.scala
index 156700d590..6943c78226 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Contexts.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Contexts.scala
@@ -230,10 +230,23 @@ trait Contexts requires Analyzer {
val argContext = baseContext.makeNewScope(tree, owner)
argContext.reportGeneralErrors = this.reportGeneralErrors
argContext.reportAmbiguousErrors = this.reportAmbiguousErrors
- for (val sym <- scope.toList) argContext.scope enter sym
+ def enterElems(c: Context) {
+ def enterLocalElems(e: ScopeEntry) {
+ if (e != null && e.owner == c.scope) {
+ enterLocalElems(e.next)
+ argContext.scope enter e.sym
+ }
+ }
+ if (c.owner.isTerm && !c.owner.isLocalDummy) {
+ enterElems(c.outer)
+ enterLocalElems(c.scope.elems)
+ }
+ }
+ enterElems(this)
argContext
}
+ //todo: remove
def makeConstructorSuffixContext = {
val c = make(tree)
c.inConstructorSuffix = true
diff --git a/src/compiler/scala/tools/nsc/typechecker/Namers.scala b/src/compiler/scala/tools/nsc/typechecker/Namers.scala
index be5d2600d9..eafe154756 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Namers.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Namers.scala
@@ -99,7 +99,7 @@ trait Namers requires Analyzer {
innerNamerCache
}
- def primaryConstructorParamNamer: Namer = {
+ def primaryConstructorParamNamer: Namer = { //todo: can we merge this with SCCmode?
val classContext = context.enclClass
val outerContext = classContext.outer.outer
val paramContext = outerContext.makeNewScope(outerContext.tree, outerContext.owner)
@@ -661,22 +661,17 @@ trait Namers requires Analyzer {
checkContractive(sym, result)
case vdef @ ValDef(mods, _, tpt, rhs) =>
+ val typer1 = typer.constrTyperIf(sym.hasFlag(PARAM | PRESUPER) && sym.owner.isConstructor)
if (tpt.isEmpty) {
if (rhs.isEmpty) {
context.error(tpt.pos, "missing parameter type");
ErrorType
} else {
tpt.tpe = deconstIfNotFinal(sym,
- typer.valDefRhsTyper(vdef).computeType(rhs, WildcardType))
+ newTyper(typer1.context.make(vdef, sym)).computeType(rhs, WildcardType))
tpt.tpe
}
- } else {
- val typer1 =
- if (sym.hasFlag(PARAM) && sym.owner.isConstructor && !phase.erasedTypes)
- newTyper(context.makeConstructorContext)
- else typer;
- typer1.typedType(tpt).tpe
- }
+ } else typer1.typedType(tpt).tpe
case tree @ AliasTypeDef(_, _, tparams, rhs) =>
new Namer(makeNewScope(context, tree, sym)).aliasTypeSig(sym, tparams, rhs)
diff --git a/src/compiler/scala/tools/nsc/typechecker/Typers.scala b/src/compiler/scala/tools/nsc/typechecker/Typers.scala
index 329eb344c6..60cfcac73f 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Typers.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Typers.scala
@@ -117,10 +117,17 @@ trait Typers requires Analyzer {
*/
val REGPATmode = 0x1000
- private val stickyModes: int = EXPRmode | PATTERNmode | TYPEmode | CONSTmode
+ /** The mode <code>ALTmode</code> is set when we are under a pattern alternative */
+ val ALTmode = 0x2000
+
+ private val stickyModes: int = EXPRmode | PATTERNmode | TYPEmode | CONSTmode | ALTmode
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
+
private var xxx = 10;
class Typer(context0: Context) {
import context0.unit
@@ -182,7 +189,7 @@ trait Typers requires Analyzer {
namerCache
}
- private var context = context0
+ private[typechecker] var context = context0
def context1 = context
/** Report a type error.
@@ -420,12 +427,9 @@ trait Typers requires Analyzer {
/** The typer for an expression, depending on where we are. If we are before a superclass
* call, this is a typer over a constructor context; otherwise it is the current typer.
*/
- def exprTyper(inConstr: boolean): Typer =
+ def constrTyperIf(inConstr: boolean): Typer =
if (inConstr) newTyper(context.makeConstructorContext) else this
- def valDefRhsTyper(vdef: ValDef): Typer =
- newTyper(context.make(vdef, vdef.symbol)).exprTyper(vdef.mods hasFlag PRESUPER)
-
/** <p>
* Post-process an identifier or selection node, performing the following:
* </p>
@@ -561,7 +565,10 @@ trait Typers requires Analyzer {
context.undetparams = List()
inferExprInstance(tree, tparams, pt)
adapt(tree, mode, pt)
- } else typed(applyImplicitArgs(tree), mode, pt)
+ } else {
+ val typer1 = constrTyperIf(treeInfo.isSelfConstrCall(tree) || treeInfo.isSuperConstrCall(tree))
+ typer1.typed(typer1.applyImplicitArgs(tree), mode, pt)
+ }
case mt: MethodType
if (((mode & (EXPRmode | FUNmode | LHSmode)) == EXPRmode) &&
(context.undetparams.isEmpty || (mode & POLYmode) != 0)) =>
@@ -758,7 +765,7 @@ trait Typers requires Analyzer {
val constr = treeInfo.firstConstructor(templ.body)
if (supertpt.tpe.symbol != firstParent) {
constr match {
- case DefDef(_, _, _, _, _, Apply(_, superargs)) =>
+ case DefDef(_, _, _, _, _, Block(List(Apply(_, superargs)), _)) =>
if (!superargs.isEmpty)
error(superargs.head.pos, firstParent+" is a trait; does not take constructor arguments")
case _ =>
@@ -770,7 +777,7 @@ trait Typers requires Analyzer {
constr match {
case EmptyTree =>
error(supertpt.pos, "missing type arguments")
- case DefDef(_, _, _, vparamss, _, Apply(_, superargs)) =>
+ case DefDef(_, _, _, vparamss, _, Block(List(Apply(_, superargs)), _)) =>
val outercontext = context.outer
supertpt = TypeTree(
newTyper(makeNewScope(outercontext, constr, outercontext.owner))
@@ -1002,9 +1009,7 @@ trait Typers requires Analyzer {
def typedValDef(vdef: ValDef): ValDef = {
// attributes(vdef)
val sym = vdef.symbol
- val typer1 = if (sym.hasFlag(PARAM) && sym.owner.isConstructor)
- newTyper(context.makeConstructorContext)
- else this
+ val typer1 = constrTyperIf(sym.hasFlag(PARAM) && sym.owner.isConstructor)
var tpt1 = checkNoEscaping.privates(sym, typer1.typedType(vdef.tpt))
checkNonCyclic(vdef, tpt1)
val rhs1 =
@@ -1013,7 +1018,7 @@ trait Typers requires Analyzer {
error(vdef.pos, "local variables must be initialized")
vdef.rhs
} else {
- valDefRhsTyper(vdef).transformedOrTyped(vdef.rhs, tpt1.tpe)
+ newTyper(typer1.context.make(vdef, sym)).transformedOrTyped(vdef.rhs, tpt1.tpe)
}
copy.ValDef(vdef, vdef.mods, vdef.name, tpt1, checkDead(rhs1)) setType NoType
}
@@ -1035,8 +1040,8 @@ trait Typers requires Analyzer {
if (args2.length != formals.length)
assert(false, "mismatch " + clazz + " " + formals + " " + args2);//debug
(superConstr, args1 ::: args2)
- case Block(stats, expr) =>
- decompose(stats.head)
+ case Block(stats, expr) if !stats.isEmpty =>
+ decompose(stats.last)
case _ =>
(call, List())
}
@@ -1086,24 +1091,7 @@ trait Typers requires Analyzer {
* @return ...
*/
def typedDefDef(ddef: DefDef): DefDef = {
-// attributes(ddef)
-
val meth = ddef.symbol
-
- def checkPrecedes(tree: Tree): unit = tree match {
- case Block(stat :: _, _) => checkPrecedes(stat)
- case Apply(fun, _) =>
- if (fun.symbol.isConstructor &&
- fun.symbol.owner == meth.owner && fun.symbol.pos >= meth.pos)
- error(fun.pos, "called constructor's definition must precede calling constructor's definition")
- case _ =>
- }
- def typedSuperCall(tree: Tree, pt: Type): Tree = {
- val result = typed(tree, EXPRmode | SCCmode, pt)
- checkPrecedes(result)
- result
- }
-
reenterTypeParams(ddef.tparams)
reenterValueParams(ddef.vparamss)
val tparams1 = List.mapConserve(ddef.tparams)(typedAbsTypeDef)
@@ -1115,33 +1103,24 @@ trait Typers requires Analyzer {
var tpt1 =
checkNoEscaping.locals(context.scope, WildcardType,
checkNoEscaping.privates(meth,
- typedType(ddef.tpt)))
+ typedType(ddef.tpt)))
checkNonCyclic(ddef, tpt1)
ddef.tpt.setType(tpt1.tpe)
var rhs1 =
if (ddef.name == nme.CONSTRUCTOR) {
- if (!meth.hasFlag(SYNTHETIC) &&
- !(meth.owner.isClass ||
- meth.owner.isModuleClass ||
- meth.owner.isAnonymousClass ||
- meth.owner.isRefinementClass))
- error(ddef.pos, "constructor definition not allowed here "+meth.owner)//debug
- val result = ddef.rhs match {
- case block @ Block(stat :: stats, expr) =>
- // the following makes sure not to copy the tree if no subtrees have changed
- val stat1 = typedSuperCall(stat, WildcardType)
- val block1 = newTyper(context.makeConstructorSuffixContext)
- .typedBlock(Block(stats, expr) setPos block.pos, EXPRmode, UnitClass.tpe)
- val stats1 = if ((stat eq stat1) && (stats eq block1.stats)) block.stats
- else stat1 :: block1.stats
- copy.Block(block, stats1, block1.expr) setType block1.tpe
- case _ =>
- typedSuperCall(ddef.rhs, UnitClass.tpe)
- }
- if (meth.isPrimaryConstructor && phase.id <= currentRun.typerPhase.id && !reporter.hasErrors)
- computeParamAliases(meth.owner, vparamss1, result)
- result
- } else transformedOrTyped(ddef.rhs, tpt1.tpe)
+ if (!meth.isPrimaryConstructor &&
+ (!meth.owner.isClass ||
+ meth.owner.isModuleClass ||
+ meth.owner.isAnonymousClass ||
+ meth.owner.isRefinementClass))
+ error(ddef.pos, "constructor definition not allowed here")
+ typed(ddef.rhs)
+ } else {
+ transformedOrTyped(ddef.rhs, tpt1.tpe)
+ }
+ if (meth.isPrimaryConstructor && meth.isClassConstructor &&
+ phase.id <= currentRun.typerPhase.id && !reporter.hasErrors)
+ computeParamAliases(meth.owner, vparamss1, rhs1)
if (tpt1.tpe.symbol != AllClass && !context.returnsSeen) rhs1 = checkDead(rhs1)
copy.DefDef(ddef, ddef.mods, ddef.name, tparams1, vparamss1, tpt1, rhs1) setType NoType
}
@@ -1359,7 +1338,12 @@ trait Typers requires Analyzer {
case _ =>
val localTyper = if (inBlock || (stat.isDef && !stat.isInstanceOf[LabelDef])) this
else newTyper(context.make(stat, exprOwner))
- checkDead(localTyper.typed(stat))
+ val result = checkDead(localTyper.typed(stat))
+ if (treeInfo.isSelfConstrCall(stat) || treeInfo.isSuperConstrCall(stat))
+ 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")
+ result
}
}
def accesses(accessor: Symbol, accessed: Symbol) =
@@ -1387,7 +1371,7 @@ trait Typers requires Analyzer {
}
def typedArg(arg: Tree, mode: int, newmode: int, pt: Type): Tree =
- checkDead(exprTyper((mode & SCCmode) != 0).typed(arg, mode & stickyModes | newmode, pt))
+ checkDead(constrTyperIf((mode & SCCmode) != 0).typed(arg, mode & stickyModes | newmode, pt))
def typedArgs(args: List[Tree], mode: int) =
List.mapConserve(args)(arg => typedArg(arg, mode, 0, WildcardType))
@@ -1448,7 +1432,7 @@ trait Typers requires Analyzer {
case OverloadedType(pre, alts) =>
val undetparams = context.undetparams
context.undetparams = List()
- val args1 = typedArgs(args, mode)
+ val args1 = typedArgs(args, argMode(fun, mode))
context.undetparams = undetparams
inferMethodAlternative(fun, context.undetparams, args1 map (.tpe.deconst), pt)
typedApply(tree, adapt(fun, funMode(mode), WildcardType), args1, mode, pt)
@@ -1466,7 +1450,7 @@ trait Typers requires Analyzer {
val tparams = context.undetparams
context.undetparams = List()
if (tparams.isEmpty) {
- val args2 = typedArgs(args1, mode, formals0, formals)
+ val args2 = typedArgs(args1, argMode(fun, mode), formals0, formals)
def ifPatternSkipFormals(tp: Type) = tp match {
case MethodType(_, rtp) if ((mode & PATTERNmode) != 0) => rtp
case _ => tp
@@ -1516,7 +1500,7 @@ trait Typers requires Analyzer {
if (targ == WildcardType) tparam.tpe else targ)
def typedArgToPoly(arg: Tree, formal: Type): Tree = {
val lenientPt = formal.instantiateTypeParams(tparams, lenientTargs)
- val arg1 = typedArg(arg, mode, POLYmode, lenientPt)
+ val arg1 = typedArg(arg, argMode(fun, mode), POLYmode, lenientPt)
val argtparams = context.undetparams
context.undetparams = List()
if (!argtparams.isEmpty) {
@@ -1710,7 +1694,7 @@ trait Typers requires Analyzer {
* @param args ...
* @return ...
*/
- def tryTypedArgs(args: List[Tree], other : TypeError) : List[Tree] = {
+ def tryTypedArgs(args: List[Tree], mode: int, other : TypeError) : List[Tree] = {
val c = context.makeSilent(false)
c.retyping = true
try {
@@ -1747,7 +1731,7 @@ trait Typers requires Analyzer {
}
if (errorInResult(fun) || (args exists errorInResult)) {
val Select(qual, name) = fun
- val args1 = tryTypedArgs(args, ex)
+ val args1 = tryTypedArgs(args, argMode(fun, mode), ex)
val qual1 =
if ((args1 ne null) && !pt.isError) {
def templateArgType(arg: Tree) =
@@ -2092,7 +2076,7 @@ trait Typers requires Analyzer {
copy.Sequence(tree, elems1) setType pt
case Alternative(alts) =>
- val alts1 = List.mapConserve(alts)(alt => typed(alt, mode, pt))
+ val alts1 = List.mapConserve(alts)(alt => typed(alt, mode | ALTmode, pt))
copy.Alternative(tree, alts1) setType pt
case Star(elem) =>
@@ -2125,6 +2109,8 @@ trait Typers requires Analyzer {
"use backquotes `"+vble.name+"` if you mean to match against that value;\n" +
"or rename the variable or use an explicit bind "+vble.name+"@_ to avoid this warning.")
*/
+ if ((mode & ALTmode) != 0)
+ error(tree.pos, "illegal variable in pattern alternative")
namer.enterInScope(vble)
}
val body1 = typed(body, mode, pt)