summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorLukas Rytz <lukas.rytz@epfl.ch>2009-05-30 07:36:31 +0000
committerLukas Rytz <lukas.rytz@epfl.ch>2009-05-30 07:36:31 +0000
commit390ccacfe0caa4c07af6193dec3e172c0fcd7896 (patch)
tree001ff4a00bd9d8cab651d9bf245bfc795748d829 /src
parent661f1ba10e5062fd987c4cafe43ad1f0dc3f5491 (diff)
downloadscala-390ccacfe0caa4c07af6193dec3e172c0fcd7896.tar.gz
scala-390ccacfe0caa4c07af6193dec3e172c0fcd7896.tar.bz2
scala-390ccacfe0caa4c07af6193dec3e172c0fcd7896.zip
Named and default arguments
- MethodTypes now have (params: List[Symbol]) - "copy"-methods for case classes - the "copy" object in the compiler is now called "treeCopy"
Diffstat (limited to 'src')
-rw-r--r--src/compiler/scala/tools/ant/Scalac.scala12
-rw-r--r--src/compiler/scala/tools/nsc/ast/NodePrinters.scala1
-rw-r--r--src/compiler/scala/tools/nsc/ast/TreeBrowsers.scala4
-rw-r--r--src/compiler/scala/tools/nsc/ast/TreeGen.scala6
-rw-r--r--src/compiler/scala/tools/nsc/ast/TreeInfo.scala7
-rw-r--r--src/compiler/scala/tools/nsc/ast/TreePrinters.scala2
-rw-r--r--src/compiler/scala/tools/nsc/ast/Trees.scala223
-rw-r--r--src/compiler/scala/tools/nsc/ast/parser/MarkupParsers.scala2
-rwxr-xr-xsrc/compiler/scala/tools/nsc/ast/parser/Parsers.scala40
-rwxr-xr-xsrc/compiler/scala/tools/nsc/ast/parser/Scanners.scala2
-rw-r--r--src/compiler/scala/tools/nsc/ast/parser/SymbolicXMLBuilder.scala2
-rw-r--r--src/compiler/scala/tools/nsc/ast/parser/SyntaxAnalyzer.scala2
-rw-r--r--src/compiler/scala/tools/nsc/ast/parser/TreeBuilder.scala8
-rw-r--r--src/compiler/scala/tools/nsc/backend/icode/GenICode.scala2
-rw-r--r--src/compiler/scala/tools/nsc/backend/msil/GenMSIL.scala23
-rw-r--r--src/compiler/scala/tools/nsc/doc/ModelFrames.scala6
-rw-r--r--src/compiler/scala/tools/nsc/matching/ParallelMatching.scala15
-rw-r--r--src/compiler/scala/tools/nsc/matching/PatternNodes.scala3
-rw-r--r--src/compiler/scala/tools/nsc/matching/TransMatcher.scala2
-rw-r--r--src/compiler/scala/tools/nsc/symtab/Definitions.scala24
-rw-r--r--src/compiler/scala/tools/nsc/symtab/Flags.scala1
-rw-r--r--src/compiler/scala/tools/nsc/symtab/IdeSupport.scala4
-rw-r--r--src/compiler/scala/tools/nsc/symtab/StdNames.scala1
-rw-r--r--src/compiler/scala/tools/nsc/symtab/Symbols.scala45
-rw-r--r--src/compiler/scala/tools/nsc/symtab/Types.scala132
-rw-r--r--src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala50
-rw-r--r--src/compiler/scala/tools/nsc/symtab/classfile/MetaParser.scala10
-rw-r--r--src/compiler/scala/tools/nsc/symtab/classfile/PickleFormat.scala6
-rw-r--r--src/compiler/scala/tools/nsc/symtab/classfile/Pickler.scala8
-rw-r--r--src/compiler/scala/tools/nsc/symtab/classfile/UnPickler.scala41
-rw-r--r--src/compiler/scala/tools/nsc/symtab/clr/TypeParser.scala72
-rw-r--r--src/compiler/scala/tools/nsc/transform/AddInterfaces.scala16
-rw-r--r--src/compiler/scala/tools/nsc/transform/CleanUp.scala35
-rw-r--r--src/compiler/scala/tools/nsc/transform/Constructors.scala12
-rw-r--r--src/compiler/scala/tools/nsc/transform/Erasure.scala69
-rw-r--r--src/compiler/scala/tools/nsc/transform/ExplicitOuter.scala30
-rw-r--r--src/compiler/scala/tools/nsc/transform/Flatten.scala3
-rw-r--r--src/compiler/scala/tools/nsc/transform/LambdaLift.scala28
-rw-r--r--src/compiler/scala/tools/nsc/transform/LazyVals.scala10
-rw-r--r--src/compiler/scala/tools/nsc/transform/Mixin.scala25
-rw-r--r--src/compiler/scala/tools/nsc/transform/Reifiers.scala8
-rw-r--r--src/compiler/scala/tools/nsc/transform/SampleTransform.scala2
-rw-r--r--src/compiler/scala/tools/nsc/transform/TailCalls.scala33
-rw-r--r--src/compiler/scala/tools/nsc/transform/UnCurry.scala45
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Analyzer.scala1
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Contexts.scala2
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/DeVirtualize.scala28
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/EtaExpansion.scala12
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Implicits.scala2
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Infer.scala216
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Namers.scala295
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/NamesDefaults.scala376
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/RefChecks.scala6
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/SuperAccessors.scala37
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/SyntheticMethods.scala69
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Typers.scala417
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Unapplies.scala37
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Variances.scala4
-rw-r--r--src/library/scala/reflect/Type.scala4
-rw-r--r--src/library/scala/xml/NodeSeq.scala2
60 files changed, 1836 insertions, 744 deletions
diff --git a/src/compiler/scala/tools/ant/Scalac.scala b/src/compiler/scala/tools/ant/Scalac.scala
index f5ccf236a1..aaa50cdd08 100644
--- a/src/compiler/scala/tools/ant/Scalac.scala
+++ b/src/compiler/scala/tools/ant/Scalac.scala
@@ -200,7 +200,7 @@ class Scalac extends MatchingTask {
/** Sets the <code>origin</code> as a nested src Ant parameter.
* @return An origin path to be configured. */
- def createSrc(): Path = createNewPath(origin _, origin = _)
+ def createSrc(): Path = createNewPath(origin _, p => origin = p)
/** Sets the <code>origin</code> as an external reference Ant parameter.
* @param input A reference to an origin path. */
@@ -222,7 +222,7 @@ class Scalac extends MatchingTask {
compilerPath = setOrAppend(compilerPath, input)
}
- def createCompilerPath: Path = createNewPath(compilerPath _, compilerPath = _)
+ def createCompilerPath: Path = createNewPath(compilerPath _, p => compilerPath = p)
/** Sets the <code>compilerpathref</code> attribute. Used by Ant.
* @param input The value of <code>compilerpathref</code>. */
@@ -232,7 +232,7 @@ class Scalac extends MatchingTask {
/** Sets the <code>classpath</code> as a nested classpath Ant parameter.
* @return A class path to be configured. */
- def createClasspath(): Path = createNewPath(classpath _, classpath = _)
+ def createClasspath(): Path = createNewPath(classpath _, p => classpath = p)
/** Sets the <code>classpath</code> as an external reference Ant parameter.
* @param input A reference to a class path. */
@@ -248,7 +248,7 @@ class Scalac extends MatchingTask {
/** Sets the <code>sourcepath</code> as a nested sourcepath Ant parameter.
* @return A source path to be configured. */
- def createSourcepath(): Path = createNewPath(sourcepath _, sourcepath = _)
+ def createSourcepath(): Path = createNewPath(sourcepath _, p => sourcepath = p)
/** Sets the <code>sourcepath</code> as an external reference Ant parameter.
* @param input A reference to a source path. */
@@ -266,7 +266,7 @@ class Scalac extends MatchingTask {
/** Sets the <code>bootclasspath</code> as a nested sourcepath Ant
* parameter.
* @return A source path to be configured. */
- def createBootclasspath(): Path = createNewPath(bootclasspath _, bootclasspath = _)
+ def createBootclasspath(): Path = createNewPath(bootclasspath _, p => bootclasspath = p)
/** Sets the <code>bootclasspath</code> as an external reference Ant
* parameter.
@@ -281,7 +281,7 @@ class Scalac extends MatchingTask {
/** Sets the <code>extdirs</code> as a nested sourcepath Ant parameter.
* @return An extensions path to be configured. */
- def createExtdirs(): Path = createNewPath(extdirs _, extdirs = _)
+ def createExtdirs(): Path = createNewPath(extdirs _, p => extdirs = p)
/** Sets the <code>extdirs</code> as an external reference Ant parameter.
* @param input A reference to an extensions path. */
diff --git a/src/compiler/scala/tools/nsc/ast/NodePrinters.scala b/src/compiler/scala/tools/nsc/ast/NodePrinters.scala
index 4292cb24a0..c409545527 100644
--- a/src/compiler/scala/tools/nsc/ast/NodePrinters.scala
+++ b/src/compiler/scala/tools/nsc/ast/NodePrinters.scala
@@ -92,6 +92,7 @@ abstract class NodePrinters {
if (sym hasFlag CASEACCESSOR ) buf.append(" | CASEACCESSOR")
if (sym hasFlag TRAIT ) buf.append(" | TRAIT")
+ if (sym hasFlag DEFAULTPARAM ) buf.append(" | DEFAULTPARAM")
if (sym hasFlag BRIDGE ) buf.append(" | BRIDGE")
if (sym hasFlag ACCESSOR ) buf.append(" | ACCESSOR")
diff --git a/src/compiler/scala/tools/nsc/ast/TreeBrowsers.scala b/src/compiler/scala/tools/nsc/ast/TreeBrowsers.scala
index e278ab3645..e00db368fe 100644
--- a/src/compiler/scala/tools/nsc/ast/TreeBrowsers.scala
+++ b/src/compiler/scala/tools/nsc/ast/TreeBrowsers.scala
@@ -650,11 +650,11 @@ abstract class TreeBrowsers {
clazz.name.toString() :: ")")
)
- case MethodType(paramtypes, result) =>
+ case MethodType(params, result) =>
Document.group(
Document.nest(4, "MethodType(" :/:
Document.group("(" :/:
- toDocument(paramtypes) :/:
+ symsToDocument(params) :/:
"), ") :/:
toDocument(result) :: ")")
)
diff --git a/src/compiler/scala/tools/nsc/ast/TreeGen.scala b/src/compiler/scala/tools/nsc/ast/TreeGen.scala
index a015cd1cd9..0a5df116ac 100644
--- a/src/compiler/scala/tools/nsc/ast/TreeGen.scala
+++ b/src/compiler/scala/tools/nsc/ast/TreeGen.scala
@@ -268,12 +268,12 @@ abstract class TreeGen {
// def m: T = { if (m$ eq null) m$ = new m$class(...) m$ }
// where (...) are eventual outer accessors
def mkCachedModuleAccessDef(accessor: Symbol, mvar: Symbol) =
- DefDef(accessor, vparamss => mkCached(mvar, newModule(accessor, mvar.tpe)))
+ DefDef(accessor, mkCached(mvar, newModule(accessor, mvar.tpe)))
// def m: T = new tpe(...)
// where (...) are eventual outer accessors
def mkModuleAccessDef(accessor: Symbol, tpe: Type) =
- DefDef(accessor, vparamss => newModule(accessor, tpe))
+ DefDef(accessor, newModule(accessor, tpe))
private def newModule(accessor: Symbol, tpe: Type) =
New(TypeTree(tpe),
@@ -282,7 +282,7 @@ abstract class TreeGen {
// def m: T;
def mkModuleAccessDcl(accessor: Symbol) =
- DefDef(accessor setFlag lateDEFERRED, vparamss => EmptyTree)
+ DefDef(accessor setFlag lateDEFERRED, EmptyTree)
def mkRuntimeCall(meth: Name, args: List[Tree]): Tree =
Apply(Select(mkAttributedRef(ScalaRunTimeModule), meth), args)
diff --git a/src/compiler/scala/tools/nsc/ast/TreeInfo.scala b/src/compiler/scala/tools/nsc/ast/TreeInfo.scala
index 93124d95f3..3d023777f3 100644
--- a/src/compiler/scala/tools/nsc/ast/TreeInfo.scala
+++ b/src/compiler/scala/tools/nsc/ast/TreeInfo.scala
@@ -174,6 +174,13 @@ abstract class TreeInfo {
case _ => false
}
+ /** Is tpt a by-name parameter type? */
+ def isByNameParamType(tpt: Tree) = tpt match {
+ case AppliedTypeTree(Select(_, n), _) => n == nme.BYNAME_PARAM_CLASS_NAME.toTypeName
+ case TypeTree() => tpt.tpe.typeSymbol == definitions.ByNameParamClass
+ 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/TreePrinters.scala b/src/compiler/scala/tools/nsc/ast/TreePrinters.scala
index 6fb1c4e166..2189b449ab 100644
--- a/src/compiler/scala/tools/nsc/ast/TreePrinters.scala
+++ b/src/compiler/scala/tools/nsc/ast/TreePrinters.scala
@@ -72,7 +72,7 @@ abstract class TreePrinters {
tree match {
case ValDef(mods, name, tp, rhs) =>
printAnnotations(tree)
- print(symName(tree, name)); printOpt(": ", tp)
+ print(symName(tree, name)); printOpt(": ", tp); printOpt(" = ", rhs)
case TypeDef(mods, name, tparams, rhs) =>
print(symName(tree, name))
printTypeParams(tparams); print(rhs)
diff --git a/src/compiler/scala/tools/nsc/ast/Trees.scala b/src/compiler/scala/tools/nsc/ast/Trees.scala
index 97852afe81..eeb910478c 100644
--- a/src/compiler/scala/tools/nsc/ast/Trees.scala
+++ b/src/compiler/scala/tools/nsc/ast/Trees.scala
@@ -41,7 +41,7 @@ trait Trees {
val trees: Trees.this.type = Trees.this
} with TreeInfo
- val copy = new LazyTreeCopier()
+ val treeCopy = new LazyTreeCopier()
// modifiers --------------------------------------------------------
@@ -278,11 +278,11 @@ trait Trees {
// ----- auxiliary objects and methods ------------------------------
private lazy val duplicator = new Transformer {
- override val copy = new StrictTreeCopier
+ override val treeCopy = new StrictTreeCopier
}
private class ShallowDuplicator(orig: Tree) extends Transformer {
- override val copy = new StrictTreeCopier
+ override val treeCopy = new StrictTreeCopier
override def transform(tree: Tree) =
if (tree eq orig)
super.transform(tree)
@@ -290,21 +290,6 @@ trait Trees {
tree
}
- private def syntheticParams(owner: Symbol, mtp: Type): List[List[Symbol]] = {
- var cnt = 0
- def freshName() = { cnt += 1; newTermName("x$" + cnt) }
- def synthetics(mtp: Type): List[List[Symbol]] = mtp match {
- case PolyType(_, restp) =>
- synthetics(restp)
- case MethodType(formals, restp) =>
- (formals map (f => owner.newValueParameter(owner.pos, freshName()).setInfo(f))) ::
- synthetics(restp)
- case _ =>
- List()
- }
- synthetics(mtp)
- }
-
// def nextPhase = if (phase.id > globalPhase.id) phase else phase.next;
// ----- tree node alternatives --------------------------------------
@@ -464,12 +449,10 @@ trait Trees {
def DefDef(sym: Symbol, vparamss: List[List[ValDef]], rhs: Tree): DefDef =
DefDef(sym, Modifiers(sym.flags), vparamss, rhs)
- def DefDef(sym: Symbol, mods: Modifiers, rhs: List[List[Symbol]] => Tree): DefDef = {
- val vparamss = syntheticParams(sym, sym.tpe)
- DefDef(sym, mods, vparamss map (_.map(ValDef)), rhs(vparamss))
- }
+ def DefDef(sym: Symbol, mods: Modifiers, rhs: Tree): DefDef =
+ DefDef(sym, mods, sym.paramss map (_.map(ValDef)), rhs)
- def DefDef(sym: Symbol, rhs: List[List[Symbol]] => Tree): DefDef =
+ def DefDef(sym: Symbol, rhs: Tree): DefDef =
DefDef(sym, Modifiers(sym.flags), rhs)
/** Abstract type, type parameter, or type alias */
@@ -590,16 +573,16 @@ trait Trees {
var vparamss1 =
vparamss map (vps => vps.map { vd =>
ValDef(
- Modifiers(vd.mods.flags & IMPLICIT | PARAM) withAnnotations vd.mods.annotations,
- vd.name, vd.tpt.duplicate, EmptyTree).setOriginal(vd)
+ Modifiers(vd.mods.flags & (IMPLICIT | DEFAULTPARAM) | PARAM) withAnnotations vd.mods.annotations,
+ vd.name, vd.tpt.duplicate, vd.rhs.duplicate).setOriginal(vd)
})
val (edefs, rest) = body span treeInfo.isEarlyDef
val (evdefs, etdefs) = edefs partition treeInfo.isEarlyValDef
val (lvdefs, gvdefs) = List.unzip {
evdefs map {
case vdef @ ValDef(mods, name, tpt, rhs) =>
- (copy.ValDef(vdef, Modifiers(PRESUPER), name, tpt, rhs),
- copy.ValDef(vdef, mods, name, TypeTree(), EmptyTree))
+ (treeCopy.ValDef(vdef, Modifiers(PRESUPER), name, tpt, rhs),
+ treeCopy.ValDef(vdef, mods, name, TypeTree(), EmptyTree))
}
}
val constrs =
@@ -617,7 +600,11 @@ trait Trees {
List(
DefDef(constrMods, nme.CONSTRUCTOR, List(), vparamss1, TypeTree(), Block(lvdefs ::: List(superCall), Literal(()))))
}
- Template(parents, self, gvdefs ::: List.flatten(vparamss) ::: constrs ::: etdefs ::: rest)
+ // remove defaults
+ val vparamss2 = vparamss map (vps => vps map { vd =>
+ treeCopy.ValDef(vd, vd.mods &~ DEFAULTPARAM, vd.name, vd.tpt, EmptyTree)
+ })
+ Template(parents, self, gvdefs ::: List.flatten(vparamss2) ::: constrs ::: etdefs ::: rest)
}
/** Block of expressions (semicolon separated expressions) */
@@ -1132,232 +1119,232 @@ trait Trees {
new ExistentialTypeTree(tpt, whereClauses).copyAttrs(tree)
}
- class LazyTreeCopier(copy: TreeCopier) extends TreeCopier {
+ class LazyTreeCopier(treeCopy: TreeCopier) extends TreeCopier {
def this() = this(new StrictTreeCopier)
def ClassDef(tree: Tree, mods: Modifiers, name: Name, tparams: List[TypeDef], impl: Template) = tree match {
case t @ ClassDef(mods0, name0, tparams0, impl0)
if (mods0 == mods && (name0 == name) && (tparams0 == tparams) && (impl0 == impl)) => t
- case _ => copy.ClassDef(tree, mods, name, tparams, impl)
+ case _ => treeCopy.ClassDef(tree, mods, name, tparams, impl)
}
def PackageDef(tree: Tree, name: Name, stats: List[Tree]) = tree match {
case t @ PackageDef(name0, stats0)
if (name0 == name) && (stats0 == stats) => t
- case _ => copy.PackageDef(tree, name, stats)
+ case _ => treeCopy.PackageDef(tree, name, stats)
}
def ModuleDef(tree: Tree, mods: Modifiers, name: Name, impl: Template) = tree match {
case t @ ModuleDef(mods0, name0, impl0)
if (mods0 == mods) && (name0 == name) && (impl0 == impl) => t
- case _ => copy.ModuleDef(tree, mods, name, impl)
+ case _ => treeCopy.ModuleDef(tree, mods, name, impl)
}
def ValDef(tree: Tree, mods: Modifiers, name: Name, tpt: Tree, rhs: Tree) = tree match {
case t @ ValDef(mods0, name0, tpt0, rhs0)
if (mods0 == mods) && (name0 == name) && (tpt0 == tpt) && (rhs0 == rhs) => t
- case _ => copy.ValDef(tree, mods, name, tpt, rhs)
+ case _ => treeCopy.ValDef(tree, mods, name, tpt, rhs)
}
def DefDef(tree: Tree, mods: Modifiers, name: Name, tparams: List[TypeDef], vparamss: List[List[ValDef]], tpt: Tree, rhs: Tree) = tree match {
case t @ DefDef(mods0, name0, tparams0, vparamss0, tpt0, rhs0)
if (mods0 == mods) && (name0 == name) && (tparams0 == tparams) &&
(vparamss0 == vparamss) && (tpt0 == tpt) && (rhs == rhs0) => t
- case _ => copy.DefDef(tree, mods, name, tparams, vparamss, tpt, rhs)
+ case _ => treeCopy.DefDef(tree, mods, name, tparams, vparamss, tpt, rhs)
}
def TypeDef(tree: Tree, mods: Modifiers, name: Name, tparams: List[TypeDef], rhs: Tree) = tree match {
case t @ TypeDef(mods0, name0, tparams0, rhs0)
if (mods0 == mods) && (name0 == name) && (tparams0 == tparams) && (rhs0 == rhs) => t
- case _ => copy.TypeDef(tree, mods, name, tparams, rhs)
+ case _ => treeCopy.TypeDef(tree, mods, name, tparams, rhs)
}
def LabelDef(tree: Tree, name: Name, params: List[Ident], rhs: Tree) = tree match {
case t @ LabelDef(name0, params0, rhs0)
if (name0 == name) && (params0 == params) && (rhs0 == rhs) => t
- case _ => copy.LabelDef(tree, name, params, rhs)
+ case _ => treeCopy.LabelDef(tree, name, params, rhs)
}
def Import(tree: Tree, expr: Tree, selectors: List[(Name, Name)]) = tree match {
case t @ Import(expr0, selectors0)
if (expr0 == expr) && (selectors0 == selectors) => t
- case _ => copy.Import(tree, expr, selectors)
+ case _ => treeCopy.Import(tree, expr, selectors)
}
def Annotation(tree: Tree, constr: Tree, elements: List[Tree]) = tree match {
case t @ Annotation(constr0, elements0)
if (constr0 == constr) && (elements0 == elements) => t
- case _ => copy.Annotation(tree, constr, elements)
+ case _ => treeCopy.Annotation(tree, constr, elements)
}
def DocDef(tree: Tree, comment: String, definition: Tree) = tree match {
case t @ DocDef(comment0, definition0)
if (comment0 == comment) && (definition0 == definition) => t
- case _ => copy.DocDef(tree, comment, definition)
+ case _ => treeCopy.DocDef(tree, comment, definition)
}
def Template(tree: Tree, parents: List[Tree], self: ValDef, body: List[Tree]) = tree match {
case t @ Template(parents0, self0, body0)
if (parents0 == parents) && (self0 == self) && (body0 == body) => t
- case _ => copy.Template(tree, parents, self, body)
+ case _ => treeCopy.Template(tree, parents, self, body)
}
def Block(tree: Tree, stats: List[Tree], expr: Tree) = tree match {
case t @ Block(stats0, expr0)
if ((stats0 == stats) && (expr0 == expr)) => t
- case _ => copy.Block(tree, stats, expr)
+ case _ => treeCopy.Block(tree, stats, expr)
}
def CaseDef(tree: Tree, pat: Tree, guard: Tree, body: Tree) = tree match {
case t @ CaseDef(pat0, guard0, body0)
if (pat0 == pat) && (guard0 == guard) && (body0 == body) => t
- case _ => copy.CaseDef(tree, pat, guard, body)
+ case _ => treeCopy.CaseDef(tree, pat, guard, body)
}
def Sequence(tree: Tree, trees: List[Tree]) = tree match {
case t @ Sequence(trees0)
if trees0 == trees => t
- case _ => copy.Sequence(tree, trees)
+ case _ => treeCopy.Sequence(tree, trees)
}
def Alternative(tree: Tree, trees: List[Tree]) = tree match {
case t @ Alternative(trees0)
if trees0 == trees => t
- case _ => copy.Alternative(tree, trees)
+ case _ => treeCopy.Alternative(tree, trees)
}
def Star(tree: Tree, elem: Tree) = tree match {
case t @ Star(elem0)
if elem0 == elem => t
- case _ => copy.Star(tree, elem)
+ case _ => treeCopy.Star(tree, elem)
}
def Bind(tree: Tree, name: Name, body: Tree) = tree match {
case t @ Bind(name0, body0)
if (name0 == name) && (body0 == body) => t
- case _ => copy.Bind(tree, name, body)
+ case _ => treeCopy.Bind(tree, name, body)
}
def UnApply(tree: Tree, fun: Tree, args: List[Tree]) = tree match {
case t @ UnApply(fun0, args0)
if (fun0 == fun) && (args0 == args) => t
- case _ => copy.UnApply(tree, fun, args)
+ case _ => treeCopy.UnApply(tree, fun, args)
}
def ArrayValue(tree: Tree, elemtpt: Tree, trees: List[Tree]) = tree match {
case t @ ArrayValue(elemtpt0, trees0)
if (elemtpt0 == elemtpt) && (trees0 == trees) => t
- case _ => copy.ArrayValue(tree, elemtpt, trees)
+ case _ => treeCopy.ArrayValue(tree, elemtpt, trees)
}
def Function(tree: Tree, vparams: List[ValDef], body: Tree) = tree match {
case t @ Function(vparams0, body0)
if (vparams0 == vparams) && (body0 == body) => t
- case _ => copy.Function(tree, vparams, body)
+ case _ => treeCopy.Function(tree, vparams, body)
}
def Assign(tree: Tree, lhs: Tree, rhs: Tree) = tree match {
case t @ Assign(lhs0, rhs0)
if (lhs0 == lhs) && (rhs0 == rhs) => t
- case _ => copy.Assign(tree, lhs, rhs)
+ case _ => treeCopy.Assign(tree, lhs, rhs)
}
def If(tree: Tree, cond: Tree, thenp: Tree, elsep: Tree) = tree match {
case t @ If(cond0, thenp0, elsep0)
if (cond0 == cond) && (thenp0 == thenp) && (elsep0 == elsep) => t
- case _ => copy.If(tree, cond, thenp, elsep)
+ case _ => treeCopy.If(tree, cond, thenp, elsep)
}
def Match(tree: Tree, selector: Tree, cases: List[CaseDef]) = tree match {
case t @ Match(selector0, cases0)
if (selector0 == selector) && (cases0 == cases) => t
- case _ => copy.Match(tree, selector, cases)
+ case _ => treeCopy.Match(tree, selector, cases)
}
def Return(tree: Tree, expr: Tree) = tree match {
case t @ Return(expr0)
if expr0 == expr => t
- case _ => copy.Return(tree, expr)
+ case _ => treeCopy.Return(tree, expr)
}
def Try(tree: Tree, block: Tree, catches: List[CaseDef], finalizer: Tree) = tree match {
case t @ Try(block0, catches0, finalizer0)
if (block0 == block) && (catches0 == catches) && (finalizer0 == finalizer) => t
- case _ => copy.Try(tree, block, catches, finalizer)
+ case _ => treeCopy.Try(tree, block, catches, finalizer)
}
def Throw(tree: Tree, expr: Tree) = tree match {
case t @ Throw(expr0)
if expr0 == expr => t
- case _ => copy.Throw(tree, expr)
+ case _ => treeCopy.Throw(tree, expr)
}
def New(tree: Tree, tpt: Tree) = tree match {
case t @ New(tpt0)
if tpt0 == tpt => t
- case _ => copy.New(tree, tpt)
+ case _ => treeCopy.New(tree, tpt)
}
def Typed(tree: Tree, expr: Tree, tpt: Tree) = tree match {
case t @ Typed(expr0, tpt0)
if (expr0 == expr) && (tpt0 == tpt) => t
- case _ => copy.Typed(tree, expr, tpt)
+ case _ => treeCopy.Typed(tree, expr, tpt)
}
def TypeApply(tree: Tree, fun: Tree, args: List[Tree]) = tree match {
case t @ TypeApply(fun0, args0)
if (fun0 == fun) && (args0 == args) => t
- case _ => copy.TypeApply(tree, fun, args)
+ case _ => treeCopy.TypeApply(tree, fun, args)
}
def Apply(tree: Tree, fun: Tree, args: List[Tree]) = tree match {
case t @ Apply(fun0, args0)
if (fun0 == fun) && (args0 == args) => t
- case _ => copy.Apply(tree, fun, args)
+ case _ => treeCopy.Apply(tree, fun, args)
}
def ApplyDynamic(tree: Tree, qual: Tree, args: List[Tree]) = tree match {
case t @ ApplyDynamic(qual0, args0)
if (qual0 == qual) && (args0 == args) => t
- case _ => copy.ApplyDynamic(tree, qual, args)
+ case _ => treeCopy.ApplyDynamic(tree, qual, args)
}
def Super(tree: Tree, qual: Name, mix: Name) = tree match {
case t @ Super(qual0, mix0)
if (qual0 == qual) && (mix0 == mix) => t
- case _ => copy.Super(tree, qual, mix)
+ case _ => treeCopy.Super(tree, qual, mix)
}
def This(tree: Tree, qual: Name) = tree match {
case t @ This(qual0)
if qual0 == qual => t
- case _ => copy.This(tree, qual)
+ case _ => treeCopy.This(tree, qual)
}
def Select(tree: Tree, qualifier: Tree, selector: Name) = tree match {
case t @ Select(qualifier0, selector0)
if (qualifier0 == qualifier) && (selector0 == selector) => t
- case _ => copy.Select(tree, qualifier, selector)
+ case _ => treeCopy.Select(tree, qualifier, selector)
}
def Ident(tree: Tree, name: Name) = tree match {
case t @ Ident(name0)
if name0 == name => t
- case _ => copy.Ident(tree, name)
+ case _ => treeCopy.Ident(tree, name)
}
def Literal(tree: Tree, value: Constant) = tree match {
case t @ Literal(value0)
if value0 == value => t
- case _ => copy.Literal(tree, value)
+ case _ => treeCopy.Literal(tree, value)
}
def TypeTree(tree: Tree) = tree match {
case t @ TypeTree() => t
- case _ => copy.TypeTree(tree)
+ case _ => treeCopy.TypeTree(tree)
}
def Annotated(tree: Tree, annot: Annotation, arg: Tree) = tree match {
case t @ Annotated(annot0, arg0)
if (annot0==annot) => t
- case _ => copy.Annotated(tree, annot, arg)
+ case _ => treeCopy.Annotated(tree, annot, arg)
}
def SingletonTypeTree(tree: Tree, ref: Tree) = tree match {
case t @ SingletonTypeTree(ref0)
if ref0 == ref => t
- case _ => copy.SingletonTypeTree(tree, ref)
+ case _ => treeCopy.SingletonTypeTree(tree, ref)
}
def SelectFromTypeTree(tree: Tree, qualifier: Tree, selector: Name) = tree match {
case t @ SelectFromTypeTree(qualifier0, selector0)
if (qualifier0 == qualifier) && (selector0 == selector) => t
- case _ => copy.SelectFromTypeTree(tree, qualifier, selector)
+ case _ => treeCopy.SelectFromTypeTree(tree, qualifier, selector)
}
def CompoundTypeTree(tree: Tree, templ: Template) = tree match {
case t @ CompoundTypeTree(templ0)
if templ0 == templ => t
- case _ => copy.CompoundTypeTree(tree, templ)
+ case _ => treeCopy.CompoundTypeTree(tree, templ)
}
def AppliedTypeTree(tree: Tree, tpt: Tree, args: List[Tree]) = tree match {
case t @ AppliedTypeTree(tpt0, args0)
if (tpt0 == tpt) && (args0 == args) => t
- case _ => copy.AppliedTypeTree(tree, tpt, args)
+ case _ => treeCopy.AppliedTypeTree(tree, tpt, args)
}
def TypeBoundsTree(tree: Tree, lo: Tree, hi: Tree) = tree match {
case t @ TypeBoundsTree(lo0, hi0)
if (lo0 == lo) && (hi0 == hi) => t
- case _ => copy.TypeBoundsTree(tree, lo, hi)
+ case _ => treeCopy.TypeBoundsTree(tree, lo, hi)
}
def ExistentialTypeTree(tree: Tree, tpt: Tree, whereClauses: List[Tree]) = tree match {
case t @ ExistentialTypeTree(tpt0, whereClauses0)
if (tpt0 == tpt) && (whereClauses0 == whereClauses) => t
- case _ => copy.ExistentialTypeTree(tree, tpt, whereClauses)
+ case _ => treeCopy.ExistentialTypeTree(tree, tpt, whereClauses)
}
}
abstract class Transformer {
- val copy: TreeCopier = new LazyTreeCopier
+ val treeCopy: TreeCopier = new LazyTreeCopier
protected var currentOwner: Symbol = definitions.RootClass
protected def currentMethod = currentOwner.enclMethod
protected def currentClass = currentOwner.enclClass
@@ -1367,107 +1354,107 @@ trait Trees {
tree
case PackageDef(name, stats) =>
atOwner(tree.symbol.moduleClass) {
- copy.PackageDef(tree, name, transformStats(stats, currentOwner))
+ treeCopy.PackageDef(tree, name, transformStats(stats, currentOwner))
}
case ClassDef(mods, name, tparams, impl) =>
atOwner(tree.symbol) {
- copy.ClassDef(tree, mods, name, transformTypeDefs(tparams), transformTemplate(impl))
+ treeCopy.ClassDef(tree, mods, name, transformTypeDefs(tparams), transformTemplate(impl))
}
case ModuleDef(mods, name, impl) =>
atOwner(tree.symbol.moduleClass) {
- copy.ModuleDef(tree, mods, name, transformTemplate(impl))
+ treeCopy.ModuleDef(tree, mods, name, transformTemplate(impl))
}
case ValDef(mods, name, tpt, rhs) =>
atOwner(tree.symbol) {
- copy.ValDef(tree, mods, name, transform(tpt), transform(rhs))
+ treeCopy.ValDef(tree, mods, name, transform(tpt), transform(rhs))
}
case DefDef(mods, name, tparams, vparamss, tpt, rhs) =>
atOwner(tree.symbol) {
- copy.DefDef(
+ treeCopy.DefDef(
tree, mods, name, transformTypeDefs(tparams), transformValDefss(vparamss), transform(tpt), transform(rhs))
}
case TypeDef(mods, name, tparams, rhs) =>
atOwner(tree.symbol) {
- copy.TypeDef(tree, mods, name, transformTypeDefs(tparams), transform(rhs))
+ treeCopy.TypeDef(tree, mods, name, transformTypeDefs(tparams), transform(rhs))
}
case LabelDef(name, params, rhs) =>
- copy.LabelDef(tree, name, transformIdents(params), transform(rhs)) //bq: Martin, once, atOwner(...) works, also change `LamdaLifter.proxy'
+ treeCopy.LabelDef(tree, name, transformIdents(params), transform(rhs)) //bq: Martin, once, atOwner(...) works, also change `LamdaLifter.proxy'
case Import(expr, selectors) =>
- copy.Import(tree, transform(expr), selectors)
+ treeCopy.Import(tree, transform(expr), selectors)
case Annotation(constr, elements) =>
- copy.Annotation(tree, transform(constr), transformTrees(elements))
+ treeCopy.Annotation(tree, transform(constr), transformTrees(elements))
case DocDef(comment, definition) =>
- copy.DocDef(tree, comment, transform(definition))
+ treeCopy.DocDef(tree, comment, transform(definition))
case Template(parents, self, body) =>
- copy.Template(tree, transformTrees(parents), transformValDef(self), transformStats(body, tree.symbol))
+ treeCopy.Template(tree, transformTrees(parents), transformValDef(self), transformStats(body, tree.symbol))
case Block(stats, expr) =>
- copy.Block(tree, transformStats(stats, currentOwner), transform(expr))
+ treeCopy.Block(tree, transformStats(stats, currentOwner), transform(expr))
case CaseDef(pat, guard, body) =>
- copy.CaseDef(tree, transform(pat), transform(guard), transform(body))
+ treeCopy.CaseDef(tree, transform(pat), transform(guard), transform(body))
case Sequence(trees) =>
- copy.Sequence(tree, transformTrees(trees))
+ treeCopy.Sequence(tree, transformTrees(trees))
case Alternative(trees) =>
- copy.Alternative(tree, transformTrees(trees))
+ treeCopy.Alternative(tree, transformTrees(trees))
case Star(elem) =>
- copy.Star(tree, transform(elem))
+ treeCopy.Star(tree, transform(elem))
case Bind(name, body) =>
- copy.Bind(tree, name, transform(body))
+ treeCopy.Bind(tree, name, transform(body))
case UnApply(fun, args) =>
- copy.UnApply(tree, fun, transformTrees(args)) // bq: see test/.../unapplyContexts2.scala
+ treeCopy.UnApply(tree, fun, transformTrees(args)) // bq: see test/.../unapplyContexts2.scala
case ArrayValue(elemtpt, trees) =>
- copy.ArrayValue(tree, transform(elemtpt), transformTrees(trees))
+ treeCopy.ArrayValue(tree, transform(elemtpt), transformTrees(trees))
case Function(vparams, body) =>
atOwner(tree.symbol) {
- copy.Function(tree, transformValDefs(vparams), transform(body))
+ treeCopy.Function(tree, transformValDefs(vparams), transform(body))
}
case Assign(lhs, rhs) =>
- copy.Assign(tree, transform(lhs), transform(rhs))
+ treeCopy.Assign(tree, transform(lhs), transform(rhs))
case If(cond, thenp, elsep) =>
- copy.If(tree, transform(cond), transform(thenp), transform(elsep))
+ treeCopy.If(tree, transform(cond), transform(thenp), transform(elsep))
case Match(selector, cases) =>
- copy.Match(tree, transform(selector), transformCaseDefs(cases))
+ treeCopy.Match(tree, transform(selector), transformCaseDefs(cases))
case Return(expr) =>
- copy.Return(tree, transform(expr))
+ treeCopy.Return(tree, transform(expr))
case Try(block, catches, finalizer) =>
- copy.Try(tree, transform(block), transformCaseDefs(catches), transform(finalizer))
+ treeCopy.Try(tree, transform(block), transformCaseDefs(catches), transform(finalizer))
case Throw(expr) =>
- copy.Throw(tree, transform(expr))
+ treeCopy.Throw(tree, transform(expr))
case New(tpt) =>
- copy.New(tree, transform(tpt))
+ treeCopy.New(tree, transform(tpt))
case Typed(expr, tpt) =>
- copy.Typed(tree, transform(expr), transform(tpt))
+ treeCopy.Typed(tree, transform(expr), transform(tpt))
case TypeApply(fun, args) =>
- copy.TypeApply(tree, transform(fun), transformTrees(args))
+ treeCopy.TypeApply(tree, transform(fun), transformTrees(args))
case Apply(fun, args) =>
- copy.Apply(tree, transform(fun), transformTrees(args))
+ treeCopy.Apply(tree, transform(fun), transformTrees(args))
case ApplyDynamic(qual, args) =>
- copy.ApplyDynamic(tree, transform(qual), transformTrees(args))
+ treeCopy.ApplyDynamic(tree, transform(qual), transformTrees(args))
case Super(qual, mix) =>
- copy.Super(tree, qual, mix)
+ treeCopy.Super(tree, qual, mix)
case This(qual) =>
- copy.This(tree, qual)
+ treeCopy.This(tree, qual)
case Select(qualifier, selector) =>
- copy.Select(tree, transform(qualifier), selector)
+ treeCopy.Select(tree, transform(qualifier), selector)
case Ident(name) =>
- copy.Ident(tree, name)
+ treeCopy.Ident(tree, name)
case Literal(value) =>
- copy.Literal(tree, value)
+ treeCopy.Literal(tree, value)
case TypeTree() =>
- copy.TypeTree(tree)
+ treeCopy.TypeTree(tree)
case Annotated(annot, arg) =>
- copy.Annotated(tree, transform(annot).asInstanceOf[Annotation], transform(arg))
+ treeCopy.Annotated(tree, transform(annot).asInstanceOf[Annotation], transform(arg))
case SingletonTypeTree(ref) =>
- copy.SingletonTypeTree(tree, transform(ref))
+ treeCopy.SingletonTypeTree(tree, transform(ref))
case SelectFromTypeTree(qualifier, selector) =>
- copy.SelectFromTypeTree(tree, transform(qualifier), selector)
+ treeCopy.SelectFromTypeTree(tree, transform(qualifier), selector)
case CompoundTypeTree(templ) =>
- copy.CompoundTypeTree(tree, transformTemplate(templ))
+ treeCopy.CompoundTypeTree(tree, transformTemplate(templ))
case AppliedTypeTree(tpt, args) =>
- copy.AppliedTypeTree(tree, transform(tpt), transformTrees(args))
+ treeCopy.AppliedTypeTree(tree, transform(tpt), transformTrees(args))
case TypeBoundsTree(lo, hi) =>
- copy.TypeBoundsTree(tree, transform(lo), transform(hi))
+ treeCopy.TypeBoundsTree(tree, transform(lo), transform(hi))
case ExistentialTypeTree(tpt, whereClauses) =>
- copy.ExistentialTypeTree(tree, transform(tpt), transformTrees(whereClauses))
+ treeCopy.ExistentialTypeTree(tree, transform(tpt), transformTrees(whereClauses))
case tree : StubTree =>
tree.symbol = NoSymbol
tree.tpe = null
diff --git a/src/compiler/scala/tools/nsc/ast/parser/MarkupParsers.scala b/src/compiler/scala/tools/nsc/ast/parser/MarkupParsers.scala
index 3118eb6e6d..a8f6853853 100644
--- a/src/compiler/scala/tools/nsc/ast/parser/MarkupParsers.scala
+++ b/src/compiler/scala/tools/nsc/ast/parser/MarkupParsers.scala
@@ -2,7 +2,7 @@
* Copyright 2005-2009 LAMP/EPFL
* @author Burak Emir
*/
-// $Id: MarkupParsers.scala 17315 2009-03-16 17:46:58Z extempore $
+// $Id: MarkupParsers.scala 17754 2009-05-18 10:54:00Z milessabin $
package scala.tools.nsc.ast.parser
diff --git a/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala b/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala
index c116b60cee..2c12facda4 100755
--- a/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala
+++ b/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala
@@ -2,7 +2,7 @@
* Copyright 2005-2009 LAMP/EPFL
* @author Martin Odersky
*/
-// $Id: Parsers.scala 17415 2009-03-31 13:38:18Z imaier $
+// $Id: Parsers.scala 17756 2009-05-18 14:28:59Z rytz $
//todo: allow infix type patterns
@@ -1029,7 +1029,7 @@ self =>
if (isWildcard(t))
(placeholderParams: @unchecked) match {
case (vd @ ValDef(mods, name, _, _)) :: rest =>
- placeholderParams = copy.ValDef(vd, mods, name, tpt.duplicate, EmptyTree) :: rest
+ placeholderParams = treeCopy.ValDef(vd, mods, name, tpt.duplicate, EmptyTree) :: rest
}
// this does not correspond to syntax, but is necessary to
// accept closures. We might restrict closures to be between {...} only.
@@ -1200,11 +1200,27 @@ self =>
/** ArgumentExprs ::= `(' [Exprs [`,']] `)'
* | [nl] BlockExpr
*/
- def argumentExprs(): List[Tree] =
+ def argumentExprs(): List[Tree] = {
+ // if arg has the form "x$1 => a = x$1" it's treated as "a = x$1" with x$1
+ // in placeholderParams. This allows e.g. "val f: Int => Int = foo(a = 1, b = _)"
+ def convertArg(arg: Tree): Tree = arg match {
+ case Function(
+ List(vd @ ValDef(mods, pname1, ptype1, EmptyTree)),
+ Assign(Ident(aname), rhs)) if (mods hasFlag Flags.SYNTHETIC) =>
+ rhs match {
+ case Ident(`pname1`) | Typed(Ident(`pname1`), _) =>
+ placeholderParams = vd :: placeholderParams
+ atPos(arg.pos) { Assign(Ident(aname), Ident(pname1)) }
+ case _ => arg
+ }
+ case _ => arg
+ }
+
if (in.token == LBRACE)
List(blockExpr())
else
- surround(LPAREN, RPAREN)(if (in.token == RPAREN) List() else exprs(), List())
+ surround(LPAREN, RPAREN)(if (in.token == RPAREN) List() else (exprs() map convertArg), List())
+ }
/** BlockExpr ::= `{' (CaseClauses | Block) `}'
*/
@@ -1611,11 +1627,11 @@ self =>
/** ParamClauses ::= {ParamClause} [[nl] `(' implicit Params `)']
* ParamClause ::= [nl] `(' [Params] ')'
* Params ::= Param {`,' Param}
- * Param ::= {Annotation} Id [`:' ParamType]
+ * Param ::= {Annotation} Id [`:' ParamType] [`=' Expr]
* ClassParamClauses ::= {ClassParamClause} [[nl] `(' implicit ClassParams `)']
* ClassParamClause ::= [nl] `(' [ClassParams] ')'
* ClassParams ::= ClassParam {`,' ClassParam}
- * ClassParam ::= {Annotation} [{Modifier} (`val' | `var')] Id [`:' ParamType]
+ * ClassParam ::= {Annotation} [{Modifier} (`val' | `var')] Id [`:' ParamType] [`=' Expr]
*/
def paramClauses(owner: Name, implicitViews: List[Tree], ofCaseClass: Boolean): List[List[ValDef]] = {
var implicitmod = 0
@@ -1657,8 +1673,14 @@ self =>
}
paramType()
}
+ val default =
+ if (in.token == EQUALS) {
+ in.nextToken()
+ mods |= Flags.DEFAULTPARAM
+ expr()
+ } else EmptyTree
atPos(start, if (name == nme.ERROR) start else nameOffset) {
- ValDef((mods | implicitmod | bynamemod) withAnnotations annots, name, tpt, EmptyTree)
+ ValDef((mods | implicitmod | bynamemod) withAnnotations annots, name, tpt, default)
}
}
def paramClause(): List[ValDef] = {
@@ -2194,9 +2216,9 @@ self =>
if (in.token == WITH && self.isEmpty) {
val earlyDefs: List[Tree] = body flatMap {
case vdef @ ValDef(mods, name, tpt, rhs) if !(mods hasFlag Flags.DEFERRED) =>
- List(copy.ValDef(vdef, mods | Flags.PRESUPER, name, tpt, rhs))
+ List(treeCopy.ValDef(vdef, mods | Flags.PRESUPER, name, tpt, rhs))
case tdef @ TypeDef(mods, name, tparams, rhs) =>
- List(copy.TypeDef(tdef, mods | Flags.PRESUPER, name, tparams, rhs))
+ List(treeCopy.TypeDef(tdef, mods | Flags.PRESUPER, name, tparams, rhs))
case stat if !stat.isEmpty =>
syntaxError(stat.pos, "only type definitions and concrete field definitions allowed in early object initialization section", false)
List()
diff --git a/src/compiler/scala/tools/nsc/ast/parser/Scanners.scala b/src/compiler/scala/tools/nsc/ast/parser/Scanners.scala
index bd32213837..b15ec75cd7 100755
--- a/src/compiler/scala/tools/nsc/ast/parser/Scanners.scala
+++ b/src/compiler/scala/tools/nsc/ast/parser/Scanners.scala
@@ -2,7 +2,7 @@
* Copyright 2005-2009 LAMP/EPFL
* @author Martin Odersky
*/
-// $Id: Scanners.scala 17274 2009-03-10 11:39:04Z michelou $
+// $Id: Scanners.scala 17285 2009-03-11 13:51:56Z rytz $
package scala.tools.nsc.ast.parser
diff --git a/src/compiler/scala/tools/nsc/ast/parser/SymbolicXMLBuilder.scala b/src/compiler/scala/tools/nsc/ast/parser/SymbolicXMLBuilder.scala
index b2c83ae704..27e506b361 100644
--- a/src/compiler/scala/tools/nsc/ast/parser/SymbolicXMLBuilder.scala
+++ b/src/compiler/scala/tools/nsc/ast/parser/SymbolicXMLBuilder.scala
@@ -2,7 +2,7 @@
* Copyright 2005-2009 LAMP/EPFL
* @author Burak Emir
*/
-// $Id: SymbolicXMLBuilder.scala 16884 2009-01-09 16:52:09Z cunei $
+// $Id: SymbolicXMLBuilder.scala 17756 2009-05-18 14:28:59Z rytz $
package scala.tools.nsc.ast.parser
diff --git a/src/compiler/scala/tools/nsc/ast/parser/SyntaxAnalyzer.scala b/src/compiler/scala/tools/nsc/ast/parser/SyntaxAnalyzer.scala
index 3b402bdd36..0c3350aedc 100644
--- a/src/compiler/scala/tools/nsc/ast/parser/SyntaxAnalyzer.scala
+++ b/src/compiler/scala/tools/nsc/ast/parser/SyntaxAnalyzer.scala
@@ -2,7 +2,7 @@
* Copyright 2005-2009 LAMP/EPFL
* @author Martin Odersky
*/
-// $Id: SyntaxAnalyzer.scala 16893 2009-01-13 13:09:22Z cunei $
+// $Id: SyntaxAnalyzer.scala 17080 2009-02-10 17:19:16Z rytz $
package scala.tools.nsc.ast.parser
diff --git a/src/compiler/scala/tools/nsc/ast/parser/TreeBuilder.scala b/src/compiler/scala/tools/nsc/ast/parser/TreeBuilder.scala
index 28cb07b421..728dd99d27 100644
--- a/src/compiler/scala/tools/nsc/ast/parser/TreeBuilder.scala
+++ b/src/compiler/scala/tools/nsc/ast/parser/TreeBuilder.scala
@@ -47,13 +47,13 @@ abstract class TreeBuilder {
})
}
case Apply(fn @ Apply(_, _), args) =>
- copy.Apply(tree, transform(fn), transformTrees(args))
+ treeCopy.Apply(tree, transform(fn), transformTrees(args))
case Apply(fn, args) =>
- copy.Apply(tree, fn, transformTrees(args))
+ treeCopy.Apply(tree, fn, transformTrees(args))
case Typed(expr, tpt) =>
- copy.Typed(tree, transform(expr), tpt)
+ treeCopy.Typed(tree, transform(expr), tpt)
case Bind(name, body) =>
- copy.Bind(tree, name, transform(body))
+ treeCopy.Bind(tree, name, transform(body))
case Sequence(_) | Alternative(_) | Star(_) =>
super.transform(tree)
case _ =>
diff --git a/src/compiler/scala/tools/nsc/backend/icode/GenICode.scala b/src/compiler/scala/tools/nsc/backend/icode/GenICode.scala
index b7bdf1de9d..53b3317853 100644
--- a/src/compiler/scala/tools/nsc/backend/icode/GenICode.scala
+++ b/src/compiler/scala/tools/nsc/backend/icode/GenICode.scala
@@ -1707,7 +1707,7 @@ abstract class GenICode extends SubComponent {
sym.setInfo(oldLabel.tpe)
labels(oldLabel) = sym
}
- val tree = copy.LabelDef(t, name1, params, transform(rhs))
+ val tree = treeCopy.LabelDef(t, name1, params, transform(rhs))
tree.symbol = labels(t.symbol)
ctx.labels += (tree.symbol -> (new Label(tree.symbol) setParams(params map (_.symbol))));
diff --git a/src/compiler/scala/tools/nsc/backend/msil/GenMSIL.scala b/src/compiler/scala/tools/nsc/backend/msil/GenMSIL.scala
index 39fe0f4733..e9c8680b25 100644
--- a/src/compiler/scala/tools/nsc/backend/msil/GenMSIL.scala
+++ b/src/compiler/scala/tools/nsc/backend/msil/GenMSIL.scala
@@ -1425,10 +1425,11 @@ abstract class GenMSIL extends SubComponent {
// method: implicit view(FunctionX[PType0, PType1, ...,PTypeN, ResType]):DelegateType
val (isDelegateView, paramType, resType) = atPhase(currentRun.typerPhase){
msym.tpe match {
- case MethodType(parameterTypes, resultType)
- if (parameterTypes.length == 1 && msym.name == nme.view_) =>
- val isDel = definitions.isCorrespondingDelegate(resultType, parameterTypes(0))
- (isDel, parameterTypes(0), resultType)
+ case MethodType(params, resultType)
+ if (params.length == 1 && msym.name == nme.view_) =>
+ val paramType = params(0).tpe
+ val isDel = definitions.isCorrespondingDelegate(resultType, paramType)
+ (isDel, paramType, resultType)
case _ => (false, null, null)
}
}
@@ -2267,16 +2268,16 @@ abstract class GenMSIL extends SubComponent {
// create the static caller method and the delegate object
- val (paramTypes, returnType) = delegateType.member(nme.apply).tpe match {
+ val (params, returnType) = delegateType.member(nme.apply).tpe match {
case MethodType(delParams, delReturn) => (delParams, delReturn)
case _ => abort("not a delegate type: " + delegateType)
}
val caller: MethodBuilder = delegateCallers.DefineMethod(
"$delegateCaller$$" + nbDelegateCallers,
MethodAttributes.Final | MethodAttributes.Public | MethodAttributes.Static,
- msilType(returnType), paramTypes.map(msilType).toArray)
- for (i <- 0 until paramTypes.length)
- caller.DefineParameter(i, ParameterAttributes.None, "arg" + i)
+ msilType(returnType), (params map (_.tpe)).map(msilType).toArray)
+ for (i <- 0 until params.length)
+ caller.DefineParameter(i, ParameterAttributes.None, "arg" + i) // FIXME: use name of parameter symbol
val delegCtor = msilType(delegateType).GetConstructor(Array(MOBJECT, INT_PTR))
mcode.Emit(OpCodes.Ldnull)
mcode.Emit(OpCodes.Ldftn, caller)
@@ -2287,9 +2288,9 @@ abstract class GenMSIL extends SubComponent {
val functionApply: MethodInfo = getMethod(functionType.member(nme.apply))
val dcode: ILGenerator = caller.GetILGenerator()
dcode.Emit(OpCodes.Ldsfld, anonfunField)
- for (i <- 0 until paramTypes.length) {
+ for (i <- 0 until params.length) {
loadArg(dcode)(i)
- emitBox(dcode, toTypeKind(paramTypes(i)))
+ emitBox(dcode, toTypeKind(params(i).tpe))
}
dcode.Emit(OpCodes.Callvirt, functionApply)
emitUnbox(dcode, toTypeKind(returnType))
@@ -2444,7 +2445,7 @@ abstract class GenMSIL extends SubComponent {
alternatives.foreach(s => mapMethod(s, newClass, newName, msilParamTypes(s)))
// paramTypes: List[Type], resType: Type
- case MethodType(paramTypes, resType) =>
+ case MethodType(params, resType) =>
mapMethod(memberSym, newClass, newName, msilParamTypes(memberSym))
case _ =>
diff --git a/src/compiler/scala/tools/nsc/doc/ModelFrames.scala b/src/compiler/scala/tools/nsc/doc/ModelFrames.scala
index bd6c816ea8..5bda711f12 100644
--- a/src/compiler/scala/tools/nsc/doc/ModelFrames.scala
+++ b/src/compiler/scala/tools/nsc/doc/ModelFrames.scala
@@ -141,10 +141,12 @@ trait ModelFrames extends ModelExtractor {
}
java.net.URLEncoder.encode(sym.nameString +
(sym.tpe match {
- case MethodType(paramTypes, _) =>
+ case MethodType(params, _) =>
+ val paramTypes = params map (_.tpe)
if (sym hasFlag Flags.JAVA) javaParams(paramTypes)
else scalaParams(paramTypes)
- case PolyType(_, MethodType(paramTypes, _)) =>
+ case PolyType(_, MethodType(params, _)) =>
+ val paramTypes = params map (_.tpe)
if (sym hasFlag Flags.JAVA) javaParams(paramTypes)
else scalaParams(paramTypes)
case _ => ""
diff --git a/src/compiler/scala/tools/nsc/matching/ParallelMatching.scala b/src/compiler/scala/tools/nsc/matching/ParallelMatching.scala
index 15f712413d..b00ea9d68c 100644
--- a/src/compiler/scala/tools/nsc/matching/ParallelMatching.scala
+++ b/src/compiler/scala/tools/nsc/matching/ParallelMatching.scala
@@ -117,7 +117,7 @@ trait ParallelMatching {
final def getAlternativeBranches: List[Tree] = {
def get_BIND(pctx: Tree => Tree, p: Tree): List[Tree] = p match {
- case b @ Bind(n, p) => get_BIND((x: Tree) => pctx(copy.Bind(b, n, x) setType x.tpe), p)
+ case b @ Bind(n, p) => get_BIND((x: Tree) => pctx(treeCopy.Bind(b, n, x) setType x.tpe), p)
case Alternative(ps) => ps map pctx
}
get_BIND(x => x, tree)
@@ -653,7 +653,7 @@ trait ParallelMatching {
}
def getAlternativeBranches(p: Tree): List[Tree] = {
def get_BIND(pctx:Tree => Tree, p:Tree): List[Tree] = p match {
- case b @ Bind(n,p) => get_BIND((x: Tree) => pctx(copy.Bind(b, n, x) setType x.tpe), p)
+ case b @ Bind(n,p) => get_BIND((x: Tree) => pctx(treeCopy.Bind(b, n, x) setType x.tpe), p)
case Alternative(ps) => ps map pctx
}
get_BIND(x => x, p)
@@ -735,15 +735,15 @@ trait ParallelMatching {
}
if (!isReached(bx)) { // first time this bx is requested
// might be bound elsewhere ( see `x @ unapply' ) <-- this comment refers to null check
- val (vsyms, argts, vdefs) : (List[Symbol], List[Type], List[Tree]) = unzip3(
+ val (vsyms, vdefs) : (List[Symbol], List[Tree]) = List.unzip(
for (v <- vss(bx) ; substv <- subst(v)) yield
- (v, v.tpe, typedValDef(v, substv))
+ (v, typedValDef(v, substv))
)
val body = targets(bx)
// @bug: typer is not able to digest a body of type Nothing being assigned result type Unit
val tpe = if (body.tpe.isNothing) body.tpe else resultType
- val label = theOwner.newLabel(body.pos, "body%"+bx) setInfo MethodType(argts, tpe)
+ val label = theOwner.newLabel(body.pos, "body%"+bx) setInfo MethodType(vsyms, tpe)
// TODO - newLabel doesn't get a fresh name, is that okay? or should it be more like this:
// val label = theOwner.newLabel(body.pos, cunit.fresh.newName(body.pos, "body%"+bx)) setInfo MethodType(argts, tpe)
labels(bx) = label
@@ -759,7 +759,7 @@ trait ParallelMatching {
val args: List[Ident] = vss(bx).flatMap(subst(_))
val label = labels(bx)
val body = targets(bx)
- val MethodType(fmls, _) = label.tpe
+ val fmls = label.tpe.paramTypes
// sanity checks
if (fmls.length != args.length) {
@@ -829,7 +829,8 @@ trait ParallelMatching {
// @pre for UnApply_TypeApply: is not right-ignoring (no star pattern) ; no exhaustivity check
case UnApply_TypeApply(tptArg, xs) => temp(j) setFlag Flags.TRANS_FLAG
makeBind(vs, normalizedListPattern(xs, tptArg.tpe))
- case ua @ UnApply(Apply(fn, _), _) => val MethodType(List(argtpe, _*), _) = fn.tpe
+ case ua @ UnApply(Apply(fn, _), _) => val MethodType(List(arg, _*), _) = fn.tpe
+ val argtpe = arg.tpe
val npat = if (temp(j).tpe <:< argtpe) ua
else Typed(ua, TypeTree(argtpe)) setType argtpe
makeBind(vs, npat) setType argtpe
diff --git a/src/compiler/scala/tools/nsc/matching/PatternNodes.scala b/src/compiler/scala/tools/nsc/matching/PatternNodes.scala
index 83fb17c213..3b142affbc 100644
--- a/src/compiler/scala/tools/nsc/matching/PatternNodes.scala
+++ b/src/compiler/scala/tools/nsc/matching/PatternNodes.scala
@@ -128,7 +128,8 @@ trait PatternNodes {
val listType = TypeRef(pre, definitions.ListClass, List(tptArg))
resType = TypeRef(pre, sym , List(tptArg))
- MethodType(List(tptArg, listType), resType)
+ val dummyMethod = new TermSymbol(NoSymbol, NoPosition, "matching$dummy")
+ MethodType(dummyMethod.newSyntheticValueParams(List(tptArg, listType)), resType)
}
Apply(TypeTree(consType), List(x,normalizedListPattern(xs,tptArg))) setType resType
}
diff --git a/src/compiler/scala/tools/nsc/matching/TransMatcher.scala b/src/compiler/scala/tools/nsc/matching/TransMatcher.scala
index 583adfddff..b7b16fc906 100644
--- a/src/compiler/scala/tools/nsc/matching/TransMatcher.scala
+++ b/src/compiler/scala/tools/nsc/matching/TransMatcher.scala
@@ -74,7 +74,7 @@ trait TransMatcher {
(v, typedValDef(v, ti))
}
)
- (tmps, vds, ThrowMatchError(selector.pos, copy.Apply(app, fn, tmps map mkIdent)))
+ (tmps, vds, ThrowMatchError(selector.pos, treeCopy.Apply(app, fn, tmps map mkIdent)))
}
// sets temporaries, variable declarations, and the fail tree
diff --git a/src/compiler/scala/tools/nsc/symtab/Definitions.scala b/src/compiler/scala/tools/nsc/symtab/Definitions.scala
index fdad54ffcb..b28cfc859c 100644
--- a/src/compiler/scala/tools/nsc/symtab/Definitions.scala
+++ b/src/compiler/scala/tools/nsc/symtab/Definitions.scala
@@ -128,6 +128,7 @@ trait Definitions {
def List_apply = getMember(ListModule, nme.apply)
lazy val ArrayClass: Symbol = getClass("scala.Array")
def Array_apply = getMember(ArrayClass, nme.apply)
+ def Array_update = getMember(ArrayClass, nme.update)
lazy val ArrayModule: Symbol = getModule("scala.Array")
def ArrayModule_apply = getMember(ArrayModule, nme.apply)
lazy val SerializableClass: Symbol = getClass(sn.Serializable)
@@ -445,13 +446,22 @@ trait Definitions {
msym
}
- private def newMethod(owner: Symbol, name: Name, formals: List[Type], restpe: Type): Symbol =
- newMethod(owner, name).setInfo(MethodType(formals, restpe))
- private def newPolyMethod(owner: Symbol, name: Name, tcon: Symbol => Type): Symbol = {
+ private def newMethod(owner: Symbol, name: Name, formals: List[Type], restpe: Type): Symbol = {
+ val msym = newMethod(owner, name)
+ val params = msym.newSyntheticValueParams(formals)
+ msym.setInfo(MethodType(params, restpe))
+ }
+
+ /** tcon receives the type parameter symbol as argument */
+ private def newPolyMethod(owner: Symbol, name: Name, tcon: Symbol => Type): Symbol =
+ newPolyMethodCon(owner, name, tparam => msym => tcon(tparam))
+
+ /** tcon receives the type parameter symbol and the method symbol as arguments */
+ private def newPolyMethodCon(owner: Symbol, name: Name, tcon: Symbol => Symbol => Type): Symbol = {
val msym = newMethod(owner, name)
val tparam = newTypeParam(msym, 0)
- msym.setInfo(PolyType(List(tparam), tcon(tparam)))
+ msym.setInfo(PolyType(List(tparam), tcon(tparam)(msym)))
}
private def newParameterlessMethod(owner: Symbol, name: Name, restpe: Type) =
@@ -479,7 +489,7 @@ trait Definitions {
/** Test whether a method symbol is that of a boxing method. */
def isBox(m: Symbol) = (boxMethod.values contains m) && {
m.tpe match {
- case MethodType(List(argtpe), _) => (boxMethod get argtpe.typeSymbol) match {
+ case MethodType(List(arg), _) => (boxMethod get arg.tpe.typeSymbol) match {
case Some(`m`) => true
case _ => false
}
@@ -794,9 +804,9 @@ trait Definitions {
Object_!= = newMethod(ObjectClass, nme.NE, anyrefparam, booltype) setFlag FINAL
Object_eq = newMethod(ObjectClass, nme.eq, anyrefparam, booltype) setFlag FINAL
Object_ne = newMethod(ObjectClass, "ne", anyrefparam, booltype) setFlag FINAL
- Object_synchronized = newPolyMethod(
+ Object_synchronized = newPolyMethodCon(
ObjectClass, nme.synchronized_,
- tparam => MethodType(List(tparam.typeConstructor), tparam.typeConstructor)) setFlag FINAL
+ tparam => msym => MethodType(msym.newSyntheticValueParams(List(tparam.typeConstructor)), tparam.typeConstructor)) setFlag FINAL
Object_isInstanceOf = newPolyMethod(
ObjectClass, "$isInstanceOf",
tparam => MethodType(List(), booltype)) setFlag FINAL
diff --git a/src/compiler/scala/tools/nsc/symtab/Flags.scala b/src/compiler/scala/tools/nsc/symtab/Flags.scala
index 654c96a94f..2c7462296a 100644
--- a/src/compiler/scala/tools/nsc/symtab/Flags.scala
+++ b/src/compiler/scala/tools/nsc/symtab/Flags.scala
@@ -53,6 +53,7 @@ object Flags {
final val CASEACCESSOR = 0x01000000 // symbol is a case parameter (or its accessor)
final val TRAIT = 0x02000000 // symbol is a trait
+ final val DEFAULTPARAM = 0x02000000 // the parameter has a default value
final val BRIDGE = 0x04000000 // function is a bridge method. Set by Erasure
final val ACCESSOR = 0x08000000 // a value or variable accessor (getter or setter)
diff --git a/src/compiler/scala/tools/nsc/symtab/IdeSupport.scala b/src/compiler/scala/tools/nsc/symtab/IdeSupport.scala
index e52658baa9..97e883414b 100644
--- a/src/compiler/scala/tools/nsc/symtab/IdeSupport.scala
+++ b/src/compiler/scala/tools/nsc/symtab/IdeSupport.scala
@@ -259,7 +259,7 @@ trait IdeSupport extends SymbolTable { // added to global, not analyzers.
def hasError(infoA : Type) : Boolean = {
if (infoA == ErrorType) return true
infoA match {
- case MethodType(args,ret) => hasError(ret) || args.exists(hasError)
+ case MethodType(args,ret) => hasError(ret) || infoA.paramTypes.exists(hasError)
case PolyType(params,ret) => hasError(ret)
case TypeBounds(lo,hi) => hasError(lo) || hasError(hi)
case TypeRef(pre,_,args) => hasError(pre) || args.exists(hasError)
@@ -638,7 +638,7 @@ trait IdeSupport extends SymbolTable { // added to global, not analyzers.
}
object lightDuplicator extends Transformer {
- override val copy = new StrictTreeCopier
+ override val treeCopy = new StrictTreeCopier
}
// make the trees less detailed.
override def sanitize(tree : Tree) : Tree = lightDuplicator.transform(tree match {
diff --git a/src/compiler/scala/tools/nsc/symtab/StdNames.scala b/src/compiler/scala/tools/nsc/symtab/StdNames.scala
index a0b559885a..1dbfb99e95 100644
--- a/src/compiler/scala/tools/nsc/symtab/StdNames.scala
+++ b/src/compiler/scala/tools/nsc/symtab/StdNames.scala
@@ -269,6 +269,7 @@ trait StdNames {
val forceBoxedArray = newTermName("forceBoxedArray")
val checkInitialized = newTermName("checkInitialized")
val classOf = newTermName("classOf")
+ val copy = newTermName("copy")
val dottype = newTermName(".type")
val drop = newTermName("drop")
val elem = newTermName("elem")
diff --git a/src/compiler/scala/tools/nsc/symtab/Symbols.scala b/src/compiler/scala/tools/nsc/symtab/Symbols.scala
index f9bd2ea831..e0b522f400 100644
--- a/src/compiler/scala/tools/nsc/symtab/Symbols.scala
+++ b/src/compiler/scala/tools/nsc/symtab/Symbols.scala
@@ -120,7 +120,6 @@ trait Symbols {
*/
var privateWithin: Symbol = _
-
// Creators -------------------------------------------------------------------
final def newValue(pos: Position, name: Name) =
@@ -207,6 +206,28 @@ trait Symbols {
final def newTypeParameter(pos: Position, name: Name) =
newAbstractType(pos, name).setFlag(PARAM)
+ /** Synthetic value parameters when parameter symbols are not available
+ */
+ final def newSyntheticValueParamss(argtypess: List[List[Type]]): List[List[Symbol]] = {
+ var cnt = 0
+ def freshName() = { cnt += 1; newTermName("x$" + cnt) }
+ def param(tp: Type) =
+ newValueParameter(owner.pos, freshName()).setFlag(SYNTHETIC).setInfo(tp)
+ argtypess map (_.map(param))
+ }
+
+ /** Synthetic value parameters when parameter symbols are not available.
+ * Calling this method multiple times will re-use the same parameter names.
+ */
+ final def newSyntheticValueParams(argtypes: List[Type]): List[Symbol] =
+ newSyntheticValueParamss(List(argtypes)).head
+
+ /** Synthetic value parameter when parameter symbol is not available.
+ * Calling this method multiple times will re-use the same parameter name.
+ */
+ final def newSyntheticValueParam(argtype: Type): Symbol =
+ newSyntheticValueParams(List(argtype)).head
+
/** Type skolems are type parameters ``seen from the inside''
* Given a class C[T]
* Then the class has a TypeParameter with name `T' in its typeParams list
@@ -790,6 +811,10 @@ trait Symbols {
def typeParams: List[Symbol] =
if (isMonomorphicType) List() else { rawInfo.load(this); rawInfo.typeParams }
+ /** The value parameter sections of this symbol.
+ */
+ def paramss: List[List[Symbol]] = info.paramss
+
def getAttributes(clazz: Symbol): List[AnnotationInfo] =
attributes.filter(_.atp.typeSymbol.isNonBottomSubClass(clazz))
@@ -993,6 +1018,13 @@ trait Symbols {
*/
def alias: Symbol = NoSymbol
+ /** For parameter symbols: the method computing its default value, NoSymbol
+ * for all others
+ */
+ def defaultGetter: Symbol = NoSymbol
+ def defaultGetter_=(getter: Symbol): Unit =
+ throw new Error("defaultGetter cannot be set for " + this)
+
/** For a lazy value, it's lazy accessor. NoSymbol for all others */
def lazyAccessor: Symbol = NoSymbol
@@ -1402,8 +1434,8 @@ trait Symbols {
tp match {
case PolyType(tparams, res) =>
typeParamsString + infoString(res)
- case MethodType(pts, res) =>
- pts.mkString("(", ",", ")") + infoString(res)
+ case MethodType(params, res) =>
+ params.map(_.defString).mkString("(", ",", ")") + infoString(res)
case _ =>
": " + tp
}
@@ -1449,10 +1481,12 @@ trait Symbols {
privateWithin = NoSymbol
protected var referenced: Symbol = NoSymbol
+ protected var defGetter: Symbol = NoSymbol
def cloneSymbolImpl(owner: Symbol): Symbol = {
val clone = new TermSymbol(owner, pos, name)
clone.referenced = referenced
+ clone.defGetter = defGetter
clone
}
@@ -1469,6 +1503,10 @@ trait Symbols {
this
}
+ override def defaultGetter = defGetter
+ override def defaultGetter_=(getter: Symbol): Unit =
+ defGetter = getter
+
override def outerSource: Symbol =
if (name endsWith nme.OUTER) initialize.referenced
else NoSymbol
@@ -1769,6 +1807,7 @@ trait Symbols {
def cloneSymbolImpl(owner: Symbol): Symbol = throw new Error()
}
+
def cloneSymbols(syms: List[Symbol]): List[Symbol] = {
val syms1 = syms map (_.cloneSymbol)
for (sym1 <- syms1) sym1.setInfo(sym1.info.substSym(syms, syms1))
diff --git a/src/compiler/scala/tools/nsc/symtab/Types.scala b/src/compiler/scala/tools/nsc/symtab/Types.scala
index 33fdfaf76b..a21dc9b8ac 100644
--- a/src/compiler/scala/tools/nsc/symtab/Types.scala
+++ b/src/compiler/scala/tools/nsc/symtab/Types.scala
@@ -144,6 +144,8 @@ trait Types {
override def isVolatile = underlying.isVolatile
override def finalResultType = underlying.finalResultType
override def paramSectionCount = underlying.paramSectionCount
+ override def paramss = underlying.paramss
+ override def params = underlying.params
override def paramTypes = underlying.paramTypes
override def termSymbol = underlying.termSymbol
override def termSymbolDirect = underlying.termSymbolDirect
@@ -180,6 +182,8 @@ trait Types {
override def resultType(actuals: List[Type]) = maybeRewrap(underlying.resultType(actuals))
override def finalResultType = maybeRewrap(underlying.finalResultType)
override def paramSectionCount = 0
+ override def paramss: List[List[Symbol]] = List()
+ override def params: List[Symbol] = List()
override def paramTypes: List[Type] = List()
override def typeArgs = underlying.typeArgs
override def notNull = maybeRewrap(underlying.notNull)
@@ -308,6 +312,14 @@ trait Types {
* 0 for all other types */
def paramSectionCount: Int = 0
+ /** For a method or poly type, a list of its value parameter sections,
+ * the empty list for all other types */
+ def paramss: List[List[Symbol]] = List()
+
+ /** For a method or poly type, its first value parameter section,
+ * the empty list for all other types */
+ def params: List[Symbol] = List()
+
/** For a method or poly type, the types of its first value parameter section,
* the empty list for all other types */
def paramTypes: List[Type] = List()
@@ -584,8 +596,8 @@ trait Types {
-1
}
- /** If this is a polytype, a copy with cloned type parameters owned
- * by `owner'. Identity for all other types.
+ /** If this is a poly- or methodtype, a copy with cloned type / value parameters
+ * owned by `owner'. Identity for all other types.
*/
def cloneInfo(owner: Symbol) = this
@@ -1608,7 +1620,7 @@ A type's typeSymbol should never be inspected directly.
/** A class representing a method type with parameters.
*/
- case class MethodType(override val paramTypes: List[Type],
+ case class MethodType(override val params: List[Symbol],
override val resultType: Type) extends Type {
override val isTrivial: Boolean =
paramTypes.forall(_.isTrivial) && resultType.isTrivial
@@ -1616,6 +1628,12 @@ A type's typeSymbol should never be inspected directly.
//assert(paramTypes forall (pt => !pt.typeSymbol.isImplClass))//DEBUG
override def paramSectionCount: Int = resultType.paramSectionCount + 1
+ override def paramss: List[List[Symbol]] = params :: resultType.paramss
+
+ override def paramTypes = params map (_.tpe)
+
+ override def boundSyms = params ::: resultType.boundSyms
+
override def resultType(actuals: List[Type]) = {
val map = new InstantiateDeBruijnMap(actuals)
val rawResTpe = map.apply(resultType)
@@ -1628,31 +1646,32 @@ A type's typeSymbol should never be inspected directly.
override def finalResultType: Type = resultType.finalResultType
- protected def paramPrefix = "("
-
private def dependentToString(base: Int): String = {
val params = for ((pt, n) <- paramTypes.zipWithIndex) yield "x$"+n+":"+pt
val res = resultType match {
case mt: MethodType => mt.dependentToString(base + params.length)
case rt => rt.toString
}
- params.mkString(paramPrefix, ",", ")")+res
+ params.mkString("(", ",", ")")+res
}
override def safeToString: String =
if (resultType.isDependent) dependentToString(0)
- else paramTypes.mkString(paramPrefix, ",", ")") + resultType
+ else params.map(_.defString).mkString("(", ",", ")") + resultType
+
+ override def cloneInfo(owner: Symbol) = {
+ val vparams = cloneSymbols(params, owner)
+ copyMethodType(this, vparams, resultType.substSym(params, vparams).cloneInfo(owner))
+ }
override def kind = "MethodType"
}
- // Lukas: check whether we can eliminate this in favor of implicit flags on parameters
+ // todo: this class is no longer needed, a method type is implicit if the first
+ // parameter has the IMPLICIT flag
+ class ImplicitMethodType(ps: List[Symbol], rt: Type) extends MethodType(ps, rt)
- class ImplicitMethodType(pts: List[Type], rt: Type) extends MethodType(pts, rt) {
- override protected def paramPrefix = "(implicit "
- }
-
- class JavaMethodType(pts: List[Type], rt: Type) extends MethodType(pts, rt)
+ class JavaMethodType(ps: List[Symbol], rt: Type) extends MethodType(ps, rt)
/** A class representing a polymorphic type or, if tparams.length == 0,
* a parameterless method type.
@@ -1667,12 +1686,14 @@ A type's typeSymbol should never be inspected directly.
extends Type {
override def paramSectionCount: Int = resultType.paramSectionCount
+ override def paramss: List[List[Symbol]] = resultType.paramss
+ override def params: List[Symbol] = resultType.params
override def paramTypes: List[Type] = resultType.paramTypes
override def parents: List[Type] = resultType.parents
override def decls: Scope = resultType.decls
override def termSymbol: Symbol = resultType.termSymbol
override def typeSymbol: Symbol = resultType.typeSymbol
- override def boundSyms: List[Symbol] = typeParams
+ override def boundSyms: List[Symbol] = typeParams ::: resultType.boundSyms
override def prefix: Type = resultType.prefix
override def baseTypeSeq: BaseTypeSeq = resultType.baseTypeSeq
override def baseTypeSeqDepth: Int = resultType.baseTypeSeqDepth
@@ -1698,7 +1719,7 @@ A type's typeSymbol should never be inspected directly.
override def cloneInfo(owner: Symbol) = {
val tparams = cloneSymbols(typeParams, owner)
- PolyType(tparams, resultType.substSym(typeParams, tparams))
+ PolyType(tparams, resultType.substSym(typeParams, tparams).cloneInfo(owner))
}
override def kind = "PolyType"
@@ -1938,6 +1959,14 @@ A type's typeSymbol should never be inspected directly.
override def kind = "AnnotatedType"
}
+ /** A class representing types with a name. When an application uses
+ * named arguments, the named argument types for calling isApplicable
+ * are represented as NamedType.
+ */
+ case class NamedType(name: Name, tp: Type) extends Type {
+ override def safeToString: String = name.toString +": "+ tp
+ }
+
/** A class representing an as-yet unevaluated type.
*/
abstract class LazyType extends Type {
@@ -2113,12 +2142,19 @@ A type's typeSymbol should never be inspected directly.
}
/** The canonical creator for implicit method types */
- def ImplicitMethodType(paramTypes: List[Type], resultType: Type): ImplicitMethodType =
- new ImplicitMethodType(paramTypes, resultType) // don't unique this!
+ def ImplicitMethodType(params: List[Symbol], resultType: Type): ImplicitMethodType =
+ new ImplicitMethodType(params, resultType) // don't unique this!
/** The canonical creator for implicit method types */
- def JavaMethodType(paramTypes: List[Type], resultType: Type): JavaMethodType =
- new JavaMethodType(paramTypes, resultType) // don't unique this!
+ def JavaMethodType(params: List[Symbol], resultType: Type): JavaMethodType =
+ new JavaMethodType(params, resultType) // don't unique this!
+
+ /** Create a new MethodType of the same class as tp, i.e. keep Java / ImplicitMethodType */
+ def copyMethodType(tp: Type, params: List[Symbol], restpe: Type): Type = tp match {
+ case _: ImplicitMethodType => ImplicitMethodType(params, restpe)
+ case _: JavaMethodType => JavaMethodType(params, restpe)
+ case _ => MethodType(params, restpe)
+ }
/** A creator for intersection type where intersections of a single type are
* replaced by the type itself, and repeated parent classes are merged.
@@ -2409,13 +2445,14 @@ A type's typeSymbol should never be inspected directly.
if ((parents1 eq parents) && (decls1 eq decls)) tp
else cloneDecls(ClassInfoType(parents1, new Scope(), clazz), tp, decls1)
*/
- case MethodType(paramtypes, result) =>
+ case MethodType(params, result) =>
variance = -variance
- val paramtypes1 = List.mapConserve(paramtypes)(this)
+ val params1 = mapOver(params)
variance = -variance
val result1 = this(result)
- if ((paramtypes1 eq paramtypes) && (result1 eq result)) tp
- else copyMethodType(tp, paramtypes1, result1)
+ if ((params1 eq params) && (result1 eq result)) tp
+ // for new dependent types: result1.substSym(params, params1)?
+ else copyMethodType(tp, params1, result1.substSym(params, params1))
case PolyType(tparams, result) =>
variance = -variance
val tparams1 = mapOver(tparams)
@@ -2577,12 +2614,6 @@ A type's typeSymbol should never be inspected directly.
tree1.shallowDuplicate.setType(tpe1)
}
}
-
- protected def copyMethodType(tp: Type, formals: List[Type], restpe: Type): Type = tp match {
- case _: ImplicitMethodType => ImplicitMethodType(formals, restpe)
- case _: JavaMethodType => JavaMethodType(formals, restpe)
- case _ => MethodType(formals, restpe)
- }
}
/** A type map that always returns the input type unchanged */
@@ -2804,10 +2835,13 @@ A type's typeSymbol should never be inspected directly.
else if (matches(from.head, sym)) toType(tp, to.head)
else subst(tp, sym, from.tail, to.tail)
- private def renameBoundSyms(tp: Type) = tp match {
+ private def renameBoundSyms(tp: Type): Type = tp match {
+ case MethodType(ps, restp) =>
+ val ps1 = cloneSymbols(ps)
+ copyMethodType(tp, ps1, renameBoundSyms(restp.substSym(ps, ps1)))
case PolyType(bs, restp) =>
val bs1 = cloneSymbols(bs)
- PolyType(bs1, restp.substSym(bs, bs1))
+ PolyType(bs1, renameBoundSyms(restp.substSym(bs, bs1)))
case ExistentialType(bs, restp) =>
val bs1 = cloneSymbols(bs)
ExistentialType(bs1, restp.substSym(bs, bs1))
@@ -3182,7 +3216,8 @@ A type's typeSymbol should never be inspected directly.
sym
} else {
var rebind0 = pre.findMember(sym.name, BRIDGE, 0, true)(NoSymbol)
- if (rebind0 == NoSymbol) { assert(false, ""+pre+"."+sym+" does no longer exist, phase = "+phase) }
+ if (rebind0 == NoSymbol) {
+ assert(false, ""+pre+"."+sym+" does no longer exist, phase = "+phase) }
/** The two symbols have the same fully qualified name */
def corresponds(sym1: Symbol, sym2: Symbol): Boolean =
sym1.name == sym2.name && (sym1.isPackageClass || corresponds(sym1.owner, sym2.owner))
@@ -3224,6 +3259,10 @@ A type's typeSymbol should never be inspected directly.
if ((pre1 eq pre) && (sym1 eq sym) && (args1 eq args)/* && sym.isExternal*/) tp
else typeRef(pre1, sym1, args1)
}
+ case MethodType(params, restp) =>
+ val restp1 = this(restp)
+ if (restp1 eq restp) tp
+ else copyMethodType(tp, params, restp1)
case PolyType(tparams, restp) =>
val restp1 = this(restp)
if (restp1 eq restp) tp
@@ -3245,7 +3284,6 @@ A type's typeSymbol should never be inspected directly.
else refinedType(parents1, tp.typeSymbol.owner, decls, tp.typeSymbol.owner.pos)
case SuperType(_, _) => mapOver(tp)
case TypeBounds(_, _) => mapOver(tp)
- case MethodType(_, _) => mapOver(tp)
case TypeVar(_, _) => mapOver(tp)
case AnnotatedType(_,_,_) => mapOver(tp)
case NotNullType(_) => mapOver(tp)
@@ -3509,9 +3547,9 @@ A type's typeSymbol should never be inspected directly.
}
//Console.println("is same? " + tp1 + " " + tp2 + " " + tp1.typeSymbol.owner + " " + tp2.typeSymbol.owner)//DEBUG
isSameTypes(parents1, parents2) && isSubScope(ref1, ref2) && isSubScope(ref2, ref1)
- case (MethodType(pts1, res1), MethodType(pts2, res2)) =>
- (pts1.length == pts2.length &&
- isSameTypes(pts1, pts2) &&
+ case (MethodType(params1, res1), MethodType(params2, res2)) =>
+ // new dependent types: probably fix this, use substSym as done for PolyType
+ (isSameTypes(tp1.paramTypes, tp2.paramTypes) &&
res1 =:= res2 &&
tp1.isInstanceOf[ImplicitMethodType] == tp2.isInstanceOf[ImplicitMethodType])
case (PolyType(tparams1, res1), PolyType(tparams2, res2)) =>
@@ -3674,9 +3712,9 @@ A type's typeSymbol should never be inspected directly.
val tp2n = normalizePlus(tp2)
((tp1n ne tp1) || (tp2n ne tp2)) && isSubType(tp1n, tp2n, depth)
})
- case (MethodType(pts1, res1), MethodType(pts2, res2)) =>
- (pts1.length == pts2.length &&
- matchingParams(pts1, pts2, tp1.isInstanceOf[JavaMethodType], tp2.isInstanceOf[JavaMethodType]) &&
+ case (MethodType(params1, res1), MethodType(params2, res2)) =>
+ (params1.length == params2.length &&
+ matchingParams(tp1.paramTypes, tp2.paramTypes, tp1.isInstanceOf[JavaMethodType], tp2.isInstanceOf[JavaMethodType]) &&
(res1 <:< res2) &&
tp1.isInstanceOf[ImplicitMethodType] == tp2.isInstanceOf[ImplicitMethodType])
case (PolyType(tparams1, res1), PolyType(tparams2, res2)) =>
@@ -3793,8 +3831,8 @@ A type's typeSymbol should never be inspected directly.
tparams1.length == tparams2.length &&
matchesType(res1, res2.substSym(tparams2, tparams1), alwaysMatchSimple)
(tp1, tp2) match {
- case (MethodType(pts1, res1), MethodType(pts2, res2)) =>
- matchingParams(pts1, pts2, tp1.isInstanceOf[JavaMethodType], tp2.isInstanceOf[JavaMethodType]) &&
+ case (MethodType(params1, res1), MethodType(params2, res2)) =>
+ matchingParams(tp1.paramTypes, tp2.paramTypes, tp1.isInstanceOf[JavaMethodType], tp2.isInstanceOf[JavaMethodType]) &&
matchesType(res1, res2, alwaysMatchSimple) &&
tp1.isInstanceOf[ImplicitMethodType] == tp2.isInstanceOf[ImplicitMethodType]
case (PolyType(tparams1, res1), PolyType(tparams2, res2)) =>
@@ -4047,8 +4085,8 @@ A type's typeSymbol should never be inspected directly.
List.map2(tparams, List.transpose(matchingBounds(ts, tparams)))
((tparam, bounds) => tparam.cloneSymbol.setInfo(glb(bounds, depth))),
lub0(matchingInstTypes(ts, tparams)))
- case ts @ MethodType(pts, _) :: rest =>
- MethodType(pts, lub0(matchingRestypes(ts, pts)))
+ case ts @ MethodType(params, _) :: rest =>
+ MethodType(params, lub0(matchingRestypes(ts, params map (_.tpe))))
case ts @ TypeBounds(_, _) :: rest =>
mkTypeBounds(glb(ts map (_.bounds.lo), depth), lub(ts map (_.bounds.hi), depth))
case ts0 =>
@@ -4074,7 +4112,7 @@ A type's typeSymbol should never be inspected directly.
val symtypes =
(List.map2(narrowts, syms)
((t, sym) => t.memberInfo(sym).substThis(t.typeSymbol, lubThisType)));
- if (proto.isTerm)
+ if (proto.isTerm) // possible problem: owner of info is still the old one, instead of new refinement class
proto.cloneSymbol(lubRefined.typeSymbol).setInfo(lub(symtypes, decr(depth)))
else if (symtypes.tail forall (symtypes.head =:=))
proto.cloneSymbol(lubRefined.typeSymbol).setInfo(symtypes.head)
@@ -4148,8 +4186,8 @@ A type's typeSymbol should never be inspected directly.
List.map2(tparams, List.transpose(matchingBounds(ts, tparams)))
((tparam, bounds) => tparam.cloneSymbol.setInfo(lub(bounds, depth))),
glb0(matchingInstTypes(ts, tparams)))
- case ts @ MethodType(pts, _) :: rest =>
- MethodType(pts, glb0(matchingRestypes(ts, pts)))
+ case ts @ MethodType(params, _) :: rest =>
+ MethodType(params, glb0(matchingRestypes(ts, params map (_.tpe))))
case ts @ TypeBounds(_, _) :: rest =>
mkTypeBounds(lub(ts map (_.bounds.lo), depth), glb(ts map (_.bounds.hi), depth))
case ts0 =>
@@ -4361,7 +4399,7 @@ A type's typeSymbol should never be inspected directly.
*/
private def matchingRestypes(tps: List[Type], pts: List[Type]): List[Type] =
tps map {
- case MethodType(pts1, res) if (isSameTypes(pts1, pts)) =>
+ case MethodType(params1, res) if (isSameTypes(params1 map (_.tpe), pts)) =>
res
case _ =>
throw new NoCommonType(tps)
diff --git a/src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala b/src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala
index 110bf32a46..9df9dc77f9 100644
--- a/src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala
+++ b/src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala
@@ -255,9 +255,9 @@ abstract class ClassfileParser {
var tpe = getType(in.getChar(start + 3))
if (name == nme.CONSTRUCTOR)
tpe match {
- case MethodType(formals, restpe) =>
+ case MethodType(params, restpe) =>
assert(restpe.typeSymbol == definitions.UnitClass)
- tpe = MethodType(formals, ownerTpe)
+ tpe = MethodType(params, ownerTpe)
}
p = (name, tpe)
@@ -295,8 +295,10 @@ abstract class ClassfileParser {
c
}
- def getType(index: Int): Type =
- sigToType(null, getExternalName(index))
+ def getType(index: Int): Type = getType(null, index)
+
+ def getType(sym: Symbol, index: Int): Type =
+ sigToType(sym, getExternalName(index))
def getSuperClass(index: Int): Symbol =
if (index == 0) definitions.AnyClass else getClassSymbol(index)
@@ -431,10 +433,10 @@ abstract class ClassfileParser {
if (isAnnotation) {
val value = instanceDefs.lookup(nme.value)
if (value != NoSymbol) {
- instanceDefs.enter(
- clazz.newConstructor(NoPosition)
+ val constr = clazz.newConstructor(NoPosition)
+ instanceDefs.enter(constr
.setFlag(clazz.flags & ConstrFlags)
- .setInfo(MethodType(List(value.tpe.resultType), clazz.tpe)))
+ .setInfo(MethodType(constr.newSyntheticValueParams(List(value.tpe.resultType)), clazz.tpe)))
}
}
}
@@ -488,23 +490,22 @@ abstract class ClassfileParser {
in.skip(4); skipAttributes()
} else {
val name = pool.getName(in.nextChar)
- var info = pool.getType(in.nextChar)
+ val sym = getOwner(jflags).newMethod(NoPosition, name).setFlag(sflags)
+ var info = pool.getType(sym, (in.nextChar))
if (name == nme.CONSTRUCTOR)
info match {
- case MethodType(formals, restpe) =>
- assert(restpe.typeSymbol == definitions.UnitClass)
+ case MethodType(params, restpe) =>
// if this is a non-static inner class, remove the explicit outer parameter
- val newFormals = innerClasses.get(externalName) match {
+ val newParams = innerClasses.get(externalName) match {
case Some(entry) if !isScalaRaw && (entry.jflags & JAVA_ACC_STATIC) == 0 =>
- assert(formals.head.typeSymbol == clazz.owner, formals.head.typeSymbol + ": " + clazz.owner)
- formals.tail
+ assert(params.head.tpe.typeSymbol == clazz.owner, params.head.tpe.typeSymbol + ": " + clazz.owner)
+ params.tail
case _ =>
- formals
+ params
}
- info = MethodType(newFormals, clazz.tpe)
+ info = MethodType(newParams, clazz.tpe)
}
- val sym = getOwner(jflags)
- .newMethod(NoPosition, name).setFlag(sflags).setInfo(info)
+ sym.setInfo(info)
setPrivateWithin(sym, jflags)
parseAttributes(sym, info)
if ((jflags & JAVA_ACC_VARARGS) != 0) {
@@ -518,12 +519,13 @@ abstract class ClassfileParser {
/** Convert repeated parameters to arrays if they occur as part of a Java method
*/
private def arrayToRepeated(tp: Type): Type = tp match {
- case MethodType(formals, rtpe) =>
+ case MethodType(params, rtpe) =>
+ val formals = tp.paramTypes
assert(formals.last.typeSymbol == definitions.ArrayClass)
- MethodType(
- formals.init :::
- List(appliedType(definitions.RepeatedParamClass.typeConstructor, List(formals.last.typeArgs.head))),
- rtpe)
+ val method = params.last.owner
+ val newParams = method.newSyntheticValueParams(formals.init :::
+ List(appliedType(definitions.RepeatedParamClass.typeConstructor, List(formals.last.typeArgs.head))))
+ MethodType(newParams, rtpe)
case PolyType(tparams, rtpe) =>
PolyType(tparams, arrayToRepeated(rtpe))
}
@@ -619,6 +621,8 @@ abstract class ClassfileParser {
while ('0' <= sig(index) && sig(index) <= '9') index += 1
appliedType(definitions.ArrayClass.tpe, List(sig2type(tparams, skiptvs)))
case '(' =>
+ // we need a method symbol. given in line 486 by calling getType(methodSym, ..)
+ assert(sym ne null)
val paramtypes = new ListBuffer[Type]()
while (sig(index) != ')') {
paramtypes += objToAny(sig2type(tparams, skiptvs))
@@ -629,7 +633,7 @@ abstract class ClassfileParser {
clazz.tpe
} else
sig2type(tparams, skiptvs)
- JavaMethodType(paramtypes.toList, restype)
+ JavaMethodType(sym.newSyntheticValueParams(paramtypes.toList), restype)
case 'T' =>
val n = subName(';'.==).toTypeName
index += 1
diff --git a/src/compiler/scala/tools/nsc/symtab/classfile/MetaParser.scala b/src/compiler/scala/tools/nsc/symtab/classfile/MetaParser.scala
index c52cc236fe..905a473a96 100644
--- a/src/compiler/scala/tools/nsc/symtab/classfile/MetaParser.scala
+++ b/src/compiler/scala/tools/nsc/symtab/classfile/MetaParser.scala
@@ -134,7 +134,10 @@ abstract class MetaParser{
def parse(): Type = {
nextToken();
if (token == "[") PolyType(parseTypeParams(), parse())
- else if (token == "(") MethodType(parseParams(), parse())
+ else if (token == "(") {
+ val formals = parseParams()
+ MethodType(owner.newSyntheticValueParams(formals), parse())
+ }
else parseType()
}
owner.setInfo(parse())
@@ -151,7 +154,10 @@ abstract class MetaParser{
protected def parseConstr() {
def parse(): Type = {
nextToken()
- if (token == "(") MethodType(parseParams(), parse())
+ if (token == "(") {
+ val formals = parseParams()
+ MethodType(owner.newSyntheticValueParams(formals), parse())
+ }
else owner.owner.tpe
}
owner.setInfo(parse())
diff --git a/src/compiler/scala/tools/nsc/symtab/classfile/PickleFormat.scala b/src/compiler/scala/tools/nsc/symtab/classfile/PickleFormat.scala
index 28accffa02..799c19c53f 100644
--- a/src/compiler/scala/tools/nsc/symtab/classfile/PickleFormat.scala
+++ b/src/compiler/scala/tools/nsc/symtab/classfile/PickleFormat.scala
@@ -26,7 +26,8 @@ object PickleFormat {
* | 5 ALIASsym len_Nat SymbolInfo
* | 6 CLASSsym len_Nat SymbolInfo [thistype_Ref]
* | 7 MODULEsym len_Nat SymbolInfo
- * | 8 VALsym len_Nat SymbolInfo [alias_Ref]
+ * | 8 VALsym len_Nat SymbolInfo [alias_Ref] // old VALsym, unPickling supported (checkin if minor version < 2) ** @LUC TODO remove
+ * | 8 VALsym len_Nat [defaultGetter_Ref] SymbolInfo [alias_Ref]
* | 9 EXTref len_Nat name_Ref [owner_Ref]
* | 10 EXTMODCLASSref len_Nat name_Ref [owner_Ref]
* | 11 NOtpe len_Nat
@@ -38,7 +39,8 @@ object PickleFormat {
* | 17 TYPEBOUNDStpe len_Nat tpe_Ref tpe_Ref
* | 18 REFINEDtpe len_Nat classsym_Ref {tpe_Ref}
* | 19 CLASSINFOtpe len_Nat classsym_Ref {tpe_Ref}
- * | 20 METHODtpe len_Nat tpe_Ref {tpe_Ref}
+ * | 20 METHODtpe len_Nat tpe_Ref {tpe_Ref} // old method type, unPickling still supported ** @LUC TODO remove
+ * | 20 METHODtpe len_Nat tpe_Ref {sym_Ref} // new method type
* | 21 POLYTtpe len_Nat tpe_Ref {sym_Ref}
* | 22 IMPLICITMETHODtpe len_Nat tpe_Ref {tpe_Ref}
* | 24 LITERALunit len_Nat
diff --git a/src/compiler/scala/tools/nsc/symtab/classfile/Pickler.scala b/src/compiler/scala/tools/nsc/symtab/classfile/Pickler.scala
index 052fe1647e..b82417c4a3 100644
--- a/src/compiler/scala/tools/nsc/symtab/classfile/Pickler.scala
+++ b/src/compiler/scala/tools/nsc/symtab/classfile/Pickler.scala
@@ -133,6 +133,7 @@ abstract class Pickler extends SubComponent {
if (sym.thisSym.tpeHK != sym.tpeHK)
putType(sym.typeOfThis);
putSymbol(sym.alias)
+ putSymbol(sym.defaultGetter)
if (!sym.children.isEmpty) {
val (locals, globals) = sym.children.toList.partition(_.isLocalClass)
val children =
@@ -183,8 +184,8 @@ abstract class Pickler extends SubComponent {
putSymbol(rclazz); putTypes(parents); putSymbols(decls.toList)
case ClassInfoType(parents, decls, clazz) =>
putSymbol(clazz); putTypes(parents); putSymbols(decls.toList)
- case MethodType(formals, restpe) =>
- putType(restpe); putTypes(formals)
+ case MethodType(params, restpe) =>
+ putType(restpe); putSymbols(params)
case PolyType(tparams, restpe) =>
putType(restpe); putSymbols(tparams)
case ExistentialType(tparams, restpe) =>
@@ -522,6 +523,8 @@ abstract class Pickler extends SubComponent {
val posOffset = writeSymInfo(sym)
(if (sym.isAbstractType) TYPEsym else ALIASsym) + posOffset
case sym: TermSymbol =>
+ if (!sym.isModule && sym.defaultGetter != NoSymbol)
+ writeRef(sym.defaultGetter)
val posOffset = writeSymInfo(sym)
if (sym.alias != NoSymbol) writeRef(sym.alias)
(if (sym.isModule) MODULEsym else VALsym) + posOffset
@@ -1004,6 +1007,7 @@ abstract class Pickler extends SubComponent {
case sym: TermSymbol =>
print(if (sym.isModule) "MODULEsym " else "VALsym ")
printSymInfo(sym)
+ if (!sym.isModule) printRef(sym.defaultGetter)
if (sym.alias != NoSymbol) printRef(sym.alias)
case NoType =>
print("NOtpe")
diff --git a/src/compiler/scala/tools/nsc/symtab/classfile/UnPickler.scala b/src/compiler/scala/tools/nsc/symtab/classfile/UnPickler.scala
index 1e368b9664..3db8b4ea6f 100644
--- a/src/compiler/scala/tools/nsc/symtab/classfile/UnPickler.scala
+++ b/src/compiler/scala/tools/nsc/symtab/classfile/UnPickler.scala
@@ -197,7 +197,13 @@ abstract class UnPickler {
if (tag > PosOffset) readNat
else -1
}
- val name = readNameRef()
+ var defaultGetter: Symbol = NoSymbol
+ var nameref = readNat()
+ if (tag == VALsym && isSymbolRef(nameref)) {
+ defaultGetter = at(nameref, readSymbol)
+ nameref = readNat()
+ }
+ val name = at(nameref, readName)
val owner = readSymbolRef()
val flags = pickledToRawFlags(readLongNat())
var privateWithin: Symbol = NoSymbol
@@ -234,6 +240,7 @@ abstract class UnPickler {
case VALsym =>
sym = if (name == moduleRoot.name && owner == moduleRoot.owner) moduleRoot.resetFlag(MODULE)
else owner.newValue(NoPosition, name)
+ sym.defaultGetter = defaultGetter
case _ =>
errorBadSignature("bad symbol tag: " + tag)
}
@@ -288,10 +295,38 @@ abstract class UnPickler {
ClassInfoType(until(end, readTypeRef), symScope(clazz), clazz)
case METHODtpe =>
val restpe = readTypeRef()
- MethodType(until(end, readTypeRef), restpe)
+
+ // compatibility with old format. TODO replace by "until(end, readSymbolRef)"
+ val params = if (readIndex == end) List[Symbol]()
+ else {
+ val index = readNat()
+ if (isSymbolRef(index))
+ at(index, readSymbol) :: until(end, readSymbolRef)
+ else {
+ val formals = at(index, readType) :: until(end, readTypeRef)
+ // @LUC TODO the owner should be the method symbol, and newSyntheticValueParams
+ // should only be called once, not separately for each parameter list
+ val dummyMethod = new TermSymbol(NoSymbol, NoPosition, "unPickler$dummy")
+ dummyMethod.newSyntheticValueParams(formals)
+ }
+ }
+ MethodType(params, restpe)
case IMPLICITMETHODtpe =>
val restpe = readTypeRef()
- ImplicitMethodType(until(end, readTypeRef), restpe)
+ val params = if (readIndex == end) List[Symbol]()
+ else {
+ val index = readNat()
+ if (isSymbolRef(index))
+ at(index, readSymbol) :: until(end, readSymbolRef)
+ else {
+ val formals = until(end, readTypeRef)
+ // @LUC TODO the owner should be the method symbol, and newSyntheticValueParams
+ // should only be called once, not separately for each parameter list
+ val dummyMethod = new TermSymbol(NoSymbol, NoPosition, "unPickler$dummy")
+ dummyMethod.newSyntheticValueParams(formals)
+ }
+ }
+ ImplicitMethodType(params, restpe)
case POLYtpe =>
val restpe = readTypeRef()
PolyType(until(end, readSymbolRef), restpe)
diff --git a/src/compiler/scala/tools/nsc/symtab/clr/TypeParser.scala b/src/compiler/scala/tools/nsc/symtab/clr/TypeParser.scala
index 81b2df32ee..d6f3b37328 100644
--- a/src/compiler/scala/tools/nsc/symtab/clr/TypeParser.scala
+++ b/src/compiler/scala/tools/nsc/symtab/clr/TypeParser.scala
@@ -159,10 +159,11 @@ abstract class TypeParser {
gparamsLength = gparams.length;
val name: Name = if (gparamsLength == 0) prop.Name else nme.apply;
val flags = translateAttributes(getter);
- val mtype: Type = if (gparamsLength == 0) PolyType(List(), propType)
- else methodType(getter, getter.ReturnType);
val owner: Symbol = if (getter.IsStatic) statics else clazz;
- val methodSym = owner.newMethod(NoPosition, name).setFlag(flags).setInfo(mtype);
+ val methodSym = owner.newMethod(NoPosition, name).setFlag(flags)
+ val mtype: Type = if (gparamsLength == 0) PolyType(List(), propType)
+ else methodType(getter, getter.ReturnType)(methodSym)
+ methodSym.setInfo(mtype);
methodSym.setFlag(Flags.ACCESSOR);
(if (getter.IsStatic) staticDefs else instanceDefs).enter(methodSym)
clrTypes.methods(methodSym) = getter;
@@ -181,9 +182,10 @@ abstract class TypeParser {
val name: Name = if (gparamsLength == 0) nme.getterToSetter(prop.Name)
else nme.update;
val flags = translateAttributes(setter);
- val mtype: Type = methodType(setter, definitions.UnitClass.tpe);
+ val mtype = methodType(setter, definitions.UnitClass.tpe);
val owner: Symbol = if (setter.IsStatic) statics else clazz;
- val methodSym = owner.newMethod(NoPosition, name).setFlag(flags).setInfo(mtype);
+ val methodSym = owner.newMethod(NoPosition, name).setFlag(flags)
+ methodSym.setInfo(mtype(methodSym))
methodSym.setFlag(Flags.ACCESSOR);
(if (setter.IsStatic) staticDefs else instanceDefs).enter(methodSym);
clrTypes.methods(methodSym) = setter;
@@ -234,13 +236,13 @@ abstract class TypeParser {
// create the box/unbox methods for value types
if (typ.IsValueType) {
- val box = statics.newMethod(NoPosition, nme.box).
- setInfo(MethodType(List(clazz.tpe), definitions.ObjectClass.tpe));
- definitions.boxMethod(clazz) = box;
- val unbox = statics.newMethod(NoPosition, nme.unbox).
- setInfo(MethodType(List(definitions.ObjectClass.tpe), clazz.tpe));
- definitions.unboxMethod(clazz) = unbox;
- //Console.println(typ.FullName + " : " + parents);
+ val box = statics.newMethod(NoPosition, nme.box)
+ box.setInfo(MethodType(box.newSyntheticValueParams(List(clazz.tpe)), definitions.ObjectClass.tpe))
+ definitions.boxMethod(clazz) = box
+ val unbox = statics.newMethod(NoPosition, nme.unbox)
+ unbox.setInfo(MethodType(unbox.newSyntheticValueParams(List(definitions.ObjectClass.tpe)), clazz.tpe))
+ definitions.unboxMethod(clazz) = unbox
+ //Console.println(typ.FullName + " : " + parents)
}
// for enumerations introduce comparison and bitwise logical operations;
@@ -253,17 +255,17 @@ abstract class TypeParser {
val flags = Flags.JAVA | Flags.FINAL
for (cmpName <- ENUM_CMP_NAMES) {
- val enumCmpType: Type = JavaMethodType(List(clazz.tpe), definitions.BooleanClass.tpe);
- val enumCmp: Symbol = clazz.newMethod(NoPosition, cmpName);
- enumCmp.setFlag(flags).setInfo(enumCmpType)
- instanceDefs.enter(enumCmp);
+ val enumCmp = clazz.newMethod(NoPosition, cmpName)
+ val enumCmpType = JavaMethodType(enumCmp.newSyntheticValueParams(List(clazz.tpe)), definitions.BooleanClass.tpe)
+ enumCmp.setFlag(flags).setInfo(enumCmpType)
+ instanceDefs.enter(enumCmp)
}
for (bitLogName <- ENUM_BIT_LOG_NAMES) {
- val enumBitLogType = JavaMethodType(List(clazz.tpe), classInfo);
- val enumBitLog = clazz.newMethod(NoPosition, bitLogName);
- enumBitLog.setFlag(flags).setInfo(enumBitLogType);
- instanceDefs.enter(enumBitLog);
+ val enumBitLog = clazz.newMethod(NoPosition, bitLogName)
+ val enumBitLogType = JavaMethodType(enumBitLog.newSyntheticValueParams(List(clazz.tpe)), classInfo)
+ enumBitLog.setFlag(flags).setInfo(enumBitLogType)
+ instanceDefs.enter(enumBitLog)
}
}
@@ -277,8 +279,8 @@ abstract class TypeParser {
if (mtype == null) return;
val flags = translateAttributes(method);
val owner = if (method.IsStatic()) statics else clazz;
- val methodSym = owner.newMethod(NoPosition, getName(method)).setFlag(flags).
- setInfo(mtype);
+ val methodSym = owner.newMethod(NoPosition, getName(method)).setFlag(flags)
+ methodSym.setInfo(mtype(methodSym))
(if (method.IsStatic()) staticDefs else instanceDefs).enter(methodSym);
if (method.IsConstructor())
clrTypes.constructors(methodSym) = method.asInstanceOf[ConstructorInfo]
@@ -286,17 +288,17 @@ abstract class TypeParser {
}
private def createMethod(name: Name, flags: Long, args: Array[MSILType], retType: MSILType, method: MethodInfo, statik: Boolean): Symbol = {
- val mtype: Type = methodType(args, getCLSType(retType));
- assert(mtype != null);
+ val mtype = methodType(args, getCLSType(retType))
+ assert(mtype != null)
createMethod(name, flags, mtype, method, statik)
}
- private def createMethod(name: Name, flags: Long, mtype: Type, method: MethodInfo, statik: Boolean): Symbol = {
- val methodSym: Symbol = (if (statik) statics else clazz).newMethod(NoPosition, name);
- methodSym.setFlag(flags).setInfo(mtype);
- (if (statik) staticDefs else instanceDefs).enter(methodSym);
+ private def createMethod(name: Name, flags: Long, mtype: Symbol => Type, method: MethodInfo, statik: Boolean): Symbol = {
+ val methodSym: Symbol = (if (statik) statics else clazz).newMethod(NoPosition, name)
+ methodSym.setFlag(flags).setInfo(mtype(methodSym))
+ (if (statik) staticDefs else instanceDefs).enter(methodSym)
if (method != null)
- clrTypes.methods(methodSym) = method;
+ clrTypes.methods(methodSym) = method
methodSym
}
@@ -312,12 +314,12 @@ abstract class TypeParser {
// create the forward view: delegate => function
val delegateParamTypes: List[Type] = List(typClrType);
// not ImplicitMethodType, this is for methods with implicit parameters (not implicit methods)
- val forwardViewMethodType = JavaMethodType(delegateParamTypes, funType);
+ val forwardViewMethodType = (msym: Symbol) => JavaMethodType(msym.newSyntheticValueParams(delegateParamTypes), funType)
val fmsym = createMethod(nme.view_, flags, forwardViewMethodType, null, true);
// create the backward view: function => delegate
val functionParamTypes: List[Type] = List(funType);
- val backwardViewMethodType = JavaMethodType(functionParamTypes, typClrType);
+ val backwardViewMethodType = (msym: Symbol) => JavaMethodType(msym.newSyntheticValueParams(functionParamTypes), typClrType)
val bmsym = createMethod(nme.view_, flags, backwardViewMethodType, null, true);
}
@@ -350,23 +352,23 @@ abstract class TypeParser {
//##########################################################################
- private def methodType(method: MethodBase, rettype: MSILType): Type = {
+ private def methodType(method: MethodBase, rettype: MSILType): Symbol => Type = {
val rtype = getCLSType(rettype);
if (rtype == null) null else methodType(method, rtype);
}
/** Return a method type for the given method. */
- private def methodType(method: MethodBase, rettype: Type): Type =
+ private def methodType(method: MethodBase, rettype: Type): Symbol => Type =
methodType(method.GetParameters().map(_.ParameterType), rettype);
/** Return a method type for the provided argument types and return type. */
- private def methodType(argtypes: Array[MSILType], rettype: Type): Type = {
+ private def methodType(argtypes: Array[MSILType], rettype: Type): Symbol => Type = method => {
def paramType(typ: MSILType): Type =
if (typ eq clrTypes.OBJECT) definitions.AnyClass.tpe
else getCLSType(typ);
val ptypes = argtypes.map(paramType).toList;
if (ptypes.contains(null)) null
- else JavaMethodType(ptypes, rettype);
+ else JavaMethodType(method.newSyntheticValueParams(ptypes), rettype);
}
//##########################################################################
diff --git a/src/compiler/scala/tools/nsc/transform/AddInterfaces.scala b/src/compiler/scala/tools/nsc/transform/AddInterfaces.scala
index 16821e874f..f009f69f4a 100644
--- a/src/compiler/scala/tools/nsc/transform/AddInterfaces.scala
+++ b/src/compiler/scala/tools/nsc/transform/AddInterfaces.scala
@@ -225,11 +225,11 @@ abstract class AddInterfaces extends InfoTransform {
private def ifaceMemberDef(tree: Tree): Tree =
if (!tree.isDef || !isInterfaceMember(tree.symbol)) EmptyTree
- else if (needsImplMethod(tree.symbol)) DefDef(tree.symbol, vparamss => EmptyTree)
+ else if (needsImplMethod(tree.symbol)) DefDef(tree.symbol, EmptyTree)
else tree
private def ifaceTemplate(templ: Template): Template =
- copy.Template(templ, templ.parents, emptyValDef, templ.body map ifaceMemberDef)
+ treeCopy.Template(templ, templ.parents, emptyValDef, templ.body map ifaceMemberDef)
private def implMethodDef(tree: Tree, ifaceMethod: Symbol): Tree =
implMethodMap.get(ifaceMethod) match {
@@ -251,7 +251,7 @@ abstract class AddInterfaces extends InfoTransform {
*/
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
+ else DefDef(clazz.primaryConstructor, Block(List(), Literal(()))) :: stats
private def implTemplate(clazz: Symbol, templ: Template): Template = atPos(templ.pos) {
val templ1 = atPos(templ.pos) {
@@ -296,7 +296,7 @@ abstract class AddInterfaces extends InfoTransform {
case Block(stats, expr) =>
val (presuper, supercall :: rest) = stats span (_.symbol.hasFlag(PRESUPER))
//assert(supercall.symbol.isClassConstructor, supercall)
- copy.Block(tree, presuper ::: (supercall :: mixinConstructorCalls ::: rest), expr)
+ treeCopy.Block(tree, presuper ::: (supercall :: mixinConstructorCalls ::: rest), expr)
}
}
@@ -309,14 +309,14 @@ abstract class AddInterfaces extends InfoTransform {
val tree1 = tree match {
case ClassDef(mods, name, tparams, impl) if (sym.needsImplClass) =>
implClass(sym).initialize // to force lateDEFERRED flags
- copy.ClassDef(tree, mods | INTERFACE, name, tparams, ifaceTemplate(impl))
+ treeCopy.ClassDef(tree, mods | INTERFACE, name, tparams, ifaceTemplate(impl))
case DefDef(mods, name, tparams, vparamss, tpt, rhs)
if (sym.isClassConstructor && sym.isPrimaryConstructor && sym.owner != ArrayClass) =>
- copy.DefDef(tree, mods, name, tparams, vparamss, tpt,
+ treeCopy.DefDef(tree, mods, name, tparams, vparamss, tpt,
addMixinConstructorCalls(rhs, sym.owner)) // (3)
case Template(parents, self, body) =>
val parents1 = sym.owner.info.parents map (t => TypeTree(t) setPos tree.pos)
- copy.Template(tree, parents1, emptyValDef, body)
+ treeCopy.Template(tree, parents1, emptyValDef, body)
case This(_) =>
if (sym.needsImplClass) {
val impl = implClass(sym)
@@ -338,7 +338,7 @@ abstract class AddInterfaces extends InfoTransform {
else mix
}
if (sym.needsImplClass) Super(implClass(sym), mix1) setPos tree.pos
- else copy.Super(tree, qual, mix1)
+ else treeCopy.Super(tree, qual, mix1)
*/
case _ =>
tree
diff --git a/src/compiler/scala/tools/nsc/transform/CleanUp.scala b/src/compiler/scala/tools/nsc/transform/CleanUp.scala
index d99518c6cf..fd3257333c 100644
--- a/src/compiler/scala/tools/nsc/transform/CleanUp.scala
+++ b/src/compiler/scala/tools/nsc/transform/CleanUp.scala
@@ -69,11 +69,10 @@ abstract class CleanUp extends Transform {
val mdef =
localTyper.typed {
atPos(pos) {
- DefDef(meth, vparamss =>
- gen.mkCached(
- cvar,
- Apply(
- gen.mkAttributedRef(forName), List(Literal(sig)))))
+ DefDef(meth, gen.mkCached(
+ cvar,
+ Apply(
+ gen.mkAttributedRef(forName), List(Literal(sig)))))
}
}
@@ -155,12 +154,12 @@ abstract class CleanUp extends Transform {
(forBody: Pair[Symbol, List[Symbol]] => Tree): Symbol = {
val methSym = currentClass.newMethod(ad.pos, unit.fresh.newName(ad.pos, forName))
.setFlag(STATIC | SYNTHETIC)
- .setInfo(MethodType(forArgsTypes, forResultType))
+ methSym.setInfo(MethodType(methSym.newSyntheticValueParams(forArgsTypes), forResultType))
currentClass.info.decls.enter(methSym)
val methDef =
localTyper.typed {
atPos(ad.pos) {
- DefDef(methSym, { vparamss => forBody(Pair(methSym, vparamss(0))) })
+ DefDef(methSym, { forBody(Pair(methSym, methSym.paramss(0))) })
}
}
newDefs.append(transform(methDef))
@@ -593,12 +592,12 @@ abstract class CleanUp extends Transform {
ValDef(tmpVar, transform(qual))),
If(Apply(Select(gen.mkAttributedRef(cachedClass), nme.EQ), List(getClass(Ident(tmpVar)))),
Block(List(Assign(gen.mkAttributedRef(cachedClass), getClass(Ident(tmpVar)))),
- copy.ApplyDynamic(ad, Ident(tmpVar), transformTrees(params))),
+ treeCopy.ApplyDynamic(ad, Ident(tmpVar), transformTrees(params))),
EmptyTree)))
}
//println(guardCallSite)
*/
- localTyper.typed(copy.ApplyDynamic(ad, transform(qual), transformTrees(params)))
+ localTyper.typed(treeCopy.ApplyDynamic(ad, transform(qual), transformTrees(params)))
} else {
/* ### BODY OF THE TRANSFORMATION -> remember we're in case ad@ApplyDynamic(qual, params) ### */
@@ -625,8 +624,8 @@ abstract class CleanUp extends Transform {
* because invoke only returns object and erasure made sure the result is
* expected to be an AnyRef. */
val t: Tree = ad.symbol.tpe match {
- case MethodType(paramTypes, resType) =>
- assert(params.length == paramTypes.length)
+ case MethodType(mparams, resType) =>
+ assert(params.length == mparams.length)
atPos(ad.pos)(localTyper.typed {
val t1 = newTermName(unit.fresh.newName(ad.pos, "qual"))
val sym = currentOwner.newValue(ad.pos, t1) setInfo qual0.tpe
@@ -635,9 +634,9 @@ abstract class CleanUp extends Transform {
List(ValDef(sym, qual0)),
fixResult(if (isValueClass(resType.typeSymbol)) boxedClass(resType.typeSymbol).tpe else resType) {
if (mayRequirePrimitiveReplacement)
- callAsOperator(paramTypes, resType)
+ callAsOperator(mparams map (_.tpe), resType)
else
- callAsMethod(paramTypes, resType)
+ callAsMethod(mparams map (_.tpe), resType)
}
)
})
@@ -651,10 +650,10 @@ abstract class CleanUp extends Transform {
"(" + params.map(_.toString).mkString(", ") + ")' with"
)
ad.symbol.tpe match {
- case MethodType(paramTypes, resType) =>
+ case MethodType(mparams, resType) =>
Console.println(
" - declared parameters' types: " +
- (paramTypes.map(_.toString)).mkString("'",", ","'"))
+ (mparams.map(_.toString)).mkString("'",", ","'"))
Console.println(
" - passed arguments' types: " +
(params.map(_.toString)).mkString("'",", ","'"))
@@ -695,14 +694,14 @@ abstract class CleanUp extends Transform {
case thePrimaryConstructor@DefDef(mods, name, tparams, vparamss, tpt, rhs) if (thePrimaryConstructor == firstConstructor) =>
val newRhs = rhs match {
case theRhs@Block(stats, expr) =>
- copy.Block(theRhs, transformTrees(newInits.toList) ::: stats, expr)
+ treeCopy.Block(theRhs, transformTrees(newInits.toList) ::: stats, expr)
}
- copy.DefDef(thePrimaryConstructor, mods, name, tparams, vparamss, tpt, newRhs)
+ treeCopy.DefDef(thePrimaryConstructor, mods, name, tparams, vparamss, tpt, newRhs)
case notThePrimaryConstructor =>
notThePrimaryConstructor
}
)
- copy.Template(tree, parents, self, newBody)
+ treeCopy.Template(tree, parents, self, newBody)
}
else super.transform(tree)
diff --git a/src/compiler/scala/tools/nsc/transform/Constructors.scala b/src/compiler/scala/tools/nsc/transform/Constructors.scala
index 47256ca8bc..d5ace3c4f6 100644
--- a/src/compiler/scala/tools/nsc/transform/Constructors.scala
+++ b/src/compiler/scala/tools/nsc/transform/Constructors.scala
@@ -179,7 +179,7 @@ abstract class Constructors extends Transform {
// all methods except the primary constructor go into template
stat.symbol.tpe match {
case MethodType(List(), tp @ ConstantType(c)) =>
- defBuf += copy.DefDef(
+ defBuf += treeCopy.DefDef(
stat, mods, name, tparams, vparamss, tpt,
Literal(c) setPos rhs.pos setType tp)
case _ =>
@@ -198,7 +198,7 @@ abstract class Constructors extends Transform {
(if (canBeMoved(stat)) constrPrefixBuf else constrStatBuf) += mkAssign(
stat.symbol, rhs1)
}
- defBuf += copy.ValDef(stat, mods, name, tpt, EmptyTree)
+ defBuf += treeCopy.ValDef(stat, mods, name, tpt, EmptyTree)
}
case ClassDef(_, _, _, _) =>
// classes are treated recursively, and left in the template
@@ -278,9 +278,9 @@ abstract class Constructors extends Transform {
}
// Assemble final constructor
- defBuf += copy.DefDef(
+ defBuf += treeCopy.DefDef(
constr, constr.mods, constr.name, constr.tparams, constr.vparamss, constr.tpt,
- copy.Block(
+ treeCopy.Block(
constrBody,
paramInits ::: constrPrefixBuf.toList ::: constrStatBuf.toList,
constrBody.expr));
@@ -290,14 +290,14 @@ abstract class Constructors extends Transform {
if (!mustbeKept(sym)) clazz.info.decls unlink sym
// Eliminate all field definitions that can be dropped from template
- copy.Template(impl, impl.parents, impl.self,
+ treeCopy.Template(impl, impl.parents, impl.self,
defBuf.toList filter (stat => mustbeKept(stat.symbol)))
} // transformClassTemplate
override def transform(tree: Tree): Tree =
tree match {
case ClassDef(mods, name, tparams, impl) if !tree.symbol.hasFlag(INTERFACE) =>
- copy.ClassDef(tree, mods, name, tparams, transformClassTemplate(impl))
+ treeCopy.ClassDef(tree, mods, name, tparams, transformClassTemplate(impl))
case _ =>
super.transform(tree)
}
diff --git a/src/compiler/scala/tools/nsc/transform/Erasure.scala b/src/compiler/scala/tools/nsc/transform/Erasure.scala
index e300b81576..7330b9c9e8 100644
--- a/src/compiler/scala/tools/nsc/transform/Erasure.scala
+++ b/src/compiler/scala/tools/nsc/transform/Erasure.scala
@@ -90,13 +90,13 @@ abstract class Erasure extends AddInterfaces with typechecker.Analyzer {
apply(restpe)
case ExistentialType(tparams, restpe) =>
apply(restpe)
- case mt @ MethodType(formals, restpe) =>
+ case mt @ MethodType(params, restpe) =>
MethodType(
- formals map apply,
+ cloneSymbols(params) map (p => p.setInfo(apply(p.tpe))),
if (restpe.typeSymbol == UnitClass)
erasedTypeRef(UnitClass)
else if (settings.Xexperimental.value)
- apply(mt.resultType(formals)) // this gets rid of DeBruijnTypes
+ apply(mt.resultType(params map (_.tpe))) // this gets rid of DeBruijnTypes
else
apply(restpe))
case RefinedType(parents, decls) =>
@@ -229,8 +229,8 @@ abstract class Erasure extends AddInterfaces with typechecker.Analyzer {
assert(!tparams.isEmpty)
def paramSig(tsym: Symbol) = tsym.name+boundSig(hiBounds(tsym.info.bounds))
(if (toplevel) "<"+(tparams map paramSig).mkString+">" else "")+jsig(restpe)
- case MethodType(formals, restpe) =>
- "("+(formals map jsig).mkString+")"+
+ case MethodType(params, restpe) =>
+ "("+(params map (_.tpe) map jsig).mkString+")"+
(if (restpe.typeSymbol == UnitClass || sym.isConstructor) VOID_TAG.toString else jsig(restpe))
case RefinedType(parents, decls) if (!parents.isEmpty) =>
jsig(parents.head)
@@ -305,17 +305,27 @@ abstract class Erasure extends AddInterfaces with typechecker.Analyzer {
else if (sym.isTerm && sym.owner == ArrayClass) {
if (sym.isClassConstructor)
tp match {
- case MethodType(formals, TypeRef(pre, sym, args)) =>
- MethodType(formals map erasure, typeRef(erasure(pre), sym, args))
+ case MethodType(params, TypeRef(pre, sym, args)) =>
+ MethodType(cloneSymbols(params) map (p => p.setInfo(erasure(p.tpe))),
+ typeRef(erasure(pre), sym, args))
}
else if (sym.name == nme.apply)
tp
else if (sym.name == nme.update)
tp match {
case MethodType(List(index, tvar), restpe) =>
- MethodType(List(erasure(index), tvar), erasedTypeRef(UnitClass))
+ MethodType(List(index.cloneSymbol.setInfo(erasure(index.tpe)), tvar),
+ erasedTypeRef(UnitClass))
}
else erasure(tp)
+ } else if (
+ sym.owner != NoSymbol &&
+ sym.owner.owner == ArrayClass &&
+ sym == Array_update.paramss.head(1)) {
+ // special case for Array.update: the non-erased type remains, i.e. (Int,A)Unit
+ // since the erasure type map gets applied to every symbol, we have to catch the
+ // symbol here
+ tp
} else {
/*
val erased =
@@ -359,7 +369,7 @@ abstract class Erasure extends AddInterfaces with typechecker.Analyzer {
private def box(tree: Tree): Tree = tree match {
case LabelDef(name, params, rhs) =>
val rhs1 = box(rhs)
- copy.LabelDef(tree, name, params, rhs1) setType rhs1.tpe
+ treeCopy.LabelDef(tree, name, params, rhs1) setType rhs1.tpe
case _ =>
typed {
atPos(tree.pos) {
@@ -381,7 +391,7 @@ abstract class Erasure extends AddInterfaces with typechecker.Analyzer {
private def boxArray(tree: Tree): Tree = tree match {
case LabelDef(name, params, rhs) =>
val rhs1 = boxArray(rhs)
- copy.LabelDef(tree, name, params, rhs1) setType rhs1.tpe
+ treeCopy.LabelDef(tree, name, params, rhs1) setType rhs1.tpe
case _ =>
typed {
atPos(tree.pos) {
@@ -399,7 +409,7 @@ abstract class Erasure extends AddInterfaces with typechecker.Analyzer {
private def unbox(tree: Tree, pt: Type): Tree = tree match {
case LabelDef(name, params, rhs) =>
val rhs1 = unbox(rhs, pt)
- copy.LabelDef(tree, name, params, rhs1) setType rhs1.tpe
+ treeCopy.LabelDef(tree, name, params, rhs1) setType rhs1.tpe
case _ =>
typed {
atPos(tree.pos) {
@@ -651,7 +661,7 @@ abstract class Erasure extends AddInterfaces with typechecker.Analyzer {
// println("member cast "+tree.symbol+" "+tree.symbol.ownerChain+" "+qual1+" "+qual1.tpe)
qual1 = cast(qual1, tree.symbol.owner.tpe)
}
- copy.Select(tree, qual1, name)
+ treeCopy.Select(tree, qual1, name)
}
case _ =>
tree
@@ -685,17 +695,17 @@ abstract class Erasure extends AddInterfaces with typechecker.Analyzer {
}
def adaptCase(cdef: CaseDef): CaseDef = {
val body1 = adaptToType(cdef.body, tree1.tpe)
- copy.CaseDef(cdef, cdef.pat, cdef.guard, body1) setType body1.tpe
+ treeCopy.CaseDef(cdef, cdef.pat, cdef.guard, body1) setType body1.tpe
}
def adaptBranch(branch: Tree): Tree =
if (branch == EmptyTree) branch else adaptToType(branch, tree1.tpe);
tree1 match {
case If(cond, thenp, elsep) =>
- copy.If(tree1, cond, adaptBranch(thenp), adaptBranch(elsep))
+ treeCopy.If(tree1, cond, adaptBranch(thenp), adaptBranch(elsep))
case Match(selector, cases) =>
- copy.Match(tree1, selector, cases map adaptCase)
+ treeCopy.Match(tree1, selector, cases map adaptCase)
case Try(block, catches, finalizer) =>
- copy.Try(tree1, adaptBranch(block), catches map adaptCase, finalizer)
+ treeCopy.Try(tree1, adaptBranch(block), catches map adaptCase, finalizer)
case Ident(_) | Select(_, _) =>
if (tree1.symbol hasFlag OVERLOADED) {
val first = tree1.symbol.alternatives.head
@@ -737,20 +747,22 @@ abstract class Erasure extends AddInterfaces with typechecker.Analyzer {
*/
private def checkNoDoubleDefs(root: Symbol) {
def doubleDefError(sym1: Symbol, sym2: Symbol) {
- val tpe1 = atPhase(currentRun.refchecksPhase.next)(root.thisType.memberType(sym1))
- val tpe2 = atPhase(currentRun.refchecksPhase.next)(root.thisType.memberType(sym2))
+ // the .toString must also be computed at the earlier phase
+ def atRefc[T](op: => T) = atPhase[T](currentRun.refchecksPhase.next)(op)
+ val tpe1 = atRefc(root.thisType.memberType(sym1))
+ val tpe2 = atRefc(root.thisType.memberType(sym2))
if (!tpe1.isErroneous && !tpe2.isErroneous)
unit.error(
if (sym1.owner == root) sym1.pos else root.pos,
(if (sym1.owner == sym2.owner) "double definition:\n"
else if (sym1.owner == root) "name clash between defined and inherited member:\n"
else "name clash between inherited members:\n") +
- sym1 + ":" + tpe1 +
+ sym1 + ":" + atRefc(tpe1.toString) +
(if (sym1.owner == root) "" else sym1.locationString) + " and\n" +
- sym2 + ":" + tpe2 +
+ sym2 + ":" + atRefc(tpe2.toString) +
(if (sym2.owner == root) " at line " + (sym2.pos).line.get else sym2.locationString) +
"\nhave same type" +
- (if (tpe1 =:= tpe2) "" else " after erasure: " + atPhase(phase.next)(sym1.tpe)))
+ (if (atRefc(tpe1 =:= tpe2)) "" else " after erasure: " + atPhase(phase.next)(sym1.tpe)))
sym1.setInfo(ErrorType)
}
@@ -857,7 +869,8 @@ abstract class Erasure extends AddInterfaces with typechecker.Analyzer {
.setPos(owner.pos)
.setFlag(member.flags | BRIDGE)
.resetFlag(ACCESSOR | DEFERRED | LAZY | lateDEFERRED)
- .setInfo(otpe);
+ // the parameter symbols need to have the new owner
+ bridge.setInfo(otpe.cloneInfo(bridge))
bridgeTarget(bridge) = member
atPhase(phase.next) { owner.info.decls.enter(bridge) }
if (other.owner == owner) {
@@ -870,11 +883,11 @@ abstract class Erasure extends AddInterfaces with typechecker.Analyzer {
atPhase(phase.next) {
atPos(bridge.pos) {
val bridgeDef =
- DefDef(bridge, vparamss =>
+ DefDef(bridge,
member.tpe match {
case MethodType(List(), ConstantType(c)) => Literal(c)
case _ =>
- (((Select(This(owner), member): Tree) /: vparamss)
+ (((Select(This(owner), member): Tree) /: bridge.paramss)
((fun, vparams) => Apply(fun, vparams map Ident)))
});
if (settings.debug.value)
@@ -945,9 +958,9 @@ abstract class Erasure extends AddInterfaces with typechecker.Analyzer {
case ClassDef(mods, name, tparams, impl) =>
if (settings.debug.value)
log("defs of " + tree.symbol + " = " + tree.symbol.info.decls)
- copy.ClassDef(tree, mods, name, List(), impl)
+ treeCopy.ClassDef(tree, mods, name, List(), impl)
case DefDef(mods, name, tparams, vparamss, tpt, rhs) =>
- copy.DefDef(tree, mods, name, List(), vparamss, tpt, rhs)
+ treeCopy.DefDef(tree, mods, name, List(), vparamss, tpt, rhs)
case TypeDef(_, _, _, _) =>
EmptyTree
case TypeApply(fun, args) if (fun.symbol.owner != AnyClass &&
@@ -1045,14 +1058,14 @@ abstract class Erasure extends AddInterfaces with typechecker.Analyzer {
assert(!currentOwner.isImplClass)
//Console.println("checking no dble defs " + tree)//DEBUG
checkNoDoubleDefs(tree.symbol.owner)
- copy.Template(tree, parents, emptyValDef, addBridges(body, currentOwner))
+ treeCopy.Template(tree, parents, emptyValDef, addBridges(body, currentOwner))
case Match(selector, cases) =>
Match(Typed(selector, TypeTree(selector.tpe)), cases)
case Literal(ct) if ct.tag == ClassTag
&& ct.typeValue.typeSymbol != definitions.UnitClass =>
- copy.Literal(tree, Constant(erasure(ct.typeValue)))
+ treeCopy.Literal(tree, Constant(erasure(ct.typeValue)))
case _ =>
tree
diff --git a/src/compiler/scala/tools/nsc/transform/ExplicitOuter.scala b/src/compiler/scala/tools/nsc/transform/ExplicitOuter.scala
index d1fb5d9d82..a4125dfa2a 100644
--- a/src/compiler/scala/tools/nsc/transform/ExplicitOuter.scala
+++ b/src/compiler/scala/tools/nsc/transform/ExplicitOuter.scala
@@ -99,7 +99,7 @@ abstract class ExplicitOuter extends InfoTransform with TransMatcher with Patter
* </ol>
*/
def transformInfo(sym: Symbol, tp: Type): Type = tp match {
- case MethodType(formals, restpe1) =>
+ case MethodType(params, restpe1) =>
val restpe = transformInfo(sym, restpe1)
if (sym.owner.isTrait && ((sym hasFlag SUPERACCESSOR) || sym.isModule)) { // 5
sym.makeNotPrivate(sym.owner)
@@ -108,10 +108,12 @@ abstract class ExplicitOuter extends InfoTransform with TransMatcher with Patter
if (sym.owner.isTrait && (sym hasFlag (ACCESSOR | SUPERACCESSOR)))
sym.makeNotPrivate(sym.owner); //(2)
if (sym.owner.isTrait && (sym hasFlag PROTECTED)) sym setFlag notPROTECTED // 6
- if (sym.isClassConstructor && isInner(sym.owner)) // 1
- MethodType(sym.owner.outerClass.thisType :: formals, restpe)
- else if (restpe ne restpe1)
- MethodType(formals, restpe)
+ if (sym.isClassConstructor && isInner(sym.owner)) { // 1
+ val p = sym.newValueParameter(sym.pos, "arg" + nme.OUTER)
+ .setInfo(sym.owner.outerClass.thisType)
+ MethodType(p :: params, restpe)
+ } else if (restpe ne restpe1)
+ MethodType(params, restpe)
else tp
case ClassInfoType(parents, decls, clazz) =>
var decls1 = decls
@@ -306,7 +308,7 @@ abstract class ExplicitOuter extends InfoTransform with TransMatcher with Patter
else Select(This(currentClass), outerField(currentClass))
localTyper.typed {
atPos(currentClass.pos) {
- DefDef(outerAcc, {vparamss => rhs})
+ DefDef(outerAcc, rhs)
}
}
}
@@ -329,7 +331,7 @@ abstract class ExplicitOuter extends InfoTransform with TransMatcher with Patter
localTyper.typed {
atPos(currentClass.pos) {
// @S: atPos not good enough because of nested atPos in DefDef method, which gives position from wrong class!
- DefDef(outerAcc, {vparamss=>rhs}).setPos(currentClass.pos)
+ DefDef(outerAcc, rhs).setPos(currentClass.pos)
}
}
}
@@ -359,7 +361,7 @@ abstract class ExplicitOuter extends InfoTransform with TransMatcher with Patter
}
}
super.transform(
- copy.Template(tree, parents, self,
+ treeCopy.Template(tree, parents, self,
if (newDefs.isEmpty) decls else decls ::: newDefs.toList)
)
case DefDef(mods, name, tparams, vparamss, tpt, rhs) =>
@@ -375,7 +377,7 @@ abstract class ExplicitOuter extends InfoTransform with TransMatcher with Patter
sym.newValueParameter(sym.pos, nme.OUTER) setInfo outerField(clazz).info
((ValDef(outerParam) setType NoType) :: vparamss.head) :: vparamss.tail
} else vparamss
- super.transform(copy.DefDef(tree, mods, name, tparams, vparamss1, tpt, rhs))
+ super.transform(treeCopy.DefDef(tree, mods, name, tparams, vparamss1, tpt, rhs))
}
} else
super.transform(tree)
@@ -405,7 +407,7 @@ abstract class ExplicitOuter extends InfoTransform with TransMatcher with Patter
gen.mkAttributedQualifier(pre)
}
}
- super.transform(copy.Apply(tree, sel, outerVal :: args))
+ super.transform(treeCopy.Apply(tree, sel, outerVal :: args))
case mch @ Match(selector, cases) => // <----- transmatch hook
val tid = if (settings.debug.value) {
@@ -426,14 +428,14 @@ abstract class ExplicitOuter extends InfoTransform with TransMatcher with Patter
fmls += vs1.head.tpe
vs1 = vs1.tail
}
- val tpe = new MethodType(fmls.toList, definitions.BooleanClass.tpe)
+ val tpe = new MethodType(method.newSyntheticValueParams(fmls.toList),
+ definitions.BooleanClass.tpe)
method setInfo tpe
localTyper.
typed {
DefDef(method,
- {vparamss =>
- new ChangeOwnerTraverser(currentOwner, method).traverse(guard);
- new TreeSymSubstituter(vs, vparamss.head).traverse(guard);guard})}
+ { new ChangeOwnerTraverser(currentOwner, method).traverse(guard);
+ new TreeSymSubstituter(vs, method.paramss.head).traverse(guard);guard})}
}
val nguard = new ListBuffer[Tree]
diff --git a/src/compiler/scala/tools/nsc/transform/Flatten.scala b/src/compiler/scala/tools/nsc/transform/Flatten.scala
index 4a20175663..fa1c08f80f 100644
--- a/src/compiler/scala/tools/nsc/transform/Flatten.scala
+++ b/src/compiler/scala/tools/nsc/transform/Flatten.scala
@@ -56,6 +56,9 @@ abstract class Flatten extends InfoTransform {
}
}
ClassInfoType(parents1, decls1, clazz)
+ case MethodType(params, restp) =>
+ val restp1 = apply(restp)
+ if (restp1 eq restp) tp else copyMethodType(tp, params, restp1)
case PolyType(tparams, restp) =>
val restp1 = apply(restp);
if (restp1 eq restp) tp else PolyType(tparams, restp1)
diff --git a/src/compiler/scala/tools/nsc/transform/LambdaLift.scala b/src/compiler/scala/tools/nsc/transform/LambdaLift.scala
index 2c2314f880..41b2cc53a7 100644
--- a/src/compiler/scala/tools/nsc/transform/LambdaLift.scala
+++ b/src/compiler/scala/tools/nsc/transform/LambdaLift.scala
@@ -101,9 +101,8 @@ abstract class LambdaLift extends InfoTransform {
def localToConstr(sym: Symbol) =
if (sym.isLocalDummy) sym.owner.primaryConstructor else sym;
var encl = localToConstr(sym)
- while (!encl.isMethod && !encl.isClass) {
- encl = localToConstr(outer(encl));
- }
+ while (!encl.isMethod && !encl.isClass)
+ encl = localToConstr(outer(encl))
encl
}
@@ -318,12 +317,13 @@ abstract class LambdaLift extends InfoTransform {
val freeParams = ps map (p => ValDef(p) setPos tree.pos setType NoType);
tree match {
case DefDef(mods, name, tparams, List(vparams), tpt, rhs) =>
+ val addParams = cloneSymbols(ps).map(_.setFlag(PARAM))
sym.updateInfo(
- lifted(MethodType(sym.info.paramTypes ::: (ps map (_.tpe)), sym.info.resultType)));
- copy.DefDef(tree, mods, name, tparams, List(vparams ::: freeParams), tpt, rhs)
+ lifted(MethodType(sym.info.params ::: addParams, sym.info.resultType)))
+ treeCopy.DefDef(tree, mods, name, tparams, List(vparams ::: freeParams), tpt, rhs)
case ClassDef(mods, name, tparams, impl @ Template(parents, self, body)) =>
- copy.ClassDef(tree, mods, name, tparams,
- copy.Template(impl, parents, self, body ::: freeParams))
+ treeCopy.ClassDef(tree, mods, name, tparams,
+ treeCopy.Template(impl, parents, self, body ::: freeParams))
}
case None =>
tree
@@ -358,20 +358,20 @@ abstract class LambdaLift extends InfoTransform {
Apply(Select(New(TypeTree(sym.tpe)), nme.CONSTRUCTOR), List(rhs))
}
}
- copy.ValDef(tree, mods, name, tpt1, rhs1)
+ treeCopy.ValDef(tree, mods, name, tpt1, rhs1)
} else tree
case Return(Block(stats, value)) =>
- Block(stats, copy.Return(tree, value)) setType tree.tpe setPos tree.pos
+ Block(stats, treeCopy.Return(tree, value)) setType tree.tpe setPos tree.pos
case Return(expr) =>
assert(sym == currentMethod, sym)
tree
case Apply(fn, args) =>
- copy.Apply(tree, fn, addFreeArgs(tree.pos, sym, args))
+ treeCopy.Apply(tree, fn, addFreeArgs(tree.pos, sym, args))
case Assign(Apply(TypeApply(sel @ Select(qual, _), _), List()), rhs) =>
// eliminate casts introduced by selecting a captured variable field
// on the lhs of an assignment.
assert(sel.symbol == Object_asInstanceOf)
- copy.Assign(tree, qual, rhs)
+ treeCopy.Assign(tree, qual, rhs)
case Ident(name) =>
val tree1 =
if (sym != NoSymbol && sym.isTerm && !sym.isLabel)
@@ -401,13 +401,13 @@ abstract class LambdaLift extends InfoTransform {
def addLifted(stat: Tree): Tree = stat match {
case ClassDef(mods, name, tparams, impl @ Template(parents, self, body)) =>
val lifted = liftedDefs(stat.symbol).toList map addLifted
- val result = copy.ClassDef(
- stat, mods, name, tparams, copy.Template(impl, parents, self, body ::: lifted))
+ val result = treeCopy.ClassDef(
+ stat, mods, name, tparams, treeCopy.Template(impl, parents, self, body ::: lifted))
liftedDefs -= stat.symbol
result
case DefDef(mods, name, tp, vp, tpt, Block(Nil, expr))
if !stat.symbol.isConstructor =>
- copy.DefDef(stat, mods, name, tp, vp, tpt, expr)
+ treeCopy.DefDef(stat, mods, name, tp, vp, tpt, expr)
case _ =>
stat
}
diff --git a/src/compiler/scala/tools/nsc/transform/LazyVals.scala b/src/compiler/scala/tools/nsc/transform/LazyVals.scala
index 41c3230bff..ce5329e532 100644
--- a/src/compiler/scala/tools/nsc/transform/LazyVals.scala
+++ b/src/compiler/scala/tools/nsc/transform/LazyVals.scala
@@ -60,8 +60,8 @@ abstract class LazyVals extends Transform {
rhs1
} else
super.transform(rhs)
- copy.DefDef(tree, mods, name, tparams, vparams, tpt,
- typed(addBitmapDefs(sym, res)))
+ treeCopy.DefDef(tree, mods, name, tparams, vparams, tpt,
+ typed(addBitmapDefs(sym, res)))
case Template(parents, self, body) =>
val body1 = super.transformTrees(body)
@@ -72,11 +72,11 @@ abstract class LazyVals extends Transform {
added = true
typed(addBitmapDefs(sym, stat))
case ValDef(mods, name, tpt, rhs) =>
- typed(copy.ValDef(stat, mods, name, tpt, addBitmapDefs(stat.symbol, rhs)))
+ typed(treeCopy.ValDef(stat, mods, name, tpt, addBitmapDefs(stat.symbol, rhs)))
case _ =>
stat
}
- copy.Template(tree, parents, self, stats)
+ treeCopy.Template(tree, parents, self, stats)
case _ => super.transform(tree)
}
@@ -100,7 +100,7 @@ abstract class LazyVals extends Transform {
if (name.toString.equals("_" + methSym.name)
&& List.forall2(params.tail, methSym.tpe.paramTypes) { (ident, tpe) => ident.tpe == tpe }) =>
val sym = l.symbol
- Block(assign, copy.LabelDef(l, name, params, typed(prependStats(bmps, rhs1))))
+ Block(assign, treeCopy.LabelDef(l, name, params, typed(prependStats(bmps, rhs1))))
case _ => prependStats(bmps, rhs)
}
diff --git a/src/compiler/scala/tools/nsc/transform/Mixin.scala b/src/compiler/scala/tools/nsc/transform/Mixin.scala
index f5fbafaf7a..4a13690efd 100644
--- a/src/compiler/scala/tools/nsc/transform/Mixin.scala
+++ b/src/compiler/scala/tools/nsc/transform/Mixin.scala
@@ -172,7 +172,7 @@ abstract class Mixin extends InfoTransform {
val setterName = nme.getterToSetter(nme.getterName(field.name))
val setter = clazz.newMethod(field.pos, setterName)
.setFlag(field.flags & ~(PRIVATE | LOCAL) | ACCESSOR | lateDEFERRED)
- .setInfo(MethodType(List(field.info), UnitClass.tpe))
+ setter.setInfo(MethodType(setter.newSyntheticValueParams(List(field.info)), UnitClass.tpe))
if (needsExpandedSetterName(field)) {
//println("creating expanded setter from "+field)
setter.name = clazz.expandedSetterName(setter.name)
@@ -351,11 +351,12 @@ abstract class Mixin extends InfoTransform {
if ((parents1 eq parents) && (decls1 eq decls)) tp
else ClassInfoType(parents1, decls1, clazz)
- case MethodType(formals, restp) =>
+ case MethodType(params, restp) =>
toInterfaceMap(
- if (isImplementedStatically(sym))
- MethodType(toInterface(sym.owner.typeOfThis) :: formals, restp)
- else
+ if (isImplementedStatically(sym)) {
+ val ownerParam = sym.newSyntheticValueParam(toInterface(sym.owner.typeOfThis))
+ MethodType(ownerParam :: params, restp)
+ } else
tp)
case _ =>
@@ -419,7 +420,7 @@ abstract class Mixin extends InfoTransform {
.setFlag(PARAM)
.setInfo(toInterface(currentOwner.typeOfThis));
val selfdef = ValDef(self) setType NoType
- copy.DefDef(tree, mods, name, tparams, List(selfdef :: vparams), tpt, rhs)
+ treeCopy.DefDef(tree, mods, name, tparams, List(selfdef :: vparams), tpt, rhs)
} else {
EmptyTree
}
@@ -508,7 +509,7 @@ abstract class Mixin extends InfoTransform {
* right-hand side
*/
def addDefDef(sym: Symbol, rhs: List[Symbol] => Tree) {
- addDef(position(sym), DefDef(sym, vparamss => rhs(vparamss.head)))
+ addDef(position(sym), DefDef(sym, rhs(sym.paramss.head)))
}
/** Add `newdefs' to `stats', removing any abstract method definitions
@@ -548,7 +549,7 @@ abstract class Mixin extends InfoTransform {
log("complete super acc " + stat.symbol + stat.symbol.locationString +
" " + rhs1 + " " + stat.symbol.alias + stat.symbol.alias.locationString +
"/" + stat.symbol.alias.owner.hasFlag(lateINTERFACE))//debug
- copy.DefDef(stat, mods, name, tparams, List(vparams), tpt, rhs2)
+ treeCopy.DefDef(stat, mods, name, tparams, List(vparams), tpt, rhs2)
case _ =>
stat
}
@@ -659,7 +660,7 @@ abstract class Mixin extends InfoTransform {
val Block(stats, res) = rhs
mkLazyDef(clazz, stats, Select(This(clazz), res.symbol), fieldOffset(sym))
}
- copy.DefDef(stat, mods, name, tp, vp, tpt, rhs1)
+ treeCopy.DefDef(stat, mods, name, tp, vp, tpt, rhs1)
case DefDef(mods, name, tp, vp, tpt, rhs)
if needsInitFlag(sym) && rhs != EmptyTree && !clazz.isImplClass && !clazz.isTrait =>
@@ -670,10 +671,10 @@ abstract class Mixin extends InfoTransform {
else {
mkCheckedAccessor(clazz, rhs, fieldOffset(sym), stat.pos)
}
- copy.DefDef(stat, mods, name, tp, vp, tpt, rhs1)
+ treeCopy.DefDef(stat, mods, name, tp, vp, tpt, rhs1)
case DefDef(mods, name, tp, vp, tpt, rhs) if sym.isConstructor =>
- copy.DefDef(stat, mods, name, tp, vp, tpt, addInitBits(clazz, rhs))
+ treeCopy.DefDef(stat, mods, name, tp, vp, tpt, addInitBits(clazz, rhs))
case _ => stat
}
@@ -890,7 +891,7 @@ abstract class Mixin extends InfoTransform {
// add all new definitions to current class or interface
val body1 = addNewDefs(currentOwner, body)
- copy.Template(tree, parents1, self, body1)
+ treeCopy.Template(tree, parents1, self, body1)
case Apply(TypeApply(sel @ Select(qual, name), List(targ)), List())
if (tree.symbol == Object_asInstanceOf && (qual.tpe <:< targ.tpe)) =>
diff --git a/src/compiler/scala/tools/nsc/transform/Reifiers.scala b/src/compiler/scala/tools/nsc/transform/Reifiers.scala
index 5973fa07e8..300649aa4d 100644
--- a/src/compiler/scala/tools/nsc/transform/Reifiers.scala
+++ b/src/compiler/scala/tools/nsc/transform/Reifiers.scala
@@ -72,8 +72,8 @@ trait Reifiers {
if (_log_reify_type_) println("cannot handle RefinedType "+tp); reflect.NoType
case ClassInfoType(parents, defs, clazz) =>
if (_log_reify_type_) println("cannot handle ClassInfoType "+tp); reflect.NoType
- case MethodType(paramtypes, result) =>
- reflect.MethodType(paramtypes.map(reify), reify(result))
+ case MethodType(params, result) =>
+ reflect.MethodType(params.map(reify), reify(result))
case PolyType(tparams, result) =>
val boundss =
for {
@@ -139,8 +139,8 @@ trait Reifiers {
appliedType(untpe, args.map(unreify))
case reflect.TypeBounds(lo, hi) =>
TypeBounds(unreify(lo), unreify(hi))
- case reflect.MethodType(formals, restpe) =>
- MethodType(formals.map(unreify), unreify(restpe))
+ case reflect.MethodType(params, restpe) =>
+ MethodType(params.map(unreify), unreify(restpe))
case reflect.PolyType(typeParams, typeBounds, resultType) =>
PolyType(typeParams.map(unreify), unreify(resultType))
//todo: treat ExistentialType
diff --git a/src/compiler/scala/tools/nsc/transform/SampleTransform.scala b/src/compiler/scala/tools/nsc/transform/SampleTransform.scala
index b29f82e588..ad4e322ab1 100644
--- a/src/compiler/scala/tools/nsc/transform/SampleTransform.scala
+++ b/src/compiler/scala/tools/nsc/transform/SampleTransform.scala
@@ -30,7 +30,7 @@ abstract class SampleTransform extends Transform {
expr
case Block(defs, sup @ Super(qual, mix)) => // A hypthothetic transformation, which replaces
// {super} by {super.sample}
- copy.Block( // `copy' is the usual lazy tree copier
+ treeCopy.Block( // `copy' is the usual lazy tree copier
tree1, defs,
typed( // `typed' assigns types to its tree argument
atPos(tree1.pos)( // `atPos' fills in position of its tree argument
diff --git a/src/compiler/scala/tools/nsc/transform/TailCalls.scala b/src/compiler/scala/tools/nsc/transform/TailCalls.scala
index 3df490caac..af6c65ece2 100644
--- a/src/compiler/scala/tools/nsc/transform/TailCalls.scala
+++ b/src/compiler/scala/tools/nsc/transform/TailCalls.scala
@@ -157,7 +157,8 @@ abstract class TailCalls extends Transform
val newCtx = mkContext(ctx)
newCtx.currentMethod = tree.symbol
newCtx.makeLabel()
- newCtx.label.setInfo(MethodType(currentClass.tpe :: tree.symbol.tpe.paramTypes, tree.symbol.tpe.finalResultType))
+ val currentClassParam = tree.symbol.newSyntheticValueParam(currentClass.tpe)
+ newCtx.label.setInfo(MethodType(currentClassParam :: tree.symbol.tpe.params, tree.symbol.tpe.finalResultType))
newCtx.tailPos = true
val t1 = if (newCtx.currentMethod.isFinal ||
@@ -187,11 +188,11 @@ abstract class TailCalls extends Transform
LabelDef(newCtx.label,
newThis :: (List.flatten(vparams) map (_.symbol)),
newRHS))));
- copy.DefDef(tree, mods, name, tparams, vparams, tpt, newRHS);
+ treeCopy.DefDef(tree, mods, name, tparams, vparams, tpt, newRHS);
} else
- copy.DefDef(tree, mods, name, tparams, vparams, tpt, newRHS);
+ treeCopy.DefDef(tree, mods, name, tparams, vparams, tpt, newRHS);
} else {
- copy.DefDef(tree, mods, name, tparams, vparams, tpt, transform(rhs, newCtx))
+ treeCopy.DefDef(tree, mods, name, tparams, vparams, tpt, transform(rhs, newCtx))
}
if (!isTransformed && tailrecRequired(dd))
@@ -218,12 +219,12 @@ abstract class TailCalls extends Transform
super.transform(tree)
case Block(stats, expr) =>
- copy.Block(tree,
- transformTrees(stats, mkContext(ctx, false)),
- transform(expr))
+ treeCopy.Block(tree,
+ transformTrees(stats, mkContext(ctx, false)),
+ transform(expr))
case CaseDef(pat, guard, body) =>
- copy.CaseDef(tree, pat, guard, transform(body))
+ treeCopy.CaseDef(tree, pat, guard, transform(body))
case Sequence(_) | Alternative(_) |
Star(_) | Bind(_, _) =>
@@ -237,24 +238,24 @@ abstract class TailCalls extends Transform
super.transform(tree)
case If(cond, thenp, elsep) =>
- copy.If(tree, cond, transform(thenp), transform(elsep))
+ treeCopy.If(tree, cond, transform(thenp), transform(elsep))
case Match(selector, cases) => //super.transform(tree);
- copy.Match(tree, transform(selector, mkContext(ctx, false)), transformTrees(cases).asInstanceOf[List[CaseDef]])
+ treeCopy.Match(tree, transform(selector, mkContext(ctx, false)), transformTrees(cases).asInstanceOf[List[CaseDef]])
case Return(expr) => super.transform(tree)
case Try(block, catches, finalizer) =>
// no calls inside a try are in tail position, but keep recursing for nested functions
- copy.Try(tree, transform(block, mkContext(ctx, false)),
- transformTrees(catches, mkContext(ctx, false)).asInstanceOf[List[CaseDef]],
- transform(finalizer, mkContext(ctx, false)))
+ treeCopy.Try(tree, transform(block, mkContext(ctx, false)),
+ transformTrees(catches, mkContext(ctx, false)).asInstanceOf[List[CaseDef]],
+ transform(finalizer, mkContext(ctx, false)))
case Throw(expr) => super.transform(tree)
case New(tpt) => super.transform(tree)
case Typed(expr, tpt) => super.transform(tree)
case Apply(tapply @ TypeApply(fun, targs), vargs) =>
- lazy val defaultTree = copy.Apply(tree, tapply, transformTrees(vargs, mkContext(ctx, false)))
+ lazy val defaultTree = treeCopy.Apply(tree, tapply, transformTrees(vargs, mkContext(ctx, false)))
if ( ctx.currentMethod.isFinal &&
ctx.tailPos &&
isSameTypes(ctx.tparams, targs map (_.tpe.typeSymbol)) &&
@@ -280,10 +281,10 @@ abstract class TailCalls extends Transform
case Apply(fun, args) if (fun.symbol == definitions.Boolean_or ||
fun.symbol == definitions.Boolean_and) =>
- copy.Apply(tree, fun, transformTrees(args))
+ treeCopy.Apply(tree, fun, transformTrees(args))
case Apply(fun, args) =>
- lazy val defaultTree = copy.Apply(tree, fun, transformTrees(args, mkContext(ctx, false)))
+ lazy val defaultTree = treeCopy.Apply(tree, fun, transformTrees(args, mkContext(ctx, false)))
if (ctx.currentMethod.isFinal &&
ctx.tailPos &&
isRecursiveCall(fun)) {
diff --git a/src/compiler/scala/tools/nsc/transform/UnCurry.scala b/src/compiler/scala/tools/nsc/transform/UnCurry.scala
index fd853e3ea3..15684c23d4 100644
--- a/src/compiler/scala/tools/nsc/transform/UnCurry.scala
+++ b/src/compiler/scala/tools/nsc/transform/UnCurry.scala
@@ -51,13 +51,13 @@ abstract class UnCurry extends InfoTransform with TypingTransformers {
def apply(tp0: Type): Type = {
val tp = expandAlias(tp0)
tp match {
- case MethodType(formals, MethodType(formals1, restpe)) =>
- apply(MethodType(formals ::: formals1, restpe))
+ case MethodType(params, MethodType(params1, restpe)) =>
+ apply(MethodType(params ::: params1, restpe))
case MethodType(formals, ExistentialType(tparams, restpe @ MethodType(_, _))) =>
assert(false, "unexpected curried method types with intervening exitential")
tp0
case mt: ImplicitMethodType =>
- apply(MethodType(mt.paramTypes, mt.resultType))
+ apply(MethodType(mt.params, mt.resultType))
case PolyType(List(), restpe) =>
apply(MethodType(List(), restpe))
case PolyType(tparams, restpe) =>
@@ -91,11 +91,11 @@ abstract class UnCurry extends InfoTransform with TypingTransformers {
/** Convert repeated parameters to arrays if they occur as part of a Java method
*/
private def repeatedToArray(tp: Type): Type = tp match {
- case MethodType(formals, rtpe)
- if (!formals.isEmpty && formals.last.typeSymbol == RepeatedParamClass) =>
- MethodType(formals.init :::
- List(appliedType(ArrayClass.typeConstructor, List(formals.last.typeArgs.head))),
- rtpe)
+ case MethodType(params, rtpe)
+ if (!params.isEmpty && params.last.tpe.typeSymbol == RepeatedParamClass) =>
+ val arrayParam = params.last.owner.newSyntheticValueParams(List(
+ appliedType(ArrayClass.typeConstructor, List(params.last.tpe.typeArgs.head))))
+ MethodType(params.init ::: arrayParam, rtpe)
case PolyType(tparams, rtpe) =>
val rtpe1 = repeatedToArray(rtpe)
if (rtpe1 eq rtpe) tp
@@ -304,8 +304,8 @@ abstract class UnCurry extends InfoTransform with TypingTransformers {
val restpe = fun.tpe.typeArgs.last
anonClass setInfo ClassInfoType(
List(ObjectClass.tpe, fun.tpe, ScalaObjectClass.tpe), newScope, anonClass);
- val applyMethod = anonClass.newMethod(fun.pos, nme.apply)
- .setFlag(FINAL).setInfo(MethodType(formals, restpe));
+ val applyMethod = anonClass.newMethod(fun.pos, nme.apply).setFlag(FINAL)
+ applyMethod.setInfo(MethodType(applyMethod.newSyntheticValueParams(formals), restpe))
anonClass.info.decls enter applyMethod;
for (vparam <- fun.vparams) vparam.symbol.owner = applyMethod;
new ChangeOwnerTraverser(fun.symbol, applyMethod).traverse(fun.body);
@@ -334,8 +334,9 @@ abstract class UnCurry extends InfoTransform with TypingTransformers {
}
val members = {
if (fun.tpe.typeSymbol == PartialFunctionClass) {
- val isDefinedAtMethod = anonClass.newMethod(fun.pos, nme.isDefinedAt)
- .setFlag(FINAL).setInfo(MethodType(formals, BooleanClass.tpe))
+ val isDefinedAtMethod = anonClass.newMethod(fun.pos, nme.isDefinedAt).setFlag(FINAL)
+ isDefinedAtMethod.setInfo(MethodType(isDefinedAtMethod.newSyntheticValueParams(formals),
+ BooleanClass.tpe))
anonClass.info.decls enter isDefinedAtMethod
def idbody(idparam: Symbol) = fun.body match {
case Match(_, cases) =>
@@ -352,7 +353,7 @@ abstract class UnCurry extends InfoTransform with TypingTransformers {
List(CaseDef(Ident(nme.WILDCARD), EmptyTree, Literal(false))))
}
List(applyMethodDef(mkUnchecked(fun.body)),
- DefDef(isDefinedAtMethod, vparamss => mkUnchecked(idbody(vparamss.head.head))))
+ DefDef(isDefinedAtMethod, mkUnchecked(idbody(isDefinedAtMethod.paramss.head.head))))
} else {
List(applyMethodDef(fun.body))
}
@@ -475,9 +476,9 @@ abstract class UnCurry extends InfoTransform with TypingTransformers {
val rest = stats drop presupers.length
val supercalls = rest take 1 map transformInConstructor
val others = rest drop 1 map transform
- copy.Block(rhs, presupers ::: supercalls ::: others, transform(expr))
+ treeCopy.Block(rhs, presupers ::: supercalls ::: others, transform(expr))
}
- copy.DefDef(
+ treeCopy.DefDef(
tree, mods, name, transformTypeDefs(tparams),
transformValDefss(vparamss), transform(tpt), rhs1)
}
@@ -521,7 +522,7 @@ abstract class UnCurry extends InfoTransform with TypingTransformers {
else if (fn.symbol.name == nme.unapplySeq)
transformArgs(tree.pos, args, analyzer.unapplyTypeListFromReturnTypeSeq(fn.tpe), false)
else { assert(false,"internal error: UnApply node has wrong symbol"); null })
- copy.UnApply(tree, fn1, args1)
+ treeCopy.UnApply(tree, fn1, args1)
case Apply(fn, args) =>
if (settings.noassertions.value &&
@@ -530,12 +531,12 @@ abstract class UnCurry extends InfoTransform with TypingTransformers {
fn.symbol.owner == PredefModule.moduleClass) {
Literal(()).setPos(tree.pos).setType(UnitClass.tpe)
} else if (fn.symbol == Object_synchronized && shouldBeLiftedAnyway(args.head)) {
- transform(copy.Apply(tree, fn, List(liftTree(args.head))))
+ transform(treeCopy.Apply(tree, fn, List(liftTree(args.head))))
} else {
withNeedLift(true) {
val formals = fn.tpe.paramTypes;
val isJava = fn.symbol hasFlag JAVA // in case we need a varargs transformation
- copy.Apply(tree, transform(fn), transformTrees(transformArgs(tree.pos, args, formals, isJava)))
+ treeCopy.Apply(tree, transform(fn), transformTrees(transformArgs(tree.pos, args, formals, isJava)))
}
}
@@ -552,7 +553,7 @@ abstract class UnCurry extends InfoTransform with TypingTransformers {
inPattern = true
val pat1 = transform(pat)
inPattern = false
- copy.CaseDef(tree, pat1, transform(guard), transform(body))
+ treeCopy.CaseDef(tree, pat1, transform(guard), transform(body))
case fun @ Function(_, _) =>
mainTransform(transformFunction(fun))
@@ -592,7 +593,7 @@ abstract class UnCurry extends InfoTransform with TypingTransformers {
case None => rhs
case Some(k) => atPos(rhs.pos)(nonLocalReturnTry(rhs, k, tree.symbol))
}
- copy.DefDef(tree, mods, name, tparams, List(List.flatten(vparamss)), tpt, rhs1)
+ treeCopy.DefDef(tree, mods, name, tparams, List(List.flatten(vparamss)), tpt, rhs1)
case Try(body, catches, finalizer) =>
if (catches forall treeInfo.isCatchCase) tree
else {
@@ -617,10 +618,10 @@ abstract class UnCurry extends InfoTransform with TypingTransformers {
if (settings.debug.value) log("rewrote try: " + catches + " ==> " + catchall);
val catches1 = localTyper.typedCases(
tree, List(catchall), ThrowableClass.tpe, WildcardType);
- copy.Try(tree, body, catches1, finalizer)
+ treeCopy.Try(tree, body, catches1, finalizer)
}
case Apply(Apply(fn, args), args1) =>
- copy.Apply(tree, fn, args ::: args1)
+ treeCopy.Apply(tree, fn, args ::: args1)
case Ident(name) =>
assert(name != nme.WILDCARD_STAR.toTypeName)
applyUnary(tree);
diff --git a/src/compiler/scala/tools/nsc/typechecker/Analyzer.scala b/src/compiler/scala/tools/nsc/typechecker/Analyzer.scala
index a2e567282f..f341dd0df9 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Analyzer.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Analyzer.scala
@@ -18,6 +18,7 @@ trait Analyzer extends AnyRef
with EtaExpansion
with SyntheticMethods
with Unapplies
+ with NamesDefaults
{
val global : Global
import global._
diff --git a/src/compiler/scala/tools/nsc/typechecker/Contexts.scala b/src/compiler/scala/tools/nsc/typechecker/Contexts.scala
index 4a16da2b55..5b98b070ce 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Contexts.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Contexts.scala
@@ -102,6 +102,8 @@ trait Contexts { self: Analyzer =>
var imports: List[ImportInfo] = List() // currently visible imports
var openImplicits: List[Type] = List() // types for which implicit arguments
// are currently searched
+ // for a named application block (Tree) the corresponding NamedApplyInfo
+ var namedApplyBlockInfo: Option[(Tree, NamedApplyInfo)] = None
var prefix: Type = NoPrefix
var inConstructorSuffix = false // are we in a secondary constructor
// after the this constructor call?
diff --git a/src/compiler/scala/tools/nsc/typechecker/DeVirtualize.scala b/src/compiler/scala/tools/nsc/typechecker/DeVirtualize.scala
index 3dede2a699..ed1c35c1f1 100644
--- a/src/compiler/scala/tools/nsc/typechecker/DeVirtualize.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/DeVirtualize.scala
@@ -259,9 +259,9 @@ abstract class DeVirtualize extends InfoTransform with TypingTransformers {
protected def paramTypesAndIndices(tpe: Type, start: Int): List[List[(Type, Int)]] = tpe match {
case PolyType(_, restpe) => paramTypesAndIndices(restpe, start)
- case MethodType(formals, restpe) =>
- val end = start + formals.length
- (formals zip List.range(start, end)) :: paramTypesAndIndices(restpe, end)
+ case MethodType(params, restpe) =>
+ val end = start + params.length
+ (tpe.paramTypes zip List.range(start, end)) :: paramTypesAndIndices(restpe, end)
case _ =>
List()
}
@@ -398,7 +398,7 @@ abstract class DeVirtualize extends InfoTransform with TypingTransformers {
.setInfo(PolyType(List(), pt))
cclazz.info.decls enter pfield
atPos(factory.pos) {
- DefDef(pfield, vparamss => Ident(fixParamName(i)))
+ DefDef(pfield, Ident(fixParamName(i)))
}
}
}
@@ -436,14 +436,14 @@ abstract class DeVirtualize extends InfoTransform with TypingTransformers {
val abstpeSym = abstractType(clazz)
localTyper.typed {
atPos(factorySym.pos) {
- DefDef(factorySym, vparamss =>
+ DefDef(factorySym,
Block(
List(cclazzDef),
TypeApply(
Select(
gen.mkForwarder(
Select(New(TypeTree(cclazzDef.symbol.tpe)), nme.CONSTRUCTOR),
- vparamss),
+ factorySym.paramss),
Any_asInstanceOf),
List(
TypeTree(
@@ -463,7 +463,7 @@ abstract class DeVirtualize extends InfoTransform with TypingTransformers {
.resetFlag(notOVERRIDE | notFINAL)
cclazz.info.decls.enter(bridge)
val superRef: Tree = Select(Super(cclazz, nme.EMPTY.toTypeName), meth)
- DefDef(bridge, vparamss => gen.mkForwarder(superRef, vparamss))
+ DefDef(bridge, gen.mkForwarder(superRef, bridge.paramss))
}
/** Replace definitions of virtual classes by definitions of corresponding
@@ -526,13 +526,13 @@ abstract class DeVirtualize extends InfoTransform with TypingTransformers {
val pfield = paramField(sym.owner, paramFieldCount)
paramFieldCount += 1
pfield setPos pacc.pos
- paramFields += localTyper.typed(DefDef(pfield, vparamss => EmptyTree))
+ paramFields += localTyper.typed(DefDef(pfield, EmptyTree))
val pfieldRef = localTyper.typed {
atPos(pacc.pos) {
Select(This(sym.owner), pfield)
}
}
- paramFieldAccessors += copy.ValDef(pacc, mods, name, tpt, pfieldRef)
+ paramFieldAccessors += treeCopy.ValDef(pacc, mods, name, tpt, pfieldRef)
case _ =>
stat.symbol resetFlag PARAMACCESSOR // ??? can we do this
others += stat
@@ -540,11 +540,11 @@ abstract class DeVirtualize extends InfoTransform with TypingTransformers {
else
(if (stat.symbol != null && (stat.symbol hasFlag PRESUPER)) presupers else others) += stat
}
- copy.Template(tree, parents, self,
- paramFieldAccessors.toList :::
- presupers.toList :::
- paramFields.toList :::
- others.toList)
+ treeCopy.Template(tree, parents, self,
+ paramFieldAccessors.toList :::
+ presupers.toList :::
+ paramFields.toList :::
+ others.toList)
case _ =>
tree setType atPhase(ownPhase)(devirtualizeMap(tree.tpe))
}
diff --git a/src/compiler/scala/tools/nsc/typechecker/EtaExpansion.scala b/src/compiler/scala/tools/nsc/typechecker/EtaExpansion.scala
index f7c8e6d528..68f486a600 100644
--- a/src/compiler/scala/tools/nsc/typechecker/EtaExpansion.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/EtaExpansion.scala
@@ -80,11 +80,11 @@ trait EtaExpansion { self: Analyzer =>
}
tree match {
case Apply(fn, args) =>
- copy.Apply(tree, liftoutPrefix(fn), List.mapConserve(args)(liftout)) setType null
+ treeCopy.Apply(tree, liftoutPrefix(fn), List.mapConserve(args)(liftout)) setType null
case TypeApply(fn, args) =>
- copy.TypeApply(tree, liftoutPrefix(fn), args) setType null
+ treeCopy.TypeApply(tree, liftoutPrefix(fn), args) setType null
case Select(qual, name) =>
- copy.Select(tree, liftout(qual), name) setSymbol NoSymbol setType null
+ treeCopy.Select(tree, liftout(qual), name) setSymbol NoSymbol setType null
case Ident(name) =>
tree
}
@@ -99,14 +99,14 @@ trait EtaExpansion { self: Analyzer =>
def expand(tree: Tree, tpe: Type): Tree = tpe match {
case mt: ImplicitMethodType =>
tree
- case MethodType(formals, restpe) =>
+ case MethodType(paramSyms, restpe) =>
var cnt0 = 0
def cnt = {
cnt0 += 1
cnt0 - 1
}
- val params = formals map (formal =>
- ValDef(Modifiers(SYNTHETIC | PARAM), freshName(tree.pos, cnt), TypeTree(formal), EmptyTree))
+ val params = paramSyms map (sym =>
+ ValDef(Modifiers(SYNTHETIC | PARAM), sym.name, TypeTree(sym.tpe), EmptyTree))
atPos(tree.pos)(Function(params, expand(Apply(tree, params map gen.paramToArg), restpe)))
//atPos(tree.pos)(Function(params, expand(Apply(tree, args), restpe)))
case _ =>
diff --git a/src/compiler/scala/tools/nsc/typechecker/Implicits.scala b/src/compiler/scala/tools/nsc/typechecker/Implicits.scala
index 81c1acb3be..b41aff1155 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Implicits.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Implicits.scala
@@ -158,7 +158,7 @@ self: Analyzer =>
*/
private def containsError(tp: Type): Boolean = tp match {
case PolyType(tparams, restpe) => containsError(restpe)
- case MethodType(formals, restpe) => (formals exists (_.isError)) || containsError(restpe)
+ case MethodType(params, restpe) => (params map (_.tpe) exists (_.isError)) || containsError(restpe)
case _ => tp.isError
}
diff --git a/src/compiler/scala/tools/nsc/typechecker/Infer.scala b/src/compiler/scala/tools/nsc/typechecker/Infer.scala
index 9bec522e0c..7a340176d9 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Infer.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Infer.scala
@@ -37,15 +37,20 @@ trait Infer {
/** The formal parameter types corresponding to <code>formals</code>.
* If <code>formals</code> has a repeated last parameter, a list of
* (nargs - params.length + 1) copies of its type is returned.
+ * By-name types are replaced with their underlying type.
*
* @param formals ...
* @param nargs ...
*/
- def formalTypes(formals: List[Type], nargs: Int): List[Type] = {
- val formals1 = formals map {
+ def formalTypes(formals: List[Type], nargs: Int): List[Type] =
+ formalTypes(formals, nargs, true)
+
+ /** This variant allows keeping ByName parameters. Useed in NamesDefaults. */
+ def formalTypes(formals: List[Type], nargs: Int, removeByName: Boolean): List[Type] = {
+ val formals1 = if (removeByName) formals map {
case TypeRef(_, sym, List(arg)) if (sym == ByNameParamClass) => arg
case formal => formal
- }
+ } else formals
if (isVarArgs(formals1)) {
val ft = formals1.last.normalize.typeArgs.head
formals1.init ::: (for (i <- List.range(formals1.length - 1, nargs)) yield ft)
@@ -173,9 +178,9 @@ trait Infer {
* Implicit parameters are skipped.
*/
def normalize(tp: Type): Type = skipImplicit(tp) match {
- case MethodType(formals, restpe) if (!restpe.isDependent) =>
+ case MethodType(params, restpe) if (!restpe.isDependent) =>
if (util.Statistics.enabled) normM += 1
- functionType(formals, normalize(restpe))
+ functionType(params map (_.tpe), normalize(restpe))
case PolyType(List(), restpe) =>
if (util.Statistics.enabled) normP += 1
normalize(restpe)
@@ -392,7 +397,8 @@ trait Infer {
isPlausiblyCompatible(mt.resultType, pt)
case ExistentialType(tparams, qtpe) =>
isPlausiblyCompatible(qtpe, pt)
- case MethodType(formals, _) =>
+ case MethodType(params, _) =>
+ val formals = tp.paramTypes
pt.normalize match {
case TypeRef(pre, sym, args) =>
!sym.isClass || {
@@ -458,7 +464,7 @@ trait Infer {
// See test pos/jesper.scala
val varianceType = restpe match {
case mt: ImplicitMethodType if isFullyDefined(pt) =>
- MethodType(mt.paramTypes, AnyClass.tpe)
+ MethodType(mt.params, AnyClass.tpe)
case _ =>
restpe
}
@@ -543,6 +549,8 @@ trait Infer {
* Undetermined type arguments are represented by `definitions.NothingClass.tpe'.
* No check that inferred parameters conform to their bounds is made here.
*
+ * bq: was private, but need it for unapply checking
+ *
* @param tparams the type parameters of the method
* @param formals the value parameter types of the method
* @param restp the result type of the method
@@ -556,7 +564,6 @@ trait Infer {
* @return ...
* @throws NoInstance
*/
- // bq: was private, but need it for unapply checking
def methTypeArgs(tparams: List[Symbol], formals: List[Type], restpe: Type,
argtpes: List[Type], pt: Type,
uninstantiated: ListBuffer[Symbol]): List[Type] = {
@@ -612,14 +619,60 @@ trait Infer {
case _ =>
formalTypes(tp.paramTypes, n).length == n
}
+ /**
+ * Verifies whether the named application is valid. The logic is very
+ * similar to the one in NamesDefaults.removeNames.
+ *
+ * @return a triple (argtpes1, argPos, namesOk) where
+ * - argtpes1 the argument types in named application (assignments to
+ * non-parameter names are treated as assignments, i.e. type Unit)
+ * - argPos a Function1[Int, Int] mapping arguments from their current
+ * to the corresponding position in params
+ * - namesOK is false when there's an invalid use of named arguments
+ */
+ private def checkNames(argtpes: List[Type], params: List[Symbol]) = {
+ val argPos = (new Array[Int](argtpes.length)) map (x => -1)
+ var positionalAllowed = true
+ var namesOK = true
+ var index = 0
+ val argtpes1 = argtpes map {
+ case NamedType(name, tp) => // a named argument
+ var res = tp
+ val pos = params.findIndexOf(p => p.name == name && !p.hasFlag(SYNTHETIC))
+ if (pos == -1) {
+ if (positionalAllowed) { // treat assignment as positional argument
+ argPos(index) = index
+ res = UnitClass.tpe
+ } else // unknown parameter name
+ namesOK = false
+ } else if (argPos.contains(pos)) { // parameter specified twice
+ namesOK = false
+ } else {
+ positionalAllowed = false
+ argPos(index) = pos
+ }
+ index += 1
+ res
+ case tp => // a positional argument
+ argPos(index) = index
+ if (!positionalAllowed)
+ namesOK = false // positional after named
+ index += 1
+ tp
+ }
+ (argtpes1, argPos, namesOK)
+ }
/** Is there an instantiation of free type variables <code>undetparams</code>
* such that function type <code>ftpe</code> is applicable to
* <code>argtpes</code> and its result conform to <code>pt</code>?
*
* @param undetparams ...
- * @param ftpe ...
- * @param argtpes ...
+ * @param ftpe the type of the function (often a MethodType)
+ * @param argtpes the argument types; a NamedType(name, tp) for named
+ * arguments. For each NamedType, if `name' does not exist in `ftpe', that
+ * type is set to `Unit', i.e. the corresponding argument is treated as
+ * an assignment expression (@see checkNames).
* @param pt ...
* @return ...
*/
@@ -630,24 +683,75 @@ trait Infer {
alts exists (alt => isApplicable(undetparams, pre.memberType(alt), argtpes0, pt))
case ExistentialType(tparams, qtpe) =>
isApplicable(undetparams, qtpe, argtpes0, pt)
- case MethodType(formals0, _) =>
- val formals = formalTypes(formals0, argtpes0.length)
- val argtpes = actualTypes(argtpes0, formals.length)
- val restpe = ftpe.resultType(argtpes)
- if (undetparams.isEmpty) {
- (formals.length == argtpes.length &&
- isCompatible(argtpes, formals) &&
- isWeaklyCompatible(restpe, pt))
+ case MethodType(params, _) =>
+ // repeat varargs as needed, remove ByName
+ val formals = formalTypes(params map (_.tpe), argtpes0.length)
+
+ def tryTupleApply: Boolean = {
+ // if 1 formal, 1 argtpe (a tuple), otherwise unmodified argtpes0
+ val tupleArgTpe = actualTypes(argtpes0 map {
+ // no assignment is treated as named argument here
+ case NamedType(name, tp) => UnitClass.tpe
+ case tp => tp
+ }, formals.length)
+
+ argtpes0.length != tupleArgTpe.length &&
+ isApplicable(undetparams, ftpe, tupleArgTpe, pt)
+ }
+ def typesCompatible(argtpes: List[Type]) = {
+ val restpe = ftpe.resultType(argtpes)
+ if (undetparams.isEmpty) {
+ (isCompatible(argtpes, formals) &&
+ isWeaklyCompatible(restpe, pt))
+ } else {
+ try {
+ val uninstantiated = new ListBuffer[Symbol]
+ val targs = methTypeArgs(undetparams, formals, restpe, argtpes, pt, uninstantiated)
+ (exprTypeArgs(uninstantiated.toList, restpe.instantiateTypeParams(undetparams, targs), pt) ne null) &&
+ isWithinBounds(NoPrefix, NoSymbol, undetparams, targs)
+ } catch {
+ case ex: NoInstance => false
+ }
+ }
+ }
+
+ // very similar logic to doTypedApply in typechecker
+ if (argtpes0.length > formals.length) tryTupleApply
+ else if (argtpes0.length == formals.length) {
+ if (!argtpes0.exists(_.isInstanceOf[NamedType])) {
+ // fast track if no named arguments are used
+ typesCompatible(argtpes0)
+ } else {
+ // named arguments are used
+ val (argtpes1, argPos, namesOK) = checkNames(argtpes0, params)
+ if (!namesOK) false
+ // when using named application, the vararg param has to be specified exactly once
+ else if (!isIdentity(argPos) && (formals.length != params.length)) false
+ else {
+ // nb. arguments and names are OK, check if types are compatible
+ typesCompatible(reorderArgs(argtpes1, argPos))
+ }
+ }
} else {
- try {
- val uninstantiated = new ListBuffer[Symbol]
- val targs = methTypeArgs(undetparams, formals, restpe, argtpes, pt, uninstantiated)
- (exprTypeArgs(uninstantiated.toList, restpe.instantiateTypeParams(undetparams, targs), pt) ne null) &&
- isWithinBounds(NoPrefix, NoSymbol, undetparams, targs)
- } catch {
- case ex: NoInstance => false
+ // not enough arguments, check if applicable using defaults
+ val namedArgtpes = argtpes0.dropWhile {
+ case NamedType(name, _) => params.forall(_.name != name)
+ case _ => true
+ }
+ val namedParams = params.drop(argtpes0.length - namedArgtpes.length)
+ val missingParams = namedParams.filter(p => namedArgtpes.forall {
+ case NamedType(name, _) => name != p.name
+ case _ => true
+ })
+ if (missingParams.exists(!_.hasFlag(DEFAULTPARAM))) tryTupleApply
+ else {
+ val argtpes1 = argtpes0 ::: missingParams.map {
+ p => NamedType(p.name, p.tpe) // add defaults as named arguments
+ }
+ isApplicable(undetparams, ftpe, argtpes1, pt)
}
}
+
case PolyType(tparams, restpe) =>
val tparams1 = cloneSymbols(tparams)
isApplicable(tparams1 ::: undetparams, restpe.substSym(tparams, tparams1), argtpes0, pt)
@@ -657,7 +761,8 @@ trait Infer {
false
}
- private[typechecker] def isApplicableSafe(undetparams: List[Symbol], ftpe: Type, argtpes0: List[Type], pt: Type): Boolean = {
+ private[typechecker] def isApplicableSafe(undetparams: List[Symbol], ftpe: Type,
+ argtpes0: List[Type], pt: Type): Boolean = {
val reportAmbiguousErrors = context.reportAmbiguousErrors
context.reportAmbiguousErrors = false
try {
@@ -683,10 +788,10 @@ trait Infer {
alts exists (alt => isAsSpecific(pre.memberType(alt), ftpe2))
case et: ExistentialType =>
et.withTypeVars(isAsSpecific(_, ftpe2)) // !!! why isStrictly?
- case MethodType(formals @ (x :: xs), _) =>
- isApplicable(List(), ftpe2, formals, WildcardType)
- case PolyType(_, MethodType(formals @ (x :: xs), _)) =>
- isApplicable(List(), ftpe2, formals, WildcardType)
+ case MethodType(params @ (x :: xs), _) =>
+ isApplicable(List(), ftpe2, params map (_.tpe), WildcardType)
+ case PolyType(_, MethodType(params @ (x :: xs), _)) =>
+ isApplicable(List(), ftpe2, params map (_.tpe), WildcardType)
case ErrorType =>
true
case _ =>
@@ -1014,7 +1119,7 @@ trait Infer {
*/
def inferMethodInstance(fn: Tree, undetparams: List[Symbol],
args: List[Tree], pt0: Type): List[Symbol] = fn.tpe match {
- case MethodType(formals0, _) =>
+ case MethodType(params0, _) =>
if (inferInfo)
println("infer method instance "+fn+"\n"+
" undetparams = "+undetparams+"\n"+
@@ -1022,7 +1127,7 @@ trait Infer {
" pt = "+pt0)
try {
val pt = if (pt0.typeSymbol == UnitClass) WildcardType else pt0
- val formals = formalTypes(formals0, args.length)
+ val formals = formalTypes(params0 map (_.tpe), args.length)
val argtpes = actualTypes(args map (_.tpe.deconst), formals.length)
val restpe = fn.tpe.resultType(argtpes)
val uninstantiated = new ListBuffer[Symbol]
@@ -1393,24 +1498,57 @@ trait Infer {
/** Assign <code>tree</code> the type of an alternative which is applicable
* to <code>argtpes</code>, and whose result type is compatible with `pt'.
- * If several applicable alternatives exist, take the
- * most specialized one.
+ * If several applicable alternatives exist, drop the alternatives which use
+ * default arguments, then select the most specialized one.
* If no applicable alternative exists, and pt != WildcardType, try again
* with pt = WildcardType.
* Otherwise, if there is no best alternative, error.
+ *
+ * @param argtpes contains the argument types. If an argument is named, as
+ * "a = 3", the corresponding type is `NamedType("a", Int)'. If the name
+ * of some NamedType does not exist in an alternative's parameter names,
+ * the type is replaces by `Unit', i.e. the argument is treated as an
+ * assignment expression.
*/
- def inferMethodAlternative(tree: Tree, undetparams: List[Symbol], argtpes: List[Type], pt0: Type): Unit = tree.tpe match {
+ def inferMethodAlternative(tree: Tree, undetparams: List[Symbol],
+ argtpes: List[Type], pt0: Type): Unit = tree.tpe match {
case OverloadedType(pre, alts) =>
val pt = if (pt0.typeSymbol == UnitClass) WildcardType else pt0
tryTwice {
- if (settings.debug.value) log("infer method alt " + tree.symbol + " with alternatives " + (alts map pre.memberType) + ", argtpes = " + argtpes + ", pt = " + pt)
- val applicable = alts filter (alt => isApplicable(undetparams, followApply(pre.memberType(alt)), argtpes, pt))
+ if (settings.debug.value)
+ log("infer method alt "+ tree.symbol +" with alternatives "+
+ (alts map pre.memberType) +", argtpes = "+ argtpes +", pt = "+ pt)
+
+ val allApplicable = alts filter (alt =>
+ isApplicable(undetparams, followApply(pre.memberType(alt)), argtpes, pt))
+
+ // if there are multiple, drop those that use a default
+ // (keep those that use vararg / tupling conversion)
+ val applicable =
+ if (allApplicable.length <= 1) allApplicable
+ else allApplicable filter (alt => {
+ val mtypes = followApply(alt.tpe) match {
+ case OverloadedType(_, alts) =>
+ // for functional values, the `apply' method might be overloaded
+ alts map (_.tpe)
+ case t => List(t)
+ }
+ mtypes.exists(t => t.paramTypes.length < argtpes.length || // tupling (*)
+ hasExactlyNumParams(t, argtpes.length)) // same nb or vararg
+ // (*) more arguments than parameters, but still applicable: tuplig conversion works.
+ // todo: should not return "false" when paramTypes = (Unit) no argument is given
+ // (tupling would work)
+ })
+
+
def improves(sym1: Symbol, sym2: Symbol) =
sym2 == NoSymbol || sym2.isError ||
- isStrictlyMoreSpecific(followApply(pre.memberType(sym1)), followApply(pre.memberType(sym2)), sym1, sym2)
+ isStrictlyMoreSpecific(followApply(pre.memberType(sym1)),
+ followApply(pre.memberType(sym2)), sym1, sym2)
+
val best = ((NoSymbol: Symbol) /: applicable) ((best, alt) =>
if (improves(alt, best)) alt else best)
- val competing = applicable dropWhile (alt => best == alt || improves(best, alt))
+ val competing = applicable.dropWhile(alt => best == alt || improves(best, alt))
if (best == NoSymbol) {
if (pt == WildcardType) {
errorTree(tree, applyErrorMsg(tree, " cannot be applied to ", argtpes, pt))
diff --git a/src/compiler/scala/tools/nsc/typechecker/Namers.scala b/src/compiler/scala/tools/nsc/typechecker/Namers.scala
index ff60039e1f..d9dc0969f4 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Namers.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Namers.scala
@@ -44,10 +44,24 @@ trait Namers { self: Analyzer =>
private class NormalNamer(context : Context) extends Namer(context)
def newNamer(context : Context) : Namer = new NormalNamer(context)
+ // In the typeCompleter (templateSig) of a case class (resp it's module),
+ // synthetic `copy' (reps `apply', `unapply') methods are added. To compute
+ // their signatures, the corresponding ClassDef is needed.
+ // During naming, for each case class module symbol, the corresponding ClassDef
+ // is stored in this map.
private[typechecker] val caseClassOfModuleClass = new HashMap[Symbol, ClassDef]
+ // Default getters of constructors are added to the companion object in the
+ // typeCompleter of the constructor (methodSig). To compute the signature,
+ // we need the ClassDef. To create and enter the symbols into the companion
+ // object, we need the templateNamer of that module class.
+ // This map is extended during naming of classes, the Namer is added in when
+ // it's available, i.e. in the type completer (templateSig) of the module class.
+ private[typechecker] val classAndNamerOfModule = new HashMap[Symbol, (ClassDef, Namer)]
+
def resetNamer() {
caseClassOfModuleClass.clear
+ classAndNamerOfModule.clear
}
abstract class Namer(val context: Context) {
@@ -266,10 +280,10 @@ trait Namers { self: Analyzer =>
* class definition tree.
* @return the companion object symbol.
*/
- def ensureCompanionObject(tree: ClassDef, creator: ClassDef => Tree): Symbol = {
+ def ensureCompanionObject(tree: ClassDef, creator: => Tree): Symbol = {
val m: Symbol = context.scope.lookupWithContext(tree.name.toTermName)(context.owner).filter(! _.isSourceMethod)
if (m.isModule && inCurrentScope(m) && currentRun.compiles(m)) m
- else enterSyntheticSym(creator(tree))
+ else enterSyntheticSym(creator)
}
def enterSym(tree: Tree): Context = try {
@@ -284,10 +298,26 @@ trait Namers { self: Analyzer =>
//@M x is only in scope in `A[x <: B]'
if(!sym.isAbstractType) //@M TODO: change to isTypeMember ?
newNamer(context.makeNewScope(tree, sym)(FinishWithScopeKind)).enterSyms(tparams)
+
ltype = new PolyTypeCompleter(tparams, ltype, tree, sym, context) //@M
if (sym.isTerm) skolemize(tparams)
}
- setInfo(sym)(ltype)
+ if ((sym.name == nme.copy || sym.name.startsWith(nme.copy + "$default$")) &&
+ sym.hasFlag(SYNTHETIC)) {
+ // the 'copy' method of case classes needs a special type completer to make bug0054.scala (and others)
+ // work. the copy method has to take exactly the same parameter types as the primary constructor.
+ setInfo(sym)(mkTypeCompleter(tree)(copySym => {
+ val constrType = copySym.owner.primaryConstructor.tpe
+ val subst = new SubstSymMap(copySym.owner.typeParams, tparams map (_.symbol))
+ for ((params, cparams) <- tree.asInstanceOf[DefDef].vparamss.zip(constrType.paramss);
+ (param, cparam) <- params.zip(cparams)) {
+ // need to clone the type cparam.tpe??? problem is: we don't have the new owner yet (the new param symbol)
+ param.tpt.setType(subst(cparam.tpe))
+ () // @LUC TODO workaround for #1996
+ }
+ ltype.complete(sym)
+ }))
+ } else setInfo(sym)(ltype)
}
def finish = finishWith(List())
@@ -303,9 +333,21 @@ trait Namers { self: Analyzer =>
tree.symbol = enterClassSymbol(tree)
finishWith(tparams)
if ((mods.flags & CASE) != 0) {
- val m = ensureCompanionObject(tree, caseModuleDef)
+ val m = ensureCompanionObject(tree, caseModuleDef(tree))
caseClassOfModuleClass(m.moduleClass) = tree
}
+ val constrs = impl.body filter {
+ case DefDef(_, name, _, _, _, _) => name == nme.CONSTRUCTOR
+ case _ => false
+ }
+ val hasDefault = constrs.exists(c => {
+ val DefDef(_, _, _, vparamss, _, _) = c
+ vparamss.exists(_.exists(_.mods hasFlag DEFAULTPARAM))
+ })
+ if (hasDefault) {
+ val m = ensureCompanionObject(tree, companionModuleDef(tree, List(gen.scalaScalaObjectConstr)))
+ classAndNamerOfModule(m) = (tree, null)
+ }
case tree @ ModuleDef(mods, name, _) =>
tree.symbol = enterModuleSymbol(tree)
tree.symbol.moduleClass.setInfo(namerOf(tree.symbol).moduleClassTypeCompleter((tree)))
@@ -440,9 +482,10 @@ trait Namers { self: Analyzer =>
}
def setterTypeCompleter(tree: Tree) = mkTypeCompleter(tree) { sym =>
- if (settings.debug.value) log("defining " + sym);
- sym.setInfo(MethodType(List(typeSig(tree)), UnitClass.tpe))
- if (settings.debug.value) log("defined " + sym);
+ if (settings.debug.value) log("defining " + sym)
+ val param = sym.newSyntheticValueParam(typeSig(tree))
+ sym.setInfo(MethodType(List(param), UnitClass.tpe))
+ if (settings.debug.value) log("defined " + sym)
validate(sym)
}
@@ -478,12 +521,13 @@ trait Namers { self: Analyzer =>
else tpe
}
+ // sets each ValDef's symbol
def enterValueParams(owner: Symbol, vparamss: List[List[ValDef]]): List[List[Symbol]] = {
def enterValueParam(param: ValDef): Symbol = {
param.symbol = setInfo(
enterInScope{
val sym = owner.newValueParameter(param.pos, param.name).
- setFlag(param.mods.flags & (BYNAMEPARAM | IMPLICIT))
+ setFlag(param.mods.flags & (BYNAMEPARAM | IMPLICIT | DEFAULTPARAM))
setPrivateWithin(param, sym, param.mods)
})(typeCompleter(param))
param.symbol
@@ -595,24 +639,49 @@ trait Namers { self: Analyzer =>
*/
// add apply and unapply methods to companion objects of case classes,
- // unless they exist already
+ // unless they exist already; here, "clazz" is the module class
Namers.this.caseClassOfModuleClass get clazz match {
case Some(cdef) =>
addApplyUnapply(cdef, templateNamer)
caseClassOfModuleClass -= clazz
case None =>
}
+
+ // add the copy method to case classes; this needs to be done here, not in SyntheticMethods, because
+ // the namer phase must traverse this copy method to create default getters for its parameters.
+ Namers.this.caseClassOfModuleClass get clazz.linkedModuleOfClass.moduleClass match {
+ case Some(cdef) =>
+ def hasCopy(decls: Scope) = {
+ decls.elements exists (_.name == nme.copy)
+ }
+ if (!hasCopy(decls) &&
+ !parents.exists(p => hasCopy(p.typeSymbol.info.decls)) &&
+ !parents.flatMap(_.baseClasses).removeDuplicates.exists(bc => hasCopy(bc.info.decls)))
+ addCopyMethod(cdef, templateNamer)
+ case None =>
+ }
+
+ // if default getters (for constructor defaults) need to be added to that module,
+ // here's the namer to use
+ val module = clazz.sourceModule
+ if (classAndNamerOfModule contains module) {
+ val (cdef, _) = classAndNamerOfModule(module)
+ classAndNamerOfModule(module) = (cdef, templateNamer)
+ }
+
ClassInfoType(parents, decls, clazz)
}
private def classSig(tparams: List[TypeDef], impl: Template): Type =
polyType(typer.reenterTypeParams(tparams), templateSig(impl))
- private def methodSig(tparams: List[TypeDef], vparamss: List[List[ValDef]],
- tpt: Tree, rhs: Tree): Type = {
+ private def methodSig(mods: Modifiers, tparams: List[TypeDef],
+ vparamss: List[List[ValDef]], tpt: Tree, rhs: Tree): Type = {
val meth = context.owner
+ // enters the skolemized version into scope, returns the deSkolemized symbols
val tparamSyms = typer.reenterTypeParams(tparams)
+ // since the skolemized tparams are in scope, the TypeRefs in vparamSymss refer to skolemized tparams
var vparamSymss = enterValueParams(meth, vparamss)
if (tpt.isEmpty && meth.name == nme.CONSTRUCTOR) {
@@ -624,8 +693,8 @@ trait Namers { self: Analyzer =>
methodArgumentNames(meth) = vparamss.map(_.map(_.symbol));
def convertToDeBruijn(vparams: List[Symbol], level: Int): TypeMap = new TypeMap {
- def debruijnFor(param: Symbol) =
- DeBruijnIndex(level, vparams indexOf param)
+ def debruijnFor(param: Symbol) =
+ DeBruijnIndex(level, vparams indexOf param)
def apply(tp: Type) = {
tp match {
case SingleType(_, sym) =>
@@ -636,35 +705,38 @@ trait Namers { self: Analyzer =>
ErrorType
} else
*/
- debruijnFor(sym)
+ debruijnFor(sym)
} else tp
- case MethodType(formals, restpe) =>
- val formals1 = List.mapConserve(formals)(this)
+ case MethodType(params, restpe) =>
+ val params1 = this.mapOver(params)
val restpe1 = convertToDeBruijn(vparams, level + 1)(restpe)
- if ((formals1 eq formals) && (restpe1 eq restpe)) tp
- else copyMethodType(tp, formals1, restpe1)
+ if ((params1 eq params) && (restpe1 eq restpe)) tp
+ else copyMethodType(tp, params1, restpe1)
case _ =>
mapOver(tp)
}
}
- object treeTrans extends TypeMapTransformer {
- override def transform(tree: Tree): Tree =
- tree match {
- case Ident(name) if (vparams contains tree.symbol) =>
- val dtpe = debruijnFor(tree.symbol)
- val dsym =
- newLocalDummy(context.owner, tree.symbol.pos)
- .newValue(tree.symbol.pos, name)
-
- dsym.setFlag(PARAM)
- dsym.setInfo(dtpe)
- Ident(name).setSymbol(dsym).copyAttrs(tree).setType(dtpe)
- case tree => super.transform(tree)
- }
- }
-
- override def mapOver(arg: Tree) = Some(treeTrans.transform(arg))
+ // AnnotatedTypes can contain trees in the AnnotationArguments. When accessing a
+ // parameter in an annotation, set the type of the Ident to the DeBruijnIndex
+ object treeTrans extends TypeMapTransformer {
+ override def transform(tree: Tree): Tree =
+ tree match {
+ case Ident(name) if (vparams contains tree.symbol) =>
+ val dtpe = debruijnFor(tree.symbol)
+ val dsym =
+ newLocalDummy(context.owner, tree.symbol.pos)
+ .newValue(tree.symbol.pos, name)
+
+ dsym.setFlag(PARAM)
+ dsym.setInfo(dtpe)
+ Ident(name).setSymbol(dsym).copyAttrs(tree).setType(dtpe)
+ case tree => super.transform(tree)
+ }
+ }
+
+ // for type annotations (which may contain trees)
+ override def mapOver(arg: Tree) = Some(treeTrans.transform(arg))
}
val checkDependencies: TypeTraverser = new TypeTraverser {
@@ -685,27 +757,44 @@ trait Namers { self: Analyzer =>
}
}
+ /** Called for all value parameter lists, right to left
+ * @param vparams the symbols of one parameter list
+ * @param restpe the result type (possibly a MethodType)
+ */
def makeMethodType(vparams: List[Symbol], restpe: Type) = {
- val formals = vparams map (vparam =>
- if (meth hasFlag JAVA) objToAny(vparam.tpe) else vparam.tpe)
- val restpe1 = convertToDeBruijn(vparams, 1)(restpe)
+ // new dependent method types: probably OK already, since 'enterValueParams' above
+ // enters them in scope, and all have a lazy type. so they may depend on other params. but: need to
+ // check that params only depend on ones in earlier sections, not the same. (done by checkDependencies,
+ // so re-use / adapt that)
+ val params = vparams map (vparam =>
+ if (meth hasFlag JAVA) vparam.setInfo(objToAny(vparam.tpe)) else vparam)
+ val restpe1 = convertToDeBruijn(vparams, 1)(restpe) // new dependent types: replace symbols in restpe with the ones in vparams
if (!vparams.isEmpty && vparams.head.hasFlag(IMPLICIT))
- ImplicitMethodType(formals, restpe1)
- else if (meth hasFlag JAVA) JavaMethodType(formals, restpe1)
- else MethodType(formals, restpe1)
+ ImplicitMethodType(params, restpe1)
+ else if (meth hasFlag JAVA) JavaMethodType(params, restpe1)
+ else MethodType(params, restpe1)
}
def thisMethodType(restpe: Type) =
polyType(
- tparamSyms,
+ tparamSyms, // deSkolemized symbols
if (vparamSymss.isEmpty) PolyType(List(), restpe)
+ // vparamss refer (if they do) to skolemized tparams
else checkDependencies((vparamSymss :\ restpe) (makeMethodType)))
var resultPt = if (tpt.isEmpty) WildcardType else typer.typedType(tpt).tpe
val site = meth.owner.thisType
- def overriddenSymbol = intersectionType(meth.owner.info.parents).member(meth.name).filter(sym =>
- sym != NoSymbol && (site.memberType(sym) matches thisMethodType(resultPt)))
+ def overriddenSymbol = intersectionType(meth.owner.info.parents).member(meth.name).filter(sym => {
+ // luc: added .syubstSym from skolemized to deSkolemized
+ // site.memberType(sym): PolyType(tparams, MethodType(..., ...)) ==> all references to tparams are deSkolemized
+ // thisMethodType: tparams in PolyType are deSkolemized, the references in the MethodTypes are skolemized. ==> the two didn't match
+ // for instance, B.foo would not override A.foo, and the default on parameter b would not be inherited
+ // class A { def foo[T](a: T)(b: T = a) = a }
+ // class B extends A { override def foo[U](a: U)(b: U) = b }
+ // (new B).foo(1)()
+ sym != NoSymbol && (site.memberType(sym) matches thisMethodType(resultPt).substSym(tparams map (_.symbol), tparamSyms))
+ })
// fill in result type and parameter types from overridden symbol if there is a unique one.
if (meth.owner.isClass && (tpt.isEmpty || vparamss.exists(_.exists(_.tpt.isEmpty)))) {
@@ -743,7 +832,7 @@ trait Namers { self: Analyzer =>
}
}
}
- // Add a () parameter section if this overrides dome method with () parameters.
+ // Add a () parameter section if this overrides some method with () parameters.
if (meth.owner.isClass && vparamss.isEmpty && overriddenSymbol.alternatives.exists(
_.info.isInstanceOf[MethodType])) {
vparamSymss = List(List())
@@ -753,9 +842,104 @@ trait Namers { self: Analyzer =>
vparam.tpt.tpe = ErrorType
}
+
+ // add the getter methods for default arguments.
+
+ /** Adding the "override" and "defaultparam" (for inherited defaults) flags
+ * has to be done here. Typer is too late, if an inherited default is used
+ * before the method is typechecked, the corresponding param would not yet
+ * have the "defaultparam" flag.
+ */
+ val isConstr = meth.isConstructor
+ val overridden = if (isConstr || !meth.owner.isClass) NoSymbol
+ else overriddenSymbol
+ val overrides = overridden != NoSymbol && !(overridden hasFlag OVERLOADED)
+ // value parameters of the base class (whose defaults might be overridden)
+ var baseParamss = overridden.tpe.paramss
+ // match empty and missing parameter list
+ if (vparamss.isEmpty && baseParamss == List(Nil)) baseParamss = Nil
+ if (vparamss == List(Nil) && baseParamss.isEmpty) baseParamss = List(Nil)
+ assert(!overrides || vparamss.length == baseParamss.length, ""+ meth.fullNameString + ", "+ overridden.fullNameString)
+
+ var ownerNamer: Option[Namer] = None
+ var moduleNamer: Option[(ClassDef, Namer)] = None
+
+ var posCounter = 1
+
+ // for each value parameter, create the getter method if it has a default argument. previous
+ // denotes the parameter lists which are on the left side of the current one. these get added
+ // to the default getter. Example: "def foo(a: Int)(b: Int = a)" gives "foo$default$1(a: Int) = a"
+ (List[List[ValDef]]() /: (vparamss))((previous: List[List[ValDef]], vparams: List[ValDef]) => {
+ assert(!overrides || vparams.length == baseParamss.head.length, ""+ meth.fullNameString + ", "+ overridden.fullNameString)
+ var baseParams = if (overrides) baseParamss.head else Nil
+ for (vparam <- vparams) {
+ val sym = vparam.symbol
+ // true if the corresponding parameter of the base class has a default argument
+ val baseHasDefault = overrides && (baseParams.head hasFlag DEFAULTPARAM)
+ if (sym hasFlag DEFAULTPARAM) {
+ // generate a default getter for that argument
+ val oflag = if (baseHasDefault) OVERRIDE else 0
+ val name = (if (isConstr) "init" else meth.name) +"$default$"+ posCounter
+
+ // Create trees for the defaultGetter. Uses tools from Unapplies.scala
+ var deftParams = tparams map copyUntyped[TypeDef]
+ val defvParamss = previous map (_.map(p => {
+ // in the default getter, remove the default parameter
+ val p1 = atPos(p.pos) { ValDef(p.mods &~ DEFAULTPARAM, p.name, p.tpt.duplicate, EmptyTree) }
+ UnTyper.traverse(p1)
+ p1
+ }))
+ // let the compiler infer the return type of the defaultGetter. needed in "foo[T](a: T = 1)"
+ val defTpt = TypeTree()
+ val defRhs = copyUntyped(vparam.rhs)
+
+ val parentNamer = if (isConstr) {
+ val (cdef, nmr) = moduleNamer.getOrElse {
+ val module = meth.owner.linkedModuleOfClass
+ module.initialize // call type completer (typedTemplate), adds the
+ // module's templateNamer to classAndNamerOfModule
+ val (cdef, nmr) = classAndNamerOfModule(module)
+ moduleNamer = Some(cdef, nmr)
+ (cdef, nmr)
+ }
+ deftParams = cdef.tparams map copyUntypedInvariant
+ nmr
+ } else {
+ ownerNamer.getOrElse {
+ val ctx = context.nextEnclosing(c => c.scope.toList.contains(meth))
+ assert(ctx != NoContext)
+ val nmr = newNamer(ctx)
+ ownerNamer = Some(nmr)
+ nmr
+ }
+ }
+
+ val defaultTree = atPos(vparam.pos) {
+ DefDef(
+ Modifiers(meth.flags & (PRIVATE | PROTECTED | FINAL)) | SYNTHETIC | DEFAULTPARAM | oflag,
+ name, deftParams, defvParamss, defTpt, defRhs)
+ }
+ meth.owner.resetFlag(INTERFACE)
+ val default = parentNamer.enterSyntheticSym(defaultTree)
+ sym.defaultGetter = default
+ } else if (baseHasDefault) {
+ // the parameter does not have a default itself, but the corresponding parameter
+ // in the base class does.
+ sym.setFlag(DEFAULTPARAM)
+ sym.defaultGetter = baseParams.head.defaultGetter
+ }
+ posCounter += 1
+ if (overrides) baseParams = baseParams.tail
+ }
+ if (overrides) baseParamss = baseParamss.tail
+ previous ::: List(vparams)
+ })
+
thisMethodType(
if (tpt.isEmpty) {
+ // replace deSkolemized symbols with skolemized ones (for resultPt computed by looking at overridden symbol, right?)
val pt = resultPt.substSym(tparamSyms, tparams map (_.symbol))
+ // compute result type from rhs
tpt.tpe = widenIfNotFinal(meth, typer.computeType(rhs, pt), pt)
tpt setPos meth.pos
tpt.tpe
@@ -794,20 +978,16 @@ trait Namers { self: Analyzer =>
}
/** Given a case class
- *
* case class C[Ts] (ps: Us)
- *
* Add the following methods to toScope:
- *
* 1. if case class is not abstract, add
- *
* <synthetic> <case> def apply[Ts](ps: Us): C[Ts] = new C[Ts](ps)
- *
* 2. add a method
- *
* <synthetic> <case> def unapply[Ts](x: C[Ts]) = <ret-val>
- *
* where <ret-val> is the caseClassUnapplyReturnValue of class C (see UnApplies.scala)
+ *
+ * @param cdef is the class definition of the case class
+ * @param namer is the namer of the module class (the comp. obj)
*/
def addApplyUnapply(cdef: ClassDef, namer: Namer) {
if (!(cdef.symbol hasFlag ABSTRACT))
@@ -815,8 +995,14 @@ trait Namers { self: Analyzer =>
namer.enterSyntheticSym(caseModuleUnapplyMeth(cdef))
}
+ def addCopyMethod(cdef: ClassDef, namer: Namer) {
+ caseClassCopyMeth(cdef) foreach (namer.enterSyntheticSym(_))
+ }
+
def typeSig(tree: Tree): Type = {
val sym: Symbol = tree.symbol
+ // For definitions, transform Annotation trees to AnnotationInfos, assign
+ // them to the sym's attributes. Type annotations: see Typer.typedAnnotated
tree match {
case defn: MemberDef =>
val ainfos = for {
@@ -843,9 +1029,8 @@ trait Namers { self: Analyzer =>
//clazz.typeOfThis = singleType(sym.owner.thisType, sym);
clazz.tpe
- case DefDef(_, _, tparams, vparamss, tpt, rhs) =>
- //val result =
- newNamer(context.makeNewScope(tree, sym)).methodSig(tparams, vparamss, tpt, rhs)
+ case DefDef(mods, _, tparams, vparamss, tpt, rhs) =>
+ newNamer(context.makeNewScope(tree, sym)).methodSig(mods, tparams, vparamss, tpt, rhs)
case vdef @ ValDef(mods, _, tpt, rhs) =>
val typer1 = typer.constrTyperIf(sym.hasFlag(PARAM | PRESUPER) && sym.owner.isConstructor)
diff --git a/src/compiler/scala/tools/nsc/typechecker/NamesDefaults.scala b/src/compiler/scala/tools/nsc/typechecker/NamesDefaults.scala
new file mode 100644
index 0000000000..55a409775b
--- /dev/null
+++ b/src/compiler/scala/tools/nsc/typechecker/NamesDefaults.scala
@@ -0,0 +1,376 @@
+/* NSC -- new Scala compiler
+ * Copyright 2005-2009 LAMP/EPFL
+ * @author Martin Odersky
+ */
+// $Id: NamesDefaults.scala 17081 2009-02-10 17:45:38Z rytz $
+
+package scala.tools.nsc.typechecker
+
+import scala.collection.mutable.ListBuffer
+ import symtab.Flags._
+
+/**
+ * @author Lukas Rytz
+ * @version 1.0
+ */
+trait NamesDefaults { self: Analyzer =>
+
+ import global._
+ import definitions._
+
+ case class NamedApplyInfo(qual: Option[Tree], targs: List[Tree],
+ vargss: List[List[Tree]], blockTyper: Typer)
+ val noApplyInfo = NamedApplyInfo(None, Nil, Nil, null)
+
+ def nameOf(arg: Tree) = arg match {
+ case Assign(Ident(name), rhs) => Some(name)
+ case _ => None
+ }
+ def isNamed(arg: Tree) = nameOf(arg).isDefined
+
+
+ /** @param pos maps indicies from old to new */
+ def reorderArgs[T](args: List[T], pos: Int => Int): List[T] = {
+ val res = new Array[T](args.length)
+ // (hopefully) faster than zipWithIndex
+ (0 /: args) { case (index, arg) => res(pos(index)) = arg; index + 1 }
+ res.toList
+ }
+
+ /** @param pos maps indicies from new to old (!) */
+ def reorderArgsInv[T](args: List[T], pos: Int => Int): List[T] = {
+ val argsArray = args.toArray
+ val res = new ListBuffer[T]
+ for (i <- 0 until argsArray.length)
+ res += argsArray(pos(i))
+ res.toList
+ }
+
+ /** returns `true' if every element is equal to its index */
+ def isIdentity(a: Array[Int]) = (0 until a.length).forall(i => a(i) == i)
+
+ /**
+ * Transform a function application into a Block, and assigns typer.context
+ * .namedApplyBlockInfo to the new block as side-effect. If tree has the form
+ * Apply(fun, args)
+ * first the function "fun" (which might be an application itself!) is transformed into a
+ * block of the form
+ * {
+ * val qual$1 = qualifier_of_fun
+ * val x$1 = arg_1_of_fun
+ * ...
+ * val x$n = arg_n_of_fun
+ * qual$1.fun[targs](x$1, ...)...(..., x$n)
+ * }
+ * then for each argument in args, a value is created and entered into the block. finally
+ * the application expression of the block is updated.
+ * {
+ * val qual$1 = ..
+ * ...
+ * val x$n = ...
+ * > val qual$n+1 = arg(1)
+ * > ...
+ * > val qual$n+m = arg(m)
+ * > qual$1.fun[targs](x$1, ...)...(..., x$n)(x$n+1, ..., x$n+m)
+ * }
+ *
+ * @param typer the typer calling this method; this method calls
+ * typer.doTypedApply
+ * @param mode the mode to use for calling typer.doTypedApply
+ * @param pt the expected type for calling typer.doTypedApply
+ *
+ * @param tree: the function application tree
+ * @argPos: a function mapping arguments from their current position to the
+ * position specified by the method type. example:
+ * def foo(a: Int, b: String)
+ * foo(b = "1", a = 2)
+ * calls
+ * transformNamedApplication(Apply(foo, List("1", 2), { 0 => 1, 1 => 0 })
+ *
+ * @return the transformed application (a Block) together with the NamedApplyInfo.
+ * if isNamedApplyBlock(tree), returns the existing context.namedApplyBlockInfo
+ */
+ def transformNamedApplication(typer: Typer, mode: Int, pt: Type)
+ (tree: Tree, argPos: Int => Int): Tree = {
+ import typer._
+ import typer.infer._
+ val context = typer.context
+ import context.unit
+
+ /**
+ * Transform a function into a block, and assing context.namedApplyBlockInfo to
+ * the new block as side-effect.
+ * Fun is transformed in the following way:
+ * - Ident(f) ==> Block(Nil, Ident(f))
+ * - Select(qual, f) if (qual is stable) ==> Block(Nil, Select(qual, f))
+ * - Select(qual, f) otherwise ==> Block(ValDef(qual$1, qual), Select(qual$1, f))
+ * - TypeApply(fun, targs) ==> Block(Nil or qual$1, TypeApply(fun, targs))
+ * - Select(New(TypeTree()), <init>) ==> Block(Nil, Select(New(TypeTree()), <init>))
+ * - Select(New(Select(qual, typeName)), <init>) if (qual is stable)
+ * ==> Block(Nil, Select(...))
+ * - Select(New(Select(qual, typeName)), <init>) otherwise
+ * ==> Block(ValDef(qual$1, qual), Select(New(Select(qual$1, typeName)), <init>))
+ */
+ def baseFunBlock(baseFun: Tree): Tree = {
+ val isConstr = baseFun.symbol.isConstructor
+ val blockTyper = newTyper(context.makeNewScope(tree, context.owner)(BlockScopeKind(context.depth)))
+
+ // baseFun1: the extract the function from a potential TypeApply
+ // defaultTargs: type arguments to be used for calling defaultGetters
+ // funTargs: type arguments on baseFun, used to reconstruct TypeApply in blockWith(Out)Qualifier
+ val (baseFun1, defaultTargs, funTargs) = baseFun match {
+ case TypeApply(fun, targs) =>
+ val targsInSource =
+ if (targs.forall(a => context.undetparams contains a.symbol)) Nil
+ else targs
+ (fun, targsInSource, targs)
+
+ case Select(New(tpt @ TypeTree()), _) if isConstr =>
+ val targs = tpt.tpe match {
+ case TypeRef(pre, sym, args) if (args forall (a => context.undetparams contains a)) =>
+ args.map(TypeTree(_))
+ case _ => Nil
+ }
+ (baseFun, targs, Nil)
+
+ case _ => (baseFun, Nil, Nil)
+ }
+
+ def blockWithQualifier(qual: Tree, fun: Symbol => Tree, defaultQual: Symbol => Option[Tree]) = {
+ val sym = blockTyper.context.owner.newValue(baseFun1.pos,
+ unit.fresh.newName(baseFun1.pos, "qual$"))
+ .setInfo(qual.tpe)
+ blockTyper.context.scope.enter(sym)
+ val vd = atPos(sym.pos) { ValDef(sym, qual).setType(NoType) }
+ var baseFunTransformed: Tree = fun(sym)
+ if (!funTargs.isEmpty)
+ baseFunTransformed = treeCopy.TypeApply(baseFun, baseFunTransformed, funTargs)
+ val b = atPos(baseFun1.pos) { Block(List(vd), baseFunTransformed)
+ .setType(baseFunTransformed.tpe) }
+ context.namedApplyBlockInfo =
+ Some((b, NamedApplyInfo(defaultQual(sym), defaultTargs, Nil, blockTyper)))
+ b
+ }
+
+ def blockWithoutQualifier(fun: Tree, defaultQual: Option[Tree]) = {
+ val fun1 = if (funTargs.isEmpty) fun
+ else treeCopy.TypeApply(baseFun, fun, funTargs)
+ val b = atPos(baseFun.pos) { Block(Nil, fun1).setType(fun1.tpe) }
+ context.namedApplyBlockInfo =
+ Some((b, NamedApplyInfo(defaultQual, defaultTargs, Nil, blockTyper)))
+ b
+ }
+
+ baseFun1 match {
+ // constructor calls
+
+ case Select(New(TypeTree()), _) if isConstr =>
+ val module = baseFun.symbol.owner.linkedModuleOfClass
+ val defaultQual = if (module == NoSymbol) None
+
+ else Some(gen.mkAttributedRef(module))
+ blockWithoutQualifier(baseFun1, defaultQual)
+
+ case Select(New(Ident(_)), _) if isConstr =>
+ blockWithoutQualifier(baseFun1, None)
+
+ case Select(nev @ New(sel @ Select(qual, typeName)), constr) if isConstr =>
+ val module = baseFun.symbol.owner.linkedModuleOfClass
+ val defaultQual = if (module == NoSymbol) None
+ else Some(gen.mkAttributedRef(module))
+ if (treeInfo.isPureExpr(qual)) {
+ blockWithoutQualifier(baseFun1, defaultQual)
+ } else {
+ val fun: Symbol => Tree =
+ sym => treeCopy.Select(baseFun1,
+ treeCopy.New(nev,
+ treeCopy.Select(sel, gen.mkAttributedRef(sym), typeName)),
+ constr)
+ blockWithQualifier(qual, fun, sym => defaultQual)
+ }
+
+ // other method calls
+
+ case Ident(_) =>
+ blockWithoutQualifier(baseFun1, None)
+
+ case Select(qual, name) =>
+ assert(!isConstr, baseFun1)
+ if (treeInfo.isPureExpr(qual))
+ blockWithoutQualifier(baseFun1, Some(qual.duplicate))
+ else
+ blockWithQualifier(qual,
+ sym => treeCopy.Select(baseFun1, gen.mkAttributedRef(sym), name),
+ sym => Some(gen.mkAttributedRef(sym)))
+ }
+ }
+
+ /**
+ * For each argument (arg: T), create a local value
+ * x$n: T = arg
+ *
+ * assumes "args" are typed. owner of the definitions in the block is the owner of
+ * the block (see typedBlock), but the symbols have to be entered into the block's scope.
+ *
+ * For by-name parameters, create a value
+ * x$n: () => T = () => arg
+ */
+ def argValDefs(args: List[Tree], paramTypes: List[Type], blockTyper: Typer): List[ValDef] = {
+ val context = blockTyper.context
+ val symPs = List.map2(args, paramTypes)((arg, tpe) => {
+ val byName = tpe.typeSymbol == ByNameParamClass
+ val s = context.owner.newValue(arg.pos, unit.fresh.newName(arg.pos, "x$"))
+ val valType = if (byName) functionType(List(), arg.tpe)
+ else arg.tpe
+ s.setInfo(valType)
+ (context.scope.enter(s), byName)
+ })
+ List.map2(symPs, args)((symP, arg) => {
+ val (sym, byName) = symP
+ val body = if (byName) blockTyper.typed(Function(List(), arg))
+ else arg
+ ValDef(sym, body).setType(NoType)
+ })
+ }
+
+ // begin transform
+ if (treeInfo.isSelfConstrCall(tree)) {
+ errorTree(tree, "using named or default arguments in a self constructor call is not allowed")
+ } else if (treeInfo.isSuperConstrCall(tree)) {
+ errorTree(tree, "using named or default arguments in a super constructor call is not allowed")
+ } else if (isNamedApplyBlock(tree)) {
+ context.namedApplyBlockInfo.get._1
+ } else tree match {
+ // we know that Apply(Apply(...)) can only be an application of a curried method;
+ // for functions, it's transformed to applying the .apply() method already.
+ case Apply(fun, namelessArgs) =>
+ val transformedFun = transformNamedApplication(typer, mode, pt)(fun, x => x)
+ if (transformedFun.isErroneous) setError(tree)
+ else {
+ assert(isNamedApplyBlock(transformedFun), transformedFun)
+ val NamedApplyInfo(qual, targs, vargss, blockTyper) =
+ context.namedApplyBlockInfo.get._2
+ val existingBlock @ Block(stats, funOnly) = transformedFun
+
+ // type the application without names; put the arguments in definition-site order
+ val typedApp = doTypedApply(tree, funOnly, reorderArgs(namelessArgs, argPos), mode, pt)
+
+ if (typedApp.tpe.isError) setError(tree)
+ else typedApp match {
+ // Extract the typed arguments, restore the call-site evaluation order (using
+ // ValDef's in the block), change the arguments to these local values.
+ case Apply(expr, typedArgs) =>
+ // typedArgs: definition-site order
+ val formals = formalTypes(expr.tpe.paramTypes, typedArgs.length, false)
+ // valDefs: call-site order
+ val valDefs = argValDefs(reorderArgsInv(typedArgs, argPos),
+ reorderArgsInv(formals, argPos),
+ blockTyper)
+ // refArgs: definition-site order again
+ val refArgs = List.map2(reorderArgs(valDefs, argPos), formals)((vDef, tpe) => {
+ val ref = gen.mkAttributedRef(vDef.symbol)
+ // for by-name parameters, the local value is a nullary function returning the argument
+ if (tpe.typeSymbol == ByNameParamClass) Apply(ref, List())
+ else ref
+ })
+ // cannot call blockTyper.typedBlock here, because the method expr might be partially applied only
+ val res = blockTyper.doTypedApply(tree, expr, refArgs, mode, pt)
+ val block = treeCopy.Block(existingBlock, stats ::: valDefs, res).setType(res.tpe)
+ context.namedApplyBlockInfo =
+ Some((block, NamedApplyInfo(qual, targs, vargss ::: List(refArgs), blockTyper)))
+ block
+ }
+ }
+
+ // case ApplyDynamic??? case AppliedTypeTree???
+
+ case baseFun => // also treats "case TypeApply(fun, targs)" and "case Select(New(..), <init>)"
+ baseFunBlock(baseFun)
+
+ }
+ }
+
+
+ /**
+ * Extend the argument list `givenArgs' with default arguments. Defaults are added
+ * as named arguments calling the corresponding default getter.
+ *
+ * Example: given
+ * def foo(x: Int = 2, y: String = "def")
+ * foo(1)
+ * the argument list (y = "lt") is transformed to (y = "lt", x = foo$default$1())
+ */
+ def addDefaults(givenArgs: List[Tree], qual: Option[Tree], targs: List[Tree],
+ previousArgss: List[List[Tree]], params: List[Symbol]): (List[Tree], List[Symbol]) = {
+ if (givenArgs.length < params.length) {
+ val namedArgs = givenArgs.dropWhile( arg => {
+ val n = nameOf(arg)
+ !(n.isDefined && params.exists(p => p.name == n.get))
+ })
+ val namedParams = params.drop(givenArgs.length - namedArgs.length)
+
+ def missing(p: Symbol): Boolean = !namedArgs.exists {
+ case Assign(Ident(name), _) => name == p.name
+ case _ => false
+ }
+
+ val missingParams = namedParams filter missing
+
+ if (missingParams forall (_.hasFlag(DEFAULTPARAM))) {
+ val defaultArgs = missingParams map (p => {
+ var default1 = qual match {
+ case Some(q) => gen.mkAttributedSelect(q.duplicate, p.defaultGetter)
+ case None => gen.mkAttributedRef(p.defaultGetter)
+ }
+ default1 = if (targs.isEmpty) default1
+ else TypeApply(default1, targs.map(_.duplicate)).setPos(p.pos)
+ val default2 = (default1 /: previousArgss)((tree, args) =>
+ Apply(tree, args.map(_.duplicate)).setPos(p.pos))
+ Assign(Ident(p.name), default2)
+ })
+ (givenArgs ::: defaultArgs, Nil)
+ } else (givenArgs, missingParams filter (! _.hasFlag(DEFAULTPARAM)))
+ } else (givenArgs, Nil)
+ }
+
+ /**
+ * Removes name assignments from args. Additionally, returns an array mapping
+ * argument indicies from call-site-order to definition-site-order.
+ *
+ * Verifies that names are not specified twice, positional args don't appear
+ * after named ones.
+ */
+ def removeNames(typer: Typer)(args: List[Tree], params: List[Symbol]): (List[Tree], Array[Int]) = {
+ import typer.infer.errorTree
+
+ // maps indicies from (order written by user) to (order of definition)
+ val argPos = (new Array[Int](args.length)) map (x => -1)
+ var positionalAllowed = true
+ // @LUC TODO: make faster (don't use zipWithIndex)
+ val namelessArgs = for ((arg, index) <- (args.zipWithIndex)) yield arg match {
+ case Assign(Ident(name), rhs) =>
+ val pos = params.findIndexOf(p => p.name == name && !p.hasFlag(SYNTHETIC))
+ if (pos == -1) {
+ if (positionalAllowed) {
+ argPos(index) = index
+ // prevent isNamed from being true when calling doTypedApply recursively,
+ // treat the arg as an assignment of type Unit
+ Block(List(), arg)
+ } else {
+ errorTree(arg, "unknown parameter name: "+ name)
+ }
+ } else if (argPos contains pos) {
+ errorTree(arg, "parameter specified twice: "+ name)
+ } else {
+ positionalAllowed = false
+ argPos(index) = pos
+ rhs
+ }
+ case _ =>
+ argPos(index) = index
+ if (positionalAllowed) arg
+ else errorTree(arg, "positional after named argument.")
+ }
+ (namelessArgs, argPos)
+ }
+}
diff --git a/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala b/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala
index 686824a7f5..0403e50dcd 100644
--- a/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala
@@ -709,7 +709,7 @@ abstract class RefChecks extends InfoTransform {
assert(lazyDefSym != NoSymbol, vsym)
val ownerTransformer = new ChangeOwnerTraverser(vsym, lazyDefSym)
val lazyDef = atPos(tree.pos)(
- DefDef(lazyDefSym, vparamss => ownerTransformer(
+ DefDef(lazyDefSym, ownerTransformer(
if (tree.symbol.owner.isTrait // for traits, this is further tranformed in mixins
|| hasUnitType) rhs
else Block(List(
@@ -849,7 +849,7 @@ abstract class RefChecks extends InfoTransform {
tree match {
case DefDef(mods, name, tparams, vparams, tpt, EmptyTree) if tree.symbol.hasAttribute(definitions.NativeAttr) =>
tree.symbol.resetFlag(DEFERRED)
- result = transform(copy.DefDef(tree, mods, name, tparams, vparams, tpt,
+ result = transform(treeCopy.DefDef(tree, mods, name, tparams, vparams, tpt,
typed(Apply(gen.mkAttributedRef(definitions.Predef_error), List(Literal("native method stub"))))))
case DefDef(_, _, _, _, _, _) =>
@@ -942,7 +942,7 @@ abstract class RefChecks extends InfoTransform {
inPattern = true
val pat1 = transform(pat)
inPattern = false
- copy.CaseDef(tree, pat1, transform(guard), transform(body))
+ treeCopy.CaseDef(tree, pat1, transform(guard), transform(body))
case _ =>
super.transform(result)
}
diff --git a/src/compiler/scala/tools/nsc/typechecker/SuperAccessors.scala b/src/compiler/scala/tools/nsc/typechecker/SuperAccessors.scala
index 7b84b70041..f19cdd7d95 100644
--- a/src/compiler/scala/tools/nsc/typechecker/SuperAccessors.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/SuperAccessors.scala
@@ -114,7 +114,7 @@ abstract class SuperAccessors extends transform.Transform with transform.TypingT
superAcc.setInfo(superAccTpe.cloneInfo(superAcc))
//println("creating super acc "+superAcc+":"+superAcc.tpe)//DEBUG
clazz.info.decls enter superAcc;
- accDefBuf(clazz) += typed(DefDef(superAcc, vparamss => EmptyTree))
+ accDefBuf(clazz) += typed(DefDef(superAcc, EmptyTree))
}
atPos(sup.pos) {
Select(gen.mkAttributedThis(clazz), superAcc) setType tree.tpe;
@@ -154,7 +154,7 @@ abstract class SuperAccessors extends transform.Transform with transform.TypingT
curTree = tree
val body1 = atOwner(currentOwner) { transformTrees(body) }
accDefs = accDefs.tail;
- copy.Template(tree, parents, self, ownAccDefs.toList ::: body1);
+ treeCopy.Template(tree, parents, self, ownAccDefs.toList ::: body1);
case TypeApply(sel @ Select(This(_), name), args) =>
val sym = tree.symbol
@@ -220,10 +220,10 @@ abstract class SuperAccessors extends transform.Transform with transform.TypingT
case Apply(fn, args) =>
assert(fn.tpe != null, tree)
- copy.Apply(tree, transform(fn), transformArgs(args, fn.tpe.paramTypes))
+ treeCopy.Apply(tree, transform(fn), transformArgs(args, fn.tpe.paramTypes))
case Function(vparams, body) =>
withInvalidOwner {
- copy.Function(tree, vparams, transform(body))
+ treeCopy.Function(tree, vparams, transform(body))
}
case _ =>
super.transform(tree)
@@ -260,7 +260,7 @@ abstract class SuperAccessors extends transform.Transform with transform.TypingT
/** Return a list of list of types of all value parameter sections. */
def allParamTypes(tpe: Type): List[List[Type]] = tpe match {
case PolyType(_, restpe) => allParamTypes(restpe)
- case MethodType(pts, res) => pts :: allParamTypes(res)
+ case MethodType(params, res) => params.map(_.tpe) :: allParamTypes(res)
case _ => Nil
}
@@ -274,21 +274,25 @@ abstract class SuperAccessors extends transform.Transform with transform.TypingT
// if the result type depends on the this type of an enclosing class, the accessor
// has to take an object of exactly this type, otherwise it's more general
val objType = if (isThisType(memberType.finalResultType)) clazz.thisType else clazz.typeOfThis
- val accType = memberType match {
+ val accType = (protAcc: Symbol) => memberType match {
case PolyType(tparams, restpe) =>
- PolyType(tparams, MethodType(List(objType), restpe.asSeenFrom(qual.tpe, sym.owner)))
+ // luc: question to author: should the tparams symbols not be cloned and get a new owner (protAcc)?
+ PolyType(tparams, MethodType(List(protAcc.newSyntheticValueParam(objType)),
+ restpe.cloneInfo(protAcc).asSeenFrom(qual.tpe, sym.owner)))
case _ =>
- MethodType(List(objType), memberType.asSeenFrom(qual.tpe, sym.owner))
+ MethodType(List(protAcc.newSyntheticValueParam(objType)),
+ memberType.cloneInfo(protAcc).asSeenFrom(qual.tpe, sym.owner))
}
if (settings.debug.value) log("accType: " + accType)
- var protAcc = clazz.info.decl(accName).suchThat(_.tpe == accType)
+ var protAcc = clazz.info.decl(accName).suchThat(s => s == NoSymbol || s.tpe =:= accType(s))
if (protAcc == NoSymbol) {
- protAcc = clazz.newMethod(tree.pos, nme.protName(sym.originalName)).setInfo(accType)
+ protAcc = clazz.newMethod(tree.pos, nme.protName(sym.originalName))
+ protAcc.setInfo(accType(protAcc))
clazz.info.decls.enter(protAcc);
- val code = DefDef(protAcc, vparamss => {
- val obj = vparamss.head.head // receiver
- vparamss.tail.zip(allParamTypes(sym.tpe)).foldLeft(Select(Ident(obj), sym): Tree) (
+ val code = DefDef(protAcc, {
+ val obj = protAcc.paramss.head.head // receiver
+ protAcc.paramss.tail.zip(allParamTypes(sym.tpe)).foldLeft(Select(Ident(obj), sym): Tree) (
(fun, pvparams) => {
Apply(fun, (List.map2(pvparams._1, pvparams._2) { (v, origTpe) => makeArg(v, obj, origTpe) } ))
})
@@ -362,10 +366,11 @@ abstract class SuperAccessors extends transform.Transform with transform.TypingT
var protAcc = clazz.info.decl(accName)
if (protAcc == NoSymbol) {
protAcc = clazz.newMethod(field.pos, nme.protSetterName(field.originalName))
- .setInfo(MethodType(List(clazz.typeOfThis, field.tpe), definitions.UnitClass.tpe));
+ protAcc.setInfo(MethodType(protAcc.newSyntheticValueParams(List(clazz.typeOfThis, field.tpe)),
+ definitions.UnitClass.tpe))
clazz.info.decls.enter(protAcc)
- val code = DefDef(protAcc, vparamss => {
- val obj :: value :: Nil = vparamss.head;
+ val code = DefDef(protAcc, {
+ val obj :: value :: Nil = protAcc.paramss.head;
atPos(tree.pos) {
Assign(
Select(Ident(obj), field.name),
diff --git a/src/compiler/scala/tools/nsc/typechecker/SyntheticMethods.scala b/src/compiler/scala/tools/nsc/typechecker/SyntheticMethods.scala
index 00468abc8e..eae6eedc00 100644
--- a/src/compiler/scala/tools/nsc/typechecker/SyntheticMethods.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/SyntheticMethods.scala
@@ -59,13 +59,13 @@ trait SyntheticMethods { self: Analyzer =>
}
}
- def syntheticMethod(name: Name, flags: Int, tpe: Type) =
- newSyntheticMethod(name, flags | OVERRIDE, tpe)
+ def syntheticMethod(name: Name, flags: Int, tpeCons: Symbol => Type) =
+ newSyntheticMethod(name, flags | OVERRIDE, tpeCons)
- def newSyntheticMethod(name: Name, flags: Int, tpe: Type) = {
+ def newSyntheticMethod(name: Name, flags: Int, tpeCons: Symbol => Type) = {
var method = clazz.newMethod(clazz.pos, name)
.setFlag(flags | SYNTHETICMETH)
- .setInfo(tpe)
+ method.setInfo(tpeCons(method))
method = clazz.info.decls.enter(method).asInstanceOf[TermSymbol]
method
}
@@ -77,31 +77,32 @@ trait SyntheticMethods { self: Analyzer =>
}
*/
def productPrefixMethod: Tree = {
- val method = syntheticMethod(nme.productPrefix, 0, PolyType(List(), StringClass.tpe))
- typer.typed(DefDef(method, vparamss => Literal(Constant(clazz.name.decode))))
+ val method = syntheticMethod(nme.productPrefix, 0, sym => PolyType(List(), StringClass.tpe))
+ typer.typed(DefDef(method, Literal(Constant(clazz.name.decode))))
}
def productArityMethod(nargs:Int ): Tree = {
- val method = syntheticMethod(nme.productArity, 0, PolyType(List(), IntClass.tpe))
- typer.typed(DefDef(method, vparamss => Literal(Constant(nargs))))
+ val method = syntheticMethod(nme.productArity, 0, sym => PolyType(List(), IntClass.tpe))
+ typer.typed(DefDef(method, Literal(Constant(nargs))))
}
def productElementMethod(accs: List[Symbol]): Tree = {
//val retTpe = lub(accs map (_.tpe.resultType))
- val method = syntheticMethod(nme.productElement, 0, MethodType(List(IntClass.tpe), AnyClass.tpe/*retTpe*/))
- typer.typed(DefDef(method, vparamss => Match(Ident(vparamss.head.head), {
+ val method = syntheticMethod(nme.productElement, 0,
+ sym => MethodType(sym.newSyntheticValueParams(List(IntClass.tpe)), AnyClass.tpe/*retTpe*/))
+ typer.typed(DefDef(method, Match(Ident(method.paramss.head.head), {
(for ((sym,i) <- accs.zipWithIndex) yield {
CaseDef(Literal(Constant(i)),EmptyTree, Ident(sym))
}):::List(CaseDef(Ident(nme.WILDCARD), EmptyTree,
Throw(New(TypeTree(IndexOutOfBoundsExceptionClass.tpe), List(List(
- Select(Ident(vparamss.head.head), nme.toString_)
+ Select(Ident(method.paramss.head.head), nme.toString_)
))))))
})))
}
def moduleToStringMethod: Tree = {
- val method = syntheticMethod(nme.toString_, FINAL, MethodType(List(), StringClass.tpe))
- typer.typed(DefDef(method, vparamss => Literal(Constant(clazz.name.decode))))
+ val method = syntheticMethod(nme.toString_, FINAL, sym => MethodType(List(), StringClass.tpe))
+ typer.typed(DefDef(method, Literal(Constant(clazz.name.decode))))
}
def forwardingMethod(name: Name): Tree = {
@@ -110,13 +111,14 @@ trait SyntheticMethods { self: Analyzer =>
if (target.tpe.paramTypes.isEmpty) List()
else target.tpe.paramTypes.tail
val method = syntheticMethod(
- name, 0, MethodType(paramtypes, target.tpe.resultType))
- typer.typed(DefDef(method, vparamss =>
- Apply(gen.mkAttributedRef(target), This(clazz) :: (vparamss.head map Ident))))
+ name, 0, sym => MethodType(sym.newSyntheticValueParams(paramtypes), target.tpe.resultType))
+ typer.typed(DefDef(method,
+ Apply(gen.mkAttributedRef(target), This(clazz) :: (method.paramss.head map Ident))))
}
def equalsSym =
- syntheticMethod(nme.equals_, 0, MethodType(List(AnyClass.tpe), BooleanClass.tpe))
+ syntheticMethod(nme.equals_, 0,
+ sym => MethodType(sym.newSyntheticValueParams(List(AnyClass.tpe)), BooleanClass.tpe))
/** The equality method for case modules:
* def equals(that: Any) = this eq that
@@ -124,13 +126,13 @@ trait SyntheticMethods { self: Analyzer =>
def equalsModuleMethod: Tree = {
val method = equalsSym
val methodDef =
- DefDef(method, vparamss =>
+ DefDef(method,
Apply(
Select(This(clazz), Object_eq),
List(
TypeApply(
Select(
- Ident(vparamss.head.head),
+ Ident(method.paramss.head.head),
Any_asInstanceOf),
List(TypeTree(AnyRefClass.tpe))))))
localTyper.typed(methodDef)
@@ -149,9 +151,8 @@ trait SyntheticMethods { self: Analyzer =>
val method = equalsSym
val methodDef =
DefDef(
- method,
- { vparamss =>
- val that = Ident(vparamss.head.head)
+ method, {
+ val that = Ident(method.paramss.head.head)
val constrParamTypes = clazz.primaryConstructor.tpe.paramTypes
val hasVarArgs = !constrParamTypes.isEmpty && constrParamTypes.last.typeSymbol == RepeatedParamClass
if (false && clazz.isStatic) {
@@ -165,7 +166,7 @@ trait SyntheticMethods { self: Analyzer =>
Boolean_and),
List(
Apply(gen.mkAttributedRef(target),
- This(clazz) :: (vparamss.head map Ident))))
+ This(clazz) :: (method.paramss.head map Ident))))
} else {
val (pat, guard) = {
val guards = new ListBuffer[Tree]
@@ -215,8 +216,8 @@ trait SyntheticMethods { self: Analyzer =>
// !!! the synthetic method "readResolve" should be private,
// but then it is renamed !!!
val method = newSyntheticMethod(nme.readResolve, PROTECTED,
- MethodType(List(), ObjectClass.tpe))
- typer.typed(DefDef(method, vparamss => gen.mkAttributedRef(clazz.sourceModule)))
+ sym => MethodType(List(), ObjectClass.tpe))
+ typer.typed(DefDef(method, gen.mkAttributedRef(clazz.sourceModule)))
}
def newAccessorMethod(tree: Tree): Tree = tree match {
@@ -225,7 +226,7 @@ trait SyntheticMethods { self: Analyzer =>
newAcc.name = context.unit.fresh.newName(tree.symbol.pos, tree.symbol.name + "$")
newAcc.setFlag(SYNTHETIC).resetFlag(ACCESSOR | PARAMACCESSOR | PRIVATE)
newAcc = newAcc.owner.info.decls enter newAcc
- val result = typer.typed(DefDef(newAcc, vparamss => rhs.duplicate))
+ val result = typer.typed(DefDef(newAcc, rhs.duplicate))
log("new accessor method " + result)
result
}
@@ -246,9 +247,10 @@ trait SyntheticMethods { self: Analyzer =>
context.unit.error(sym.pos, "a definition of `"+name1+"' already exists in " + clazz)
NoSymbol
} else {
- clazz.newMethod(sym.pos, name1)
- .setInfo(sym.info)
- .setFlag(sym.getFlag(DEFERRED | OVERRIDE | STATIC))
+ val m = clazz.newMethod(sym.pos, name1)
+ m.setInfo(sym.info.cloneInfo(clazz))
+ .setFlag(sym.getFlag(DEFERRED | OVERRIDE | STATIC))
+ m
}
}
@@ -260,7 +262,7 @@ trait SyntheticMethods { self: Analyzer =>
clazz.info.decls.enter(getter)
ts += typer.typed(DefDef(
getter,
- vparamss => if (sym hasFlag DEFERRED) EmptyTree else gen.mkAttributedRef(sym)))
+ if (sym hasFlag DEFERRED) EmptyTree else gen.mkAttributedRef(sym)))
}
}
@@ -270,9 +272,8 @@ trait SyntheticMethods { self: Analyzer =>
clazz.info.decls.enter(setter)
ts += typer.typed(DefDef(
setter,
- vparamss =>
- if (sym hasFlag DEFERRED) EmptyTree
- else Apply(gen.mkAttributedRef(sym), List(Ident(vparamss.head.head)))))
+ if (sym hasFlag DEFERRED) EmptyTree
+ else Apply(gen.mkAttributedRef(sym), List(Ident(setter.paramss.head.head)))))
}
}
@@ -338,7 +339,7 @@ trait SyntheticMethods { self: Analyzer =>
}
}
val synthetics = ts.toList
- copy.Template(
+ treeCopy.Template(
templ, templ.parents, templ.self, if (synthetics.isEmpty) templ.body else templ.body ::: synthetics)
}
}
diff --git a/src/compiler/scala/tools/nsc/typechecker/Typers.scala b/src/compiler/scala/tools/nsc/typechecker/Typers.scala
index 002830bd0c..e6aa3119e1 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Typers.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Typers.scala
@@ -37,8 +37,11 @@ trait Typers { self: Analyzer =>
var failedOpEqs = 0L
var failedSilent = 0L
+ // namer calls typer.computeType(rhs) on DefDef / ValDef when tpt is empty. the result
+ // is cached here and re-used in typedDefDef / typedValDef
private val transformed = new HashMap[Tree, Tree]
+ // currently not used at all (March 09)
private val superDefs = new HashMap[Symbol, ListBuffer[Tree]]
def resetTyper() {
@@ -172,14 +175,14 @@ trait Typers { self: Analyzer =>
/** Find implicit arguments and pass them to given tree.
*/
def applyImplicitArgs(tree: Tree): Tree = tree.tpe match {
- case MethodType(formals, _) =>
+ case MethodType(params, _) =>
def implicitArg(pt: Type): SearchResult = {
val result = inferImplicit(tree, pt, true, context)
if (result == SearchFailure)
context.error(tree.pos, "no implicit argument matching parameter type "+pt+" was found.")
result
}
- val argResults = formals map implicitArg
+ val argResults = params map (_.tpe) map implicitArg
val args = argResults map (_.tree)
for (s <- argResults map (_.subst)) {
s traverse tree
@@ -206,14 +209,15 @@ trait Typers { self: Analyzer =>
case OverloadedType(_, _) => EmptyTree
case PolyType(_, _) => EmptyTree
case _ =>
- def wrapImplicit(from: Type): Tree = {
+ val dummyMethod = new TermSymbol(NoSymbol, NoPosition, "typer$dummy")
+ def wrapImplicit(from: Symbol): Tree = {
val result = inferImplicit(tree, MethodType(List(from), to), reportAmbiguous, context)
if (result.subst != EmptyTreeTypeSubstituter) result.subst traverse tree
result.tree
}
- val result = wrapImplicit(from)
+ val result = wrapImplicit(dummyMethod.newSyntheticValueParam(from))
if (result != EmptyTree) result
- else wrapImplicit(appliedType(ByNameParamClass.typeConstructor, List(from)))
+ else wrapImplicit(dummyMethod.newSyntheticValueParam(appliedType(ByNameParamClass.typeConstructor, List(from))))
}
}
@@ -683,10 +687,12 @@ trait Typers { self: Analyzer =>
val context1 = context.makeSilent(context.reportAmbiguousErrors)
context1.undetparams = context.undetparams
context1.savedTypeBounds = context.savedTypeBounds
+ context1.namedApplyBlockInfo = context.namedApplyBlockInfo
val typer1 = newTyper(context1)
val result = op(typer1)
context.undetparams = context1.undetparams
context.savedTypeBounds = context1.savedTypeBounds
+ context.namedApplyBlockInfo = context1.namedApplyBlockInfo
result
} else {
op(this)
@@ -737,7 +743,7 @@ trait Typers { self: Analyzer =>
case atp @ AnnotatedType(_, _, _) if canAdaptAnnotations(tree, mode, pt) => // (-1)
adaptAnnotations(tree, mode, pt)
case ct @ ConstantType(value) if ((mode & (TYPEmode | FUNmode)) == 0 && (ct <:< pt)) => // (0)
- copy.Literal(tree, value)
+ treeCopy.Literal(tree, value)
case OverloadedType(pre, alts) if ((mode & FUNmode) == 0) => // (1)
inferExprAlternative(tree, pt)
adapt(tree, mode, pt)
@@ -774,16 +780,39 @@ trait Typers { self: Analyzer =>
case mt: MethodType
if (((mode & (EXPRmode | FUNmode | LHSmode)) == EXPRmode) &&
(context.undetparams.isEmpty || (mode & POLYmode) != 0)) =>
- val meth = tree.symbol
+ // if (isNamedApplyBlock(tree)), we know that `tree' is a transformed
+ // named application and has the following form:
+ // { val x$1 = arg1
+ // [...]
+ // val x$n = argn
+ // fun(x$1, ..)..(.., x$n) }
+ // Eta-Expansion needs to be performed on the method `fun', not on
+ // the entire block, so we extract the fun (`tree1') apply eta-expansion,
+ // and re-construct the block at the end:
+ // { val x$1 = arg1
+ // [...]
+ // val x$n = argn
+ // (y$1, .., y$n) => fun(x$1, ..)..(.., x$n)(y$1, ..)..(.., y$n) }
+ val (tree1, meth, isExpanded) = tree match {
+ case Block(_, tree1) if isNamedApplyBlock(tree) =>
+ context.namedApplyBlockInfo = None
+ (tree1, tree1.symbol, true)
+ case _ => (tree, tree.symbol, false)
+ }
if (!meth.isConstructor &&
//isCompatible(tparamsToWildcards(mt, context.undetparams), pt) &&
isFunctionType(pt))/* &&
(pt <:< functionType(mt.paramTypes map (t => WildcardType), WildcardType)))*/ { // (4.2)
- if (settings.debug.value) log("eta-expanding "+tree+":"+tree.tpe+" to "+pt)
- checkParamsConvertible(tree.pos, tree.tpe)
- val tree1 = etaExpand(context.unit, tree)
-// println("eta "+tree+" ---> "+tree1+":"+tree1.tpe)
- typed(tree1, mode, pt)
+ if (settings.debug.value) log("eta-expanding "+tree1+":"+tree1.tpe+" to "+pt)
+ checkParamsConvertible(tree1.pos, tree1.tpe)
+ val tree2 = etaExpand(context.unit, tree1)
+ //println("eta "+tree1+" ---> "+tree2+":"+tree2.tpe)
+ val typedFun = typed(tree2, mode, pt)
+ tree match {
+ case Block(stats, fun) if (isExpanded) =>
+ treeCopy.Block(tree, stats, typedFun).setType(typedFun.tpe)
+ case _ => typedFun
+ }
} else if (!meth.isConstructor && mt.paramTypes.isEmpty) { // (4.3)
adapt(typed(Apply(tree, List()) setPos tree.pos), mode, pt)
} else if (context.implicitsEnabled) {
@@ -1018,9 +1047,9 @@ trait Typers { self: Analyzer =>
// 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 map (_.duplicate))
+ treeCopy.Apply(scall, transformSuperCall(fn), args map (_.duplicate))
case Select(Super(_, _), nme.CONSTRUCTOR) =>
- copy.Select(
+ treeCopy.Select(
scall,
New(TypeTree(supertpe) setOriginal supertpt) setType supertpe setPos supertpt.pos,
nme.CONSTRUCTOR)
@@ -1033,11 +1062,11 @@ trait Typers { self: Analyzer =>
val scall = if (cstats.isEmpty) EmptyTree else cstats.last
val cbody1 = scall match {
case Apply(_, _) =>
- copy.Block(cbody, cstats1.init,
+ treeCopy.Block(cbody, cstats1.init,
if (supertparams.isEmpty) cunit.duplicate
else transformSuperCall(scall))
case _ =>
- copy.Block(cbody, cstats1, cunit.duplicate)
+ treeCopy.Block(cbody, cstats1, cunit.duplicate)
}
val outercontext = context.outer
@@ -1190,7 +1219,7 @@ trait Typers { self: Analyzer =>
"implementation restriction: subclassing Classfile does not\n"+
"make your annotation visible at runtime. If that is what\n"+
"you want, you must write the annotation class in Java.")
- copy.ClassDef(cdef, typedMods, cdef.name, tparams1, impl2)
+ treeCopy.ClassDef(cdef, typedMods, cdef.name, tparams1, impl2)
.setType(NoType)
}
@@ -1208,7 +1237,7 @@ trait Typers { self: Analyzer =>
.typedTemplate(mdef.impl, parentTypes(mdef.impl))
val impl2 = addSyntheticMethods(impl1, clazz, context)
- copy.ModuleDef(mdef, typedMods, mdef.name, impl2) setType NoType
+ treeCopy.ModuleDef(mdef, typedMods, mdef.name, impl2) setType NoType
}
/**
@@ -1220,7 +1249,7 @@ trait Typers { self: Analyzer =>
if (mods.flags & (PRIVATE | LOCAL)) != (PRIVATE | LOCAL)
&& !stat.symbol.isModuleVar
&& !stat.symbol.hasFlag(LAZY) =>
- val vdef = copy.ValDef(stat, mods | PRIVATE | LOCAL, nme.getterToLocal(name), tpt, rhs)
+ val vdef = treeCopy.ValDef(stat, mods | PRIVATE | LOCAL, nme.getterToLocal(name), tpt, rhs)
val value = vdef.symbol
val getter = if ((mods hasFlag DEFERRED)) value else value.getter(value.owner)
assert(getter != NoSymbol, stat)
@@ -1228,14 +1257,14 @@ trait Typers { self: Analyzer =>
error(getter.pos, getter+" is defined twice")
val getterDef: DefDef = atPos(vdef) {
getter.attributes = value.initialize.attributes
- val result = DefDef(getter, vparamss =>
+ val result = DefDef(getter,
if (mods hasFlag DEFERRED) EmptyTree
else typed(
atPos(vdef) { gen.mkCheckInit(Select(This(value.owner), value)) },
EXPRmode, value.tpe))
result.tpt.asInstanceOf[TypeTree] setOriginal tpt /* setPos tpt.pos */
checkNoEscaping.privates(getter, result.tpt)
- copy.DefDef(result, result.mods withAnnotations mods.annotations, result.name,
+ treeCopy.DefDef(result, result.mods withAnnotations mods.annotations, result.name,
result.tparams, result.vparamss, result.tpt, result.rhs)
//todo: withAnnotations is probably unnecessary
}
@@ -1243,13 +1272,13 @@ trait Typers { self: Analyzer =>
val setr = getter.setter(value.owner)
setr.attributes = value.attributes
val result = atPos(vdef)(
- DefDef(setr, vparamss =>
+ DefDef(setr,
if ((mods hasFlag DEFERRED) || (setr hasFlag OVERLOADED))
EmptyTree
else
typed(Assign(Select(This(value.owner), value),
- Ident(vparamss.head.head)))))
- copy.DefDef(result, result.mods withAnnotations mods.annotations, result.name,
+ Ident(setr.paramss.head.head)))))
+ treeCopy.DefDef(result, result.mods withAnnotations mods.annotations, result.name,
result.tparams, result.vparamss, result.tpt, result.rhs)
}
val gs = if (mods hasFlag MUTABLE) List(getterDef, setterDef)
@@ -1290,7 +1319,7 @@ trait Typers { self: Analyzer =>
val self1 = templ.self match {
case vd @ ValDef(mods, name, tpt, EmptyTree) =>
val tpt1 = checkNoEscaping.privates(clazz.thisSym, typedType(tpt))
- copy.ValDef(vd, mods, name, tpt1, EmptyTree) setType NoType
+ treeCopy.ValDef(vd, mods, name, tpt1, EmptyTree) setType NoType
}
if (self1.name != nme.WILDCARD) context.scope enter self1.symbol
val selfType =
@@ -1310,7 +1339,7 @@ trait Typers { self: Analyzer =>
templ.body flatMap addGetterSetter
else templ.body
val body1 = typedStats(body, templ.symbol)
- copy.Template(templ, parents1, self1, body1) setType clazz.tpe
+ treeCopy.Template(templ, parents1, self1, body1) setType clazz.tpe
}
/** Type check the annotations within a set of modifiers. */
@@ -1338,9 +1367,23 @@ trait Typers { self: Analyzer =>
error(vdef.pos, "local variables must be initialized")
vdef.rhs
} else {
- newTyper(typer1.context.make(vdef, sym)).transformedOrTyped(vdef.rhs, tpt1.tpe)
+ val tpt2 = if (sym hasFlag DEFAULTPARAM) {
+ // When typechecking default parameter, replace all type parameters in the expected type by Wildcarad.
+ // This allows defining "def foo[T](a: T = 1)"
+ val tparams =
+ if (sym.owner.isConstructor) sym.owner.owner.info.typeParams
+ else sym.owner.tpe.typeParams
+ val subst = new SubstTypeMap(tparams, tparams map (_ => WildcardType)) {
+ override def matches(sym: Symbol, sym1: Symbol) =
+ if (sym.isSkolem) matches(sym.deSkolemize, sym1)
+ else if (sym1.isSkolem) matches(sym, sym1.deSkolemize)
+ else super[SubstTypeMap].matches(sym, sym1)
+ }
+ subst(tpt1.tpe)
+ } else tpt1.tpe
+ newTyper(typer1.context.make(vdef, sym)).transformedOrTyped(vdef.rhs, tpt2)
}
- copy.ValDef(vdef, typedMods, vdef.name, tpt1, checkDead(rhs1)) setType NoType
+ treeCopy.ValDef(vdef, typedMods, vdef.name, tpt1, checkDead(rhs1)) setType NoType
}
/** Enter all aliases of local parameter accessors.
@@ -1463,7 +1506,20 @@ trait Typers { self: Analyzer =>
for (vparams <- ddef.vparamss; vparam <- vparams)
checkStructuralCondition(meth.owner, vparam)
- copy.DefDef(ddef, typedMods, ddef.name, tparams1, vparamss1, tpt1, rhs1) setType NoType
+ // only one overloaded method is allowed to have defaults
+ if (meth.owner.isClass && meth.paramss.exists(_.exists(_.hasFlag(DEFAULTPARAM)))) {
+ val overloads = meth.owner.info.member(meth.name)
+ val otherHasDefault = overloads.filter(alt => {
+ alt != meth && alt.paramss.exists(_.exists(_.hasFlag(DEFAULTPARAM)))
+ }) != NoSymbol
+ if (otherHasDefault)
+ error(meth.pos, "multiple overloaded alternatives of "+ meth +" define default arguments")
+
+ if (meth.paramss.exists(_.exists(_.tpe.typeSymbol == RepeatedParamClass)))
+ error(meth.pos, "methods with `*'-parameters are not allowed to have default arguments")
+ }
+
+ treeCopy.DefDef(ddef, typedMods, ddef.name, tparams1, vparamss1, tpt1, rhs1) setType NoType
}
def typedTypeDef(tdef: TypeDef): TypeDef = {
@@ -1479,7 +1535,7 @@ trait Typers { self: Analyzer =>
error(tdef.pos, "lower bound "+lo1+" does not conform to upper bound "+hi1)
case _ =>
}
- copy.TypeDef(tdef, typedMods, tdef.name, tparams1, rhs1) setType NoType
+ treeCopy.TypeDef(tdef, typedMods, tdef.name, tparams1, rhs1) setType NoType
}
private def enterLabelDef(stat: Tree) {
@@ -1496,7 +1552,7 @@ trait Typers { self: Analyzer =>
val restpe = ldef.symbol.tpe.resultType
val rhs1 = typed(ldef.rhs, restpe)
ldef.params foreach (param => param.tpe = param.symbol.tpe)
- copy.LabelDef(ldef, ldef.name, ldef.params, rhs1) setType restpe
+ treeCopy.LabelDef(ldef, ldef.name, ldef.params, rhs1) setType restpe
}
protected def typedFunctionIDE(fun : Function, txt : Context) = {}
@@ -1517,7 +1573,7 @@ trait Typers { self: Analyzer =>
block.stats foreach enterLabelDef
val stats1 = typedStats(block.stats, context.owner)
val expr1 = typed(block.expr, mode & ~(FUNmode | QUALmode), pt)
- val block1 = copy.Block(block, stats1, expr1)
+ val block1 = treeCopy.Block(block, stats1, expr1)
.setType(if (treeInfo.isPureExpr(block)) expr1.tpe else expr1.tpe.deconst)
//checkNoEscaping.locals(context.scope, pt, block1)
block1
@@ -1546,7 +1602,7 @@ trait Typers { self: Analyzer =>
}
}
// body1 = checkNoEscaping.locals(context.scope, pt, body1)
- copy.CaseDef(cdef, pat1, guard1, body1) setType body1.tpe
+ treeCopy.CaseDef(cdef, pat1, guard1, body1) setType body1.tpe
}
def typedCases(tree: Tree, cases: List[CaseDef], pattp0: Type, pt: Type): List[CaseDef] = {
@@ -1636,7 +1692,7 @@ trait Typers { self: Analyzer =>
val restpe = packedType(body, fun.symbol).deconst
val funtpe = typeRef(clazz.tpe.prefix, clazz, formals ::: List(restpe))
// body = checkNoEscaping.locals(context.scope, restpe, body)
- val fun1 = copy.Function(fun, vparams, body).setType(funtpe)
+ val fun1 = treeCopy.Function(fun, vparams, body).setType(funtpe)
if (codeExpected) {
val liftPoint = Apply(Select(Ident(CodeModule), nme.lift_), List(fun1))
typed(atPos(fun.pos)(liftPoint))
@@ -1662,7 +1718,6 @@ trait Typers { self: Analyzer =>
def typedImport(imp : Import) : Import = imp
def typedStats(stats: List[Tree], exprOwner: Symbol): List[Tree] = {
-
val inBlock = exprOwner == context.owner
val localTarget =
context.unit != null &&
@@ -1706,32 +1761,43 @@ trait Typers { self: Analyzer =>
def checkNoDoubleDefsAndAddSynthetics(stats: List[Tree]): List[Tree] = {
val scope = if (inBlock) context.scope else context.owner.info.decls;
val newStats = new ListBuffer[Tree]
- var e = scope.elems;
- while ((e ne null) && e.owner == scope) {
-
- // check no double def
- var e1 = scope.lookupNextEntry(e);
- while ((e1 ne null) && e1.owner == scope) {
- if (!accesses(e.sym, e1.sym) && !accesses(e1.sym, e.sym) &&
- (e.sym.isType || inBlock || (e.sym.tpe matches e1.sym.tpe)))
- if (!e.sym.isErroneous && !e1.sym.isErroneous)
- error(e.sym.pos, e1.sym+" is defined twice"+
- {if(!settings.debug.value) "" else " in "+unit.toString})
- e1 = scope.lookupNextEntry(e1);
- }
+ var needsCheck = true
+ var moreToAdd = true
+ while (moreToAdd) {
+ val initSize = scope.size
+ var e = scope.elems;
+ while ((e ne null) && e.owner == scope) {
+
+ // check no double def
+ if (needsCheck) {
+ var e1 = scope.lookupNextEntry(e);
+ while ((e1 ne null) && e1.owner == scope) {
+ if (!accesses(e.sym, e1.sym) && !accesses(e1.sym, e.sym) &&
+ (e.sym.isType || inBlock || (e.sym.tpe matches e1.sym.tpe)))
+ if (!e.sym.isErroneous && !e1.sym.isErroneous)
+ error(e.sym.pos, e1.sym+" is defined twice"+
+ {if(!settings.debug.value) "" else " in "+unit.toString})
+ e1 = scope.lookupNextEntry(e1);
+ }
+ }
// add synthetics
context.unit.synthetics get e.sym match {
case Some(tree) =>
- newStats += tree
- context.unit.synthetics -= e.sym
+ newStats += typedStat(tree) // might add even more synthetics to the scope
+ context.unit.synthetics -= e.sym
case _ =>
}
e = e.next
}
+ needsCheck = false
+ // the type completer of a synthetic might add more synthetics. example: if the
+ // factory method of a case class (i.e. the constructor) has a default.
+ moreToAdd = initSize != scope.size
+ }
if (newStats.isEmpty) stats
- else stats ::: (newStats.toList map typedStat)
+ else stats ::: newStats.toList
}
val result = List.mapConserve(stats)(typedStat)
if (phase.erasedTypes) result
@@ -1809,6 +1875,15 @@ trait Typers { self: Analyzer =>
}
}
+ /** Is `tree' a block created by a named application?
+ */
+ def isNamedApplyBlock(tree: Tree) =
+ context.namedApplyBlockInfo match {
+ case Some((block, _)) => block == tree
+ case None => false
+ }
+
+
/**
* @param tree ...
* @param fun0 ...
@@ -1820,22 +1895,33 @@ trait Typers { self: Analyzer =>
def doTypedApply(tree: Tree, fun0: Tree, args: List[Tree], mode: Int, pt: Type): Tree = {
var fun = fun0
if (fun.hasSymbol && (fun.symbol hasFlag OVERLOADED)) {
- // preadapt symbol to number and shape of arguments given
- def shapeType(arg: Tree): Type = arg match {
- case Function(vparams, body) =>
- functionType(vparams map (vparam => AnyClass.tpe), shapeType(body))
- case _ =>
- NothingClass.tpe
+ // remove alternatives with wrong number of parameters without looking at types.
+ // less expensive than including them in inferMethodAlternatvie (see below).
+ def shapeType(arg: Tree): Type = {
+ def shape(arg1: Tree, toplevel: Boolean): Type = arg1 match {
+ case Function(vparams, body) =>
+ functionType(vparams map (vparam => AnyClass.tpe), shape(body, false))
+ case Assign(Ident(name), rhs) if toplevel =>
+ NamedType(name, shape(rhs, false))
+ case _ =>
+ NothingClass.tpe
+ }
+ shape(arg, true)
}
val argtypes = args map shapeType
val pre = fun.symbol.tpe.prefix
+
var sym = fun.symbol filter { alt =>
isApplicableSafe(context.undetparams, followApply(pre.memberType(alt)), argtypes, pt)
}
- //println("narrowed to "+sym+":"+sym.info+"/"+argtypes)
if (sym hasFlag OVERLOADED) {
- // eliminate functions that would result from tupling transforms
- val sym1 = sym filter (alt => hasExactlyNumParams(followApply(alt.tpe), argtypes.length))
+ val sym1 = sym filter (alt => {
+ // eliminate functions that would result from tupling transforms
+ // keeps alternatives with repeated params
+ hasExactlyNumParams(followApply(alt.tpe), argtypes.length) ||
+ // also keep alts which define at least one default
+ alt.tpe.paramss.exists(_.exists(_.hasFlag(DEFAULTPARAM)))
+ })
if (sym1 != NoSymbol) sym = sym1
}
if (sym != NoSymbol)
@@ -1845,35 +1931,116 @@ trait Typers { self: Analyzer =>
case OverloadedType(pre, alts) =>
val undetparams = context.extractUndetparams()
- /* Lukas:
-
- var m: Map[Tree, Name] = Map()
- val args1 = List.mapConserve(args) {
- case Assign(name, rhs) => m += (rhs -> name)
- case arg => arg
+ val argtpes = new ListBuffer[Type]
+ val amode = argMode(fun, mode)
+ val args1 = args map {
+ case Assign(Ident(name), rhs) =>
+ // named args: only type the righthand sides ("unknown identifier" errors otherwise)
+ val rhs1 = typedArg(rhs, amode, 0, WildcardType)
+ argtpes += NamedType(name, rhs1.tpe.deconst)
+ Assign(Ident(name), rhs1) // untyped; that's ok because we call doTypedApply
+ case arg =>
+ val arg1 = typedArg(arg, amode, 0, WildcardType)
+ argtpes += arg1.tpe.deconst
+ arg1
}
- */
-
- val args1 = typedArgs(args, argMode(fun, mode))
context.undetparams = undetparams
- inferMethodAlternative(fun, undetparams, args1 map (_.tpe.deconst), pt)
+ inferMethodAlternative(fun, undetparams, argtpes.toList, pt)
doTypedApply(tree, adapt(fun, funMode(mode), WildcardType), args1, mode, pt)
- case mt @ MethodType(formals0, _) =>
- val formals = formalTypes(formals0, args.length)
- var args1 = actualArgs(tree.pos, args, formals.length)
- if (args1.length != args.length) {
- silent(_.doTypedApply(tree, fun, args1, mode, pt)) match {
- case t: Tree => t
- case ex => errorTree(tree, "wrong number of arguments for "+treeSymTypeMsg(fun))
- }
- } else if (formals.length != args1.length) {
+
+ case mt @ MethodType(params, _) =>
+ // repeat vararg as often as needed, remove by-name
+ val formals = formalTypes(mt.paramTypes, args.length)
+
+ /** Try packing all arguments into a Tuple and apply `fun'
+ * to that. This is the last thing which is tried (after
+ * default arguments)
+ */
+ def tryTupleApply: Option[Tree] = {
+ // if 1 formal, 1 arg (a tuple), otherwise unmodified args
+ val tupleArgs = actualArgs(tree.pos, args, formals.length)
+
+ if (tupleArgs.length != args.length) {
+ // expected one argument, but got 0 or >1 ==> try applying to tuple
+ // the inner "doTypedApply" does "extractUndetparams" => restore when it fails
+ val savedUndetparams = context.undetparams
+ silent(_.doTypedApply(tree, fun, tupleArgs, mode, pt)) match {
+ case t: Tree => Some(t)
+ case ex =>
+ context.undetparams = savedUndetparams
+ None
+ }
+ } else None
+ }
+
+ /** Treats an application which uses named or default arguments.
+ * Also works if names + a vararg used: when names are used, the vararg
+ * parameter has to be specified exactly once. Note that combining varargs
+ * and defaults is ruled out by typedDefDef.
+ */
+ def tryNamesDefaults: Tree = {
if (mt.isErroneous) setError(tree)
- else errorTree(tree, "wrong number of arguments for "+treeSymTypeMsg(fun))
+ else if (args.length > formals.length) {
+ tryTupleApply.getOrElse {
+ errorTree(tree, "too many arguments for "+treeSymTypeMsg(fun))
+ }
+ } else if (args.length == formals.length) {
+ // we don't need defaults. names were used, so this application is transformed
+ // into a block (@see transformNamedApplication in NamesDefaults)
+ val (namelessArgs, argPos) = removeNames(Typer.this)(args, params)
+ if (namelessArgs exists (_.isErroneous)) {
+ setError(tree)
+ } else if (!isIdentity(argPos) && (formals.length != params.length))
+ // !isIdentity indicates that named arguments are used to re-order arguments
+ errorTree(tree, "when using named arguments, the vararg parameter "+
+ "has to be specified exactly once")
+ else if (isIdentity(argPos) && !isNamedApplyBlock(fun)) {
+ // if there's no re-ordering, and fun is not transformed, no need to transform
+ // more than an optimization, e.g. important in "synchronized { x = update-x }"
+ doTypedApply(tree, fun, namelessArgs, mode, pt)
+ } else {
+ transformNamedApplication(Typer.this, mode, pt)(
+ treeCopy.Apply(tree, fun, namelessArgs), argPos)
+ }
+ } else {
+ // defaults are needed. they are added to the argument list in named style as
+ // calls to the default getters. Example:
+ // foo[Int](a)() ==> foo[Int](a)(b = foo$qual.foo$default$2[Int](a))
+ val fun1 = transformNamedApplication(Typer.this, mode, pt)(fun, x => x)
+ if (fun1.isErroneous) setError(tree)
+ else {
+ assert(isNamedApplyBlock(fun1), fun1)
+ val NamedApplyInfo(qual, targs, previousArgss, _) =
+ context.namedApplyBlockInfo.get._2
+ val (allArgs, missing) = addDefaults(args, qual, targs, previousArgss, mt.params)
+ if (allArgs.length == formals.length) {
+ // a default for each missing argument was found
+ val (namelessArgs, argPos) = removeNames(Typer.this)(allArgs, params)
+ transformNamedApplication(Typer.this, mode, pt)(
+ treeCopy.Apply(tree, fun1, namelessArgs), argPos)
+ } else {
+ tryTupleApply.getOrElse {
+ val suffix =
+ if (missing.isEmpty) ""
+ else ", unspecified parameter"+ (if (missing.length > 1) "s: " else ": ") +
+ (missing.take(3).mkString(", ")) + (if (missing.length > 3) ", ..." else "")
+ errorTree(tree, "not enough arguments for "+treeSymTypeMsg(fun) + suffix)
+ }
+ }
+ }
+ }
+ }
+
+ if (formals.length != args.length || // wrong nb of arguments
+ args.exists(isNamed(_)) || // uses a named argument
+ isNamedApplyBlock(fun)) { // fun was transformed to a named apply block =>
+ // integrate this application into the block
+ tryNamesDefaults
} else {
val tparams = context.extractUndetparams()
- if (tparams.isEmpty) {
- val args2 = typedArgs(args1, argMode(fun, mode), formals0, formals)
- val restpe = mt.resultType(args2 map (_.tpe))
+ if (tparams.isEmpty) { // all type params are defined
+ val args1 = typedArgs(args, argMode(fun, mode), mt.paramTypes, formals)
+ val restpe = mt.resultType(args1 map (_.tpe)) // instantiate dependent method types
def ifPatternSkipFormals(tp: Type) = tp match {
case MethodType(_, rtp) if ((mode & PATTERNmode) != 0) => rtp
case _ => tp
@@ -1893,7 +2060,7 @@ trait Typers { self: Analyzer =>
// the compiler thinks, the PLUS method takes only one argument,
// but he thinks it's an instance method -> still two ref's on the stack
// -> translated by backend
- val rhs = copy.Apply(tree, f, args1)
+ val rhs = treeCopy.Apply(tree, f, args)
return typed(Assign(qual, rhs))
}
case _ => ()
@@ -1903,20 +2070,20 @@ trait Typers { self: Analyzer =>
if (fun.symbol == List_apply && args.isEmpty) {
atPos(tree.pos) { gen.mkNil setType restpe }
} else {
- constfold(copy.Apply(tree, fun, args2).setType(ifPatternSkipFormals(restpe)))
+ constfold(treeCopy.Apply(tree, fun, args1).setType(ifPatternSkipFormals(restpe)))
}
/* Would like to do the following instead, but curiously this fails; todo: investigate
if (fun.symbol.name == nme.apply && fun.symbol.owner == ListClass && args.isEmpty) {
atPos(tree.pos) { gen.mkNil setType restpe }
} else {
- constfold(copy.Apply(tree, fun, args2).setType(ifPatternSkipFormals(restpe)))
+ constfold(treeCopy.Apply(tree, fun, args1).setType(ifPatternSkipFormals(restpe)))
}
*/
- } else if (needsInstantiation(tparams, formals, args1)) {
+ } else if (needsInstantiation(tparams, formals, args)) {
//println("needs inst "+fun+" "+tparams+"/"+(tparams map (_.info)))
inferExprInstance(fun, tparams, WildcardType, true)
- doTypedApply(tree, fun, args1, mode, pt)
+ doTypedApply(tree, fun, args, mode, pt)
} else {
assert((mode & PATTERNmode) == 0); // this case cannot arise for patterns
val lenientTargs = protoTypeArgs(tparams, formals, mt.resultApprox, pt)
@@ -1932,12 +2099,14 @@ trait Typers { self: Analyzer =>
}
arg1
}
- val args2 = List.map2(args1, formals)(typedArgToPoly)
- if (args2 exists (_.tpe.isError)) setError(tree)
+ val args1 = List.map2(args, formals)(typedArgToPoly)
+ if (args1 exists (_.tpe.isError)) setError(tree)
else {
- if (settings.debug.value) log("infer method inst "+fun+", tparams = "+tparams+", args = "+args2.map(_.tpe)+", pt = "+pt+", lobounds = "+tparams.map(_.tpe.bounds.lo)+", parambounds = "+tparams.map(_.info));//debug
- val undetparams = inferMethodInstance(fun, tparams, args2, pt)
- val result = doTypedApply(tree, fun, args2, mode, pt)
+ if (settings.debug.value) log("infer method inst "+fun+", tparams = "+tparams+", args = "+args1.map(_.tpe)+", pt = "+pt+", lobounds = "+tparams.map(_.tpe.bounds.lo)+", parambounds = "+tparams.map(_.info));//debug
+ // define the undetparams which have been fixed by this param list, replace the corresponding symbols in "fun"
+ // returns those undetparams which have not been instantiated.
+ val undetparams = inferMethodInstance(fun, tparams, args1, pt)
+ val result = doTypedApply(tree, fun, args1, mode, pt)
context.undetparams = undetparams
result
}
@@ -1948,7 +2117,7 @@ trait Typers { self: Analyzer =>
doTypedApply(tree, fun setType fun.tpe.widen, args, mode, pt)
case ErrorType =>
- setError(copy.Apply(tree, fun, args))
+ setError(treeCopy.Apply(tree, fun, args))
/* --- begin unapply --- */
case otpe if (mode & PATTERNmode) != 0 && unapplyMember(otpe).exists =>
@@ -1967,8 +2136,8 @@ trait Typers { self: Analyzer =>
if (!isApplicableSafe(List(), unappType, List(arg.tpe), WildcardType)) {
//Console.println("UNAPP: need to typetest, arg.tpe = "+arg.tpe+", unappType = "+unappType)
def freshArgType(tp: Type): (Type, List[Symbol]) = tp match {
- case MethodType(formals, _) =>
- (formals(0), List())
+ case MethodType(params, _) =>
+ (params(0).tpe, List())
case PolyType(tparams, restype) =>
val tparams1 = cloneSymbols(tparams)
(freshArgType(restype)._1.substSym(tparams, tparams1), tparams1)
@@ -2481,14 +2650,14 @@ trait Typers { self: Analyzer =>
trackSetInfo(vble)(
if (treeInfo.isSequenceValued(body)) seqType(body1.tpe)
else body1.tpe)
- copy.Bind(tree, name, body1) setSymbol vble setType body1.tpe // buraq, was: pt
+ treeCopy.Bind(tree, name, body1) setSymbol vble setType body1.tpe // buraq, was: pt
}
}
def typedArrayValue(elemtpt: Tree, elems: List[Tree]) = {
val elemtpt1 = typedType(elemtpt, mode)
val elems1 = List.mapConserve(elems)(elem => typed(elem, mode, elemtpt1.tpe))
- copy.ArrayValue(tree, elemtpt1, elems1)
+ treeCopy.ArrayValue(tree, elemtpt1, elems1)
.setType(
(if (isFullyDefined(pt) && !phase.erasedTypes) pt
else appliedType(ArrayClass.typeConstructor, List(elemtpt1.tpe))).notNull)
@@ -2516,7 +2685,7 @@ trait Typers { self: Analyzer =>
}
if ((varsym ne null) && (varsym.isVariable || varsym.isValue && phase.erasedTypes)) {
val rhs1 = typed(rhs, lhs1.tpe)
- copy.Assign(tree, lhs1, checkDead(rhs1)) setType UnitClass.tpe
+ treeCopy.Assign(tree, lhs1, checkDead(rhs1)) setType UnitClass.tpe
} else {
if (!lhs1.tpe.isError) {
//println(lhs1+" = "+rhs+" "+varsym+" "+mayBeVarGetter(varsym)+" "+varsym.ownerChain+" "+varsym.info)// DEBUG
@@ -2532,11 +2701,11 @@ trait Typers { self: Analyzer =>
val cond1 = checkDead(typed(cond, BooleanClass.tpe))
if (elsep.isEmpty) { // in the future, should be unecessary
val thenp1 = typed(thenp, UnitClass.tpe)
- copy.If(tree, cond1, thenp1, elsep) setType thenp1.tpe
+ treeCopy.If(tree, cond1, thenp1, elsep) setType thenp1.tpe
} else {
val thenp1 = typed(thenp, pt)
val elsep1 = typed(elsep, pt)
- copy.If(tree, cond1, thenp1, elsep1) setType ptOrLub(List(thenp1.tpe, elsep1.tpe))
+ treeCopy.If(tree, cond1, thenp1, elsep1) setType ptOrLub(List(thenp1.tpe, elsep1.tpe))
}
}
@@ -2556,7 +2725,7 @@ trait Typers { self: Analyzer =>
} else {
context.enclMethod.returnsSeen = true
val expr1: Tree = typed(expr, restpt0.tpe)
- copy.Return(tree, checkDead(expr1)) setSymbol enclMethod.owner setType NothingClass.tpe
+ treeCopy.Return(tree, checkDead(expr1)) setSymbol enclMethod.owner setType NothingClass.tpe
}
}
}
@@ -2594,7 +2763,7 @@ trait Typers { self: Analyzer =>
" cannot be instantiated because it does not conform to its self-type "+
tpt1.tpe.typeOfThis)
}
- copy.New(tree, tpt1).setType(tpt1.tpe)
+ treeCopy.New(tree, tpt1).setType(tpt1.tpe)
}
def typedEta(expr1: Tree): Tree = expr1.tpe match {
@@ -2673,7 +2842,7 @@ trait Typers { self: Analyzer =>
// this must preserve m's type argument, so that we end up with List[Int], and not List[a]
//@M related bug: #1438
//println("instantiating type params "+restpe+" "+tparams+" "+targs+" = "+resultpe)
- copy.TypeApply(tree, fun, args) setType resultpe
+ treeCopy.TypeApply(tree, fun, args) setType resultpe
}
} else {
errorTree(tree, "wrong number of type parameters for "+treeSymTypeMsg(fun))
@@ -2732,7 +2901,8 @@ trait Typers { self: Analyzer =>
if ((args1 ne null) && !pt.isError) {
def templateArgType(arg: Tree) =
new BoundedWildcardType(mkTypeBounds(arg.tpe, AnyClass.tpe))
- adaptToMember(qual, name, MethodType(args1 map templateArgType, pt))
+ val dummyMethod = new TermSymbol(NoSymbol, NoPosition, "typer$dummy")
+ adaptToMember(qual, name, MethodType(dummyMethod.newSyntheticValueParams(args1 map templateArgType), pt))
} else qual
if (qual1 ne qual) {
val tree1 = Apply(Select(qual1, name) setPos fun.pos, args1) setPos tree.pos
@@ -2932,7 +3102,7 @@ trait Typers { self: Analyzer =>
}
if (sym == NoSymbol && name != nme.CONSTRUCTOR && (mode & EXPRmode) != 0) {
val qual1 = adaptToName(qual, name)
- if (qual1 ne qual) return typed(copy.Select(tree, qual1, name), mode, pt)
+ if (qual1 ne qual) return typed(treeCopy.Select(tree, qual1, name), mode, pt)
}
if (!sym.exists) {
if (settings.debug.value) Console.err.println("qual = "+qual+":"+qual.tpe+"\nSymbol="+qual.tpe.termSymbol+"\nsymbol-info = "+qual.tpe.termSymbol.info+"\nscope-id = "+qual.tpe.termSymbol.info.decls.hashCode()+"\nmembers = "+qual.tpe.members+"\nname = "+name+"\nfound = "+sym+"\nowner = "+context.enclClass.owner)
@@ -2950,8 +3120,8 @@ trait Typers { self: Analyzer =>
setError(tree)
} else {
val tree1 = tree match {
- case Select(_, _) => copy.Select(tree, qual, name)
- case SelectFromTypeTree(_, _) => copy.SelectFromTypeTree(tree, qual, name)
+ case Select(_, _) => treeCopy.Select(tree, qual, name)
+ case SelectFromTypeTree(_, _) => treeCopy.SelectFromTypeTree(tree, qual, name)
}
//if (name.toString == "Elem") println("typedSelect "+qual+":"+qual.tpe+" "+sym+"/"+tree1+":"+tree1.tpe)
val (tree2, pre2) = makeAccessible(tree1, sym, qual.tpe, qual)
@@ -3187,7 +3357,7 @@ trait Typers { self: Analyzer =>
assert(sym.moduleClass ne NoSymbol)
val stats1 = newTyper(context.make(tree, sym.moduleClass, sym.info.decls))
.typedStats(stats, NoSymbol)
- copy.PackageDef(tree, name, stats1) setType NoType
+ treeCopy.PackageDef(tree, name, stats1) setType NoType
case tree @ ClassDef(_, _, _, _) =>
newTyper(context.makeNewScope(tree, sym)).typedClassDef(tree)
@@ -3215,7 +3385,7 @@ trait Typers { self: Analyzer =>
case Annotation(constr, elements) =>
val typedConstr = typed(constr, mode, WildcardType)
val typedElems = elements.map(typed(_, mode, WildcardType))
- (copy.Annotation(tree, typedConstr, typedElems)
+ (treeCopy.Annotation(tree, typedConstr, typedElems)
setType typedConstr.tpe)
case Annotated(annot, arg) =>
@@ -3228,16 +3398,16 @@ trait Typers { self: Analyzer =>
case Sequence(elems) =>
checkRegPatOK(tree.pos, mode)
val elems1 = List.mapConserve(elems)(elem => typed(elem, mode, pt))
- copy.Sequence(tree, elems1) setType pt
+ treeCopy.Sequence(tree, elems1) setType pt
case Alternative(alts) =>
val alts1 = List.mapConserve(alts)(alt => typed(alt, mode | ALTmode, pt))
- copy.Alternative(tree, alts1) setType pt
+ treeCopy.Alternative(tree, alts1) setType pt
case Star(elem) =>
checkRegPatOK(tree.pos, mode)
val elem1 = typed(elem, mode, pt)
- copy.Star(tree, elem1) setType pt
+ treeCopy.Star(tree, elem1) setType pt
case Bind(name, body) =>
typedBind(name, body)
@@ -3246,7 +3416,7 @@ trait Typers { self: Analyzer =>
val fun1 = typed(fun)
val tpes = formalTypes(unapplyTypeList(fun.symbol, fun1.tpe), args.length)
val args1 = List.map2(args, tpes)(typedPattern(_, _))
- copy.UnApply(tree, fun1, args1) setType pt
+ treeCopy.UnApply(tree, fun1, args1) setType pt
case ArrayValue(elemtpt, elems) =>
typedArrayValue(elemtpt, elems)
@@ -3273,12 +3443,12 @@ trait Typers { self: Analyzer =>
}
val ids = for (p <- params) yield Ident(p.name)
val selector1 = atPos(tree.pos.focusStart) { if (arity == 1) ids.head else gen.mkTuple(ids) }
- val body = copy.Match(tree, selector1, cases)
+ val body = treeCopy.Match(tree, selector1, cases)
typed1(atPos(tree.pos) { Function(params, body) }, mode, pt)
} else {
val selector1 = checkDead(typed(selector))
val cases1 = typedCases(tree, cases, selector1.tpe.widen, pt)
- copy.Match(tree, selector1, cases1) setType ptOrLub(cases1 map (_.tpe))
+ treeCopy.Match(tree, selector1, cases1) setType ptOrLub(cases1 map (_.tpe))
}
case Return(expr) =>
@@ -3289,12 +3459,12 @@ trait Typers { self: Analyzer =>
val catches1 = typedCases(tree, catches, ThrowableClass.tpe, pt)
val finalizer1 = if (finalizer.isEmpty) finalizer
else typed(finalizer, UnitClass.tpe)
- copy.Try(tree, block1, catches1, finalizer1)
+ treeCopy.Try(tree, block1, catches1, finalizer1)
.setType(ptOrLub(block1.tpe :: (catches1 map (_.tpe))))
case Throw(expr) =>
val expr1 = typed(expr, ThrowableClass.tpe)
- copy.Throw(tree, expr1) setType NothingClass.tpe
+ treeCopy.Throw(tree, expr1) setType NothingClass.tpe
case New(tpt: Tree) =>
typedNew(tpt)
@@ -3307,7 +3477,7 @@ trait Typers { self: Analyzer =>
val expr1 = typed(expr, mode & stickyModes, seqType(pt))
expr1.tpe.baseType(SeqClass) match {
case TypeRef(_, _, List(elemtp)) =>
- copy.Typed(tree, expr1, tpt setType elemtp) setType elemtp
+ treeCopy.Typed(tree, expr1, tpt setType elemtp) setType elemtp
case _ =>
setError(tree)
}
@@ -3318,7 +3488,7 @@ trait Typers { self: Analyzer =>
if ((mode & PATTERNmode) != 0) inferTypedPattern(tpt1.pos, tpt1.tpe, pt)
else tpt1.tpe
//Console.println(typed pattern: "+tree+":"+", tp = "+tpt1.tpe+", pt = "+pt+" ==> "+owntype)//DEBUG
- copy.Typed(tree, expr1, tpt1) setType owntype
+ treeCopy.Typed(tree, expr1, tpt1) setType owntype
}
case TypeApply(fun, args) =>
@@ -3367,7 +3537,7 @@ trait Typers { self: Analyzer =>
val reflectiveCalls = !(settings.refinementMethodDispatch.value == "invoke-dynamic")
val qual1 = typed(qual, AnyRefClass.tpe)
val args1 = List.mapConserve(args)(arg => if (reflectiveCalls) typed(arg, AnyRefClass.tpe) else typed(arg))
- copy.ApplyDynamic(tree, qual1, args1) setType (if (reflectiveCalls) AnyRefClass.tpe else tree.symbol.info.resultType)
+ treeCopy.ApplyDynamic(tree, qual1, args1) setType (if (reflectiveCalls) AnyRefClass.tpe else tree.symbol.info.resultType)
case Super(qual, mix) =>
typedSuper(qual, mix)
@@ -3386,7 +3556,7 @@ trait Typers { self: Analyzer =>
var qual1 = checkDead(typedQualifier(qual, mode))
if (name.isTypeName) qual1 = checkStable(qual1)
val tree1 = typedSelect(qual1, name)
- if (qual1.symbol == RootPackage) copy.Ident(tree1, name)
+ if (qual1.symbol == RootPackage) treeCopy.Ident(tree1, name)
else tree1
case Ident(name) =>
@@ -3421,7 +3591,7 @@ trait Typers { self: Analyzer =>
case TypeBoundsTree(lo, hi) =>
val lo1 = typedType(lo, mode)
val hi1 = typedType(hi, mode)
- copy.TypeBoundsTree(tree, lo1, hi1) setType mkTypeBounds(lo1.tpe, hi1.tpe)
+ treeCopy.TypeBoundsTree(tree, lo1, hi1) setType mkTypeBounds(lo1.tpe, hi1.tpe)
case etpt @ ExistentialTypeTree(_, _) =>
newTyper(context.makeNewScope(tree, context.owner)).typedExistentialTypeTree(etpt, mode)
@@ -3448,7 +3618,6 @@ trait Typers { self: Analyzer =>
* @return ...
*/
def typed(tree: Tree, mode: Int, pt: Type): Tree = {
-
def dropExistential(tp: Type): Type = tp match {
case ExistentialType(tparams, tpe) =>
if (settings.debug.value) println("drop ex "+tree+" "+tp)
diff --git a/src/compiler/scala/tools/nsc/typechecker/Unapplies.scala b/src/compiler/scala/tools/nsc/typechecker/Unapplies.scala
index 4f4c39a0c0..0bb1f87ed4 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Unapplies.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Unapplies.scala
@@ -94,12 +94,19 @@ trait Unapplies { self: Analyzer =>
unapp
}
- private def copyUntyped[T <: Tree](tree: T): T = {
+ def copyUntyped[T <: Tree](tree: T): T = {
val tree1 = tree.duplicate
UnTyper.traverse(tree1)
tree1
}
+ def copyUntypedInvariant(td: TypeDef): TypeDef = {
+ val tree1 = treeCopy.TypeDef(td, td.mods &~ (COVARIANT | CONTRAVARIANT),
+ td.name, td.tparams map (_.duplicate), td.rhs.duplicate)
+ UnTyper.traverse(tree1)
+ tree1
+ }
+
private def classType(cdef: ClassDef, tparams: List[TypeDef]): Tree = {
val tycon = gen.mkAttributedRef(cdef.symbol)
if (tparams.isEmpty) tycon else AppliedTypeTree(tycon, tparams map (x => Ident(x.name)))
@@ -151,7 +158,7 @@ trait Unapplies { self: Analyzer =>
/** The apply method corresponding to a case class
*/
def caseModuleApplyMeth(cdef: ClassDef): DefDef = {
- val tparams = cdef.tparams map copyUntyped[TypeDef]
+ val tparams = cdef.tparams map copyUntypedInvariant
val cparamss = constrParamss(cdef)
atPos(cdef.pos) {
DefDef(
@@ -167,7 +174,7 @@ trait Unapplies { self: Analyzer =>
/** The unapply method corresponding to a case class
*/
def caseModuleUnapplyMeth(cdef: ClassDef): DefDef = {
- val tparams = cdef.tparams map copyUntyped[TypeDef]
+ val tparams = cdef.tparams map copyUntypedInvariant
val unapplyParamName = newTermName("x$0")
val hasVarArg = constrParamss(cdef) match {
case (cps @ (_ :: _)) :: _ => treeInfo.isRepeatedParamType(cps.last.tpt)
@@ -184,4 +191,28 @@ trait Unapplies { self: Analyzer =>
caseClassUnapplyReturnValue(unapplyParamName, cdef.symbol))
}
}
+
+ def caseClassCopyMeth(cdef: ClassDef): Option[DefDef] = {
+ val cparamss = constrParamss(cdef)
+ if (cparamss.length == 1 && cparamss.head.isEmpty || // no copy method if there are no arguments
+ cdef.symbol.hasFlag(ABSTRACT) ||
+ cparamss.exists(_.exists(vd =>
+ treeInfo.isRepeatedParamType(vd.tpt) ||
+ treeInfo.isByNameParamType(vd.tpt))))
+ None
+ else {
+ val tparams = cdef.tparams map copyUntypedInvariant
+ // the parameter types have to be exactly the same as the constructor's parameter types; so it's
+ // not good enough to just duplicated the (untyped) tpt tree; the parameter types are removed here
+ // and re-added in ``finishWith'' in the namer.
+ val paramss = cparamss map (_.map(vd =>
+ treeCopy.ValDef(vd, vd.mods | DEFAULTPARAM, vd.name,
+ TypeTree().setOriginal(vd.tpt), Ident(vd.name))))
+ val classTpe = classType(cdef, tparams)
+ Some(atPos(cdef.pos) {
+ DefDef(Modifiers(SYNTHETIC), nme.copy, tparams, paramss, classTpe,
+ New(classTpe, paramss map (_ map (p => Ident(p.name)))))
+ })
+ }
+ }
}
diff --git a/src/compiler/scala/tools/nsc/typechecker/Variances.scala b/src/compiler/scala/tools/nsc/typechecker/Variances.scala
index a02b4b04a1..920b856094 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Variances.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Variances.scala
@@ -87,8 +87,8 @@ trait Variances {
flip(varianceInType(lo)(tparam)) & varianceInType(hi)(tparam)
case RefinedType(parents, defs) =>
varianceInTypes(parents)(tparam) & varianceInSyms(defs.toList)(tparam)
- case MethodType(formals, restpe) =>
- flip(varianceInTypes(formals)(tparam)) & varianceInType(restpe)(tparam)
+ case MethodType(params, restpe) =>
+ flip(varianceInSyms(params)(tparam)) & varianceInType(restpe)(tparam)
case PolyType(tparams, restpe) =>
flip(varianceInSyms(tparams)(tparam)) & varianceInType(restpe)(tparam)
case ExistentialType(tparams, restpe) =>
diff --git a/src/library/scala/reflect/Type.scala b/src/library/scala/reflect/Type.scala
index 279a6f1695..3ce496f32d 100644
--- a/src/library/scala/reflect/Type.scala
+++ b/src/library/scala/reflect/Type.scala
@@ -48,7 +48,7 @@ case class TypeBounds(lo: Type, hi: Type) extends Type
/** This type is required by the compiler and <b>should not be used in client code</b>.
* <code>(formals1 ... formalsn) restpe</code> */
-case class MethodType(formals: List[Type], restpe: Type) extends Type
+case class MethodType(formals: List[Symbol], restpe: Type) extends Type
/** This type is required by the compiler and <b>should not be used in client code</b>. */
@@ -56,7 +56,7 @@ case class PolyType(typeParams: List[Symbol], typeBounds: List[(Type, Type)], re
/** This type is required by the compiler and <b>should not be used in client code</b>. */
-class ImplicitMethodType(formals: List[Type], restpe: Type)
+class ImplicitMethodType(formals: List[Symbol], restpe: Type)
extends MethodType(formals, restpe)
diff --git a/src/library/scala/xml/NodeSeq.scala b/src/library/scala/xml/NodeSeq.scala
index 13e0566893..28d05f885b 100644
--- a/src/library/scala/xml/NodeSeq.scala
+++ b/src/library/scala/xml/NodeSeq.scala
@@ -51,7 +51,7 @@ abstract class NodeSeq extends immutable.Sequence[Node] with SequenceTemplate[No
def apply(f: Node => Boolean): NodeSeq = filter(f)
/** structural equality */
- override def equals(x: Any) = x match {
+ override def equals(x: Any): Boolean = x match {
case z:Node => (length == 1) && z == apply(0)
case z:Seq[_] => sameElements(z)
case z:String => text == z