diff options
author | Martin Odersky <odersky@gmail.com> | 2011-03-14 11:43:13 +0000 |
---|---|---|
committer | Martin Odersky <odersky@gmail.com> | 2011-03-14 11:43:13 +0000 |
commit | 13c59adf9fbff0e99ffa9f8e30f5dc05e0c1ee4d (patch) | |
tree | 17de4b40b057cf9ac6cc11e42a652a711928e9ae /src/compiler/scala | |
parent | 1f3c58a818feb7c2887ceebb079ce992aa677c0d (diff) | |
download | scala-13c59adf9fbff0e99ffa9f8e30f5dc05e0c1ee4d.tar.gz scala-13c59adf9fbff0e99ffa9f8e30f5dc05e0c1ee4d.tar.bz2 scala-13c59adf9fbff0e99ffa9f8e30f5dc05e0c1ee4d.zip |
Changed Super to fix #4300
Diffstat (limited to 'src/compiler/scala')
14 files changed, 94 insertions, 67 deletions
diff --git a/src/compiler/scala/tools/nsc/ast/NodePrinters.scala b/src/compiler/scala/tools/nsc/ast/NodePrinters.scala index 72d1895796..ca4ccd4f35 100644 --- a/src/compiler/scala/tools/nsc/ast/NodePrinters.scala +++ b/src/compiler/scala/tools/nsc/ast/NodePrinters.scala @@ -196,7 +196,8 @@ abstract class NodePrinters { traverse(qualifier, level + 1, true) printcln(" \"" + selector + "\")") case Super(qual, mix) => - printcln("Super(\"" + qual + "\", \"" + mix + "\")" + nodeinfo2(tree)) + println("Super(\"" + mix + "\")" + nodeinfo(tree)) + traverse(qual, level + 1, true) case Template(parents, self, body) => println("Template(" + nodeinfo(tree)) println(" " + parents.map(p => diff --git a/src/compiler/scala/tools/nsc/ast/TreeBrowsers.scala b/src/compiler/scala/tools/nsc/ast/TreeBrowsers.scala index 2e51f03f4c..8fd0017b81 100644 --- a/src/compiler/scala/tools/nsc/ast/TreeBrowsers.scala +++ b/src/compiler/scala/tools/nsc/ast/TreeBrowsers.scala @@ -345,7 +345,7 @@ abstract class TreeBrowsers { ("Apply", EMPTY) case Super(qualif, mix) => - ("Super", qualif.toString() + ", mix: " + mix.toString()) + ("Super", "mix: " + mix.toString()) case This(qualifier) => ("This", qualifier) @@ -486,7 +486,7 @@ abstract class TreeBrowsers { List(qual) ::: args case Super(qualif, mix) => - Nil + List(qualif) case This(qualif) => Nil diff --git a/src/compiler/scala/tools/nsc/ast/TreePrinters.scala b/src/compiler/scala/tools/nsc/ast/TreePrinters.scala index 033034451b..b8c3e12ee6 100644 --- a/src/compiler/scala/tools/nsc/ast/TreePrinters.scala +++ b/src/compiler/scala/tools/nsc/ast/TreePrinters.scala @@ -341,12 +341,18 @@ trait TreePrinters { trees: SymbolTable => print("<apply-dynamic>("); print(qual); print("#"); print(tree.symbol.nameString) printRow(vargs, ", (", ", ", "))") - case Super(qual, mix) => + case Super(This(qual), mix) => if (!qual.isEmpty || tree.symbol != NoSymbol) print(symName(tree, qual) + ".") print("super") if (!mix.isEmpty) print("[" + mix + "]") + case Super(qual, mix) => + print(qual) + print(".super") + if (!mix.isEmpty) + print("[" + mix + "]") + case This(qual) => if (!qual.isEmpty) print(symName(tree, qual) + ".") print("this") diff --git a/src/compiler/scala/tools/nsc/ast/Trees.scala b/src/compiler/scala/tools/nsc/ast/Trees.scala index f7c56db113..cf612ad7a0 100644 --- a/src/compiler/scala/tools/nsc/ast/Trees.scala +++ b/src/compiler/scala/tools/nsc/ast/Trees.scala @@ -256,7 +256,7 @@ trait Trees extends reflect.generic.Trees { self: SymbolTable => if (vparamss1.isEmpty || !vparamss1.head.isEmpty && vparamss1.head.head.mods.isImplicit) vparamss1 = List() :: vparamss1; val superRef: Tree = atPos(superPos) { - Select(Super(tpnme.EMPTY, tpnme.EMPTY), nme.CONSTRUCTOR) + Select(Super(This(tpnme.EMPTY), tpnme.EMPTY), nme.CONSTRUCTOR) } val superCall = (superRef /: argss) (Apply) List( @@ -289,7 +289,7 @@ trait Trees extends reflect.generic.Trees { self: SymbolTable => (superRef /: argss) (Apply) } - def Super(sym: Symbol, mix: Name): Tree = Super(sym.name.toTypeName, mix.toTypeName) setSymbol sym + def Super(sym: Symbol, mix: TypeName): Tree = Super(This(sym), mix) def This(sym: Symbol): Tree = This(sym.name.toTypeName) setSymbol sym @@ -388,7 +388,7 @@ trait Trees extends reflect.generic.Trees { self: SymbolTable => def TypeApply(tree: Tree, fun: Tree, args: List[Tree]): TypeApply def Apply(tree: Tree, fun: Tree, args: List[Tree]): Apply def ApplyDynamic(tree: Tree, qual: Tree, args: List[Tree]): ApplyDynamic - def Super(tree: Tree, qual: Name, mix: Name): Super + def Super(tree: Tree, qual: Tree, mix: TypeName): Super def This(tree: Tree, qual: Name): This def Select(tree: Tree, qualifier: Tree, selector: Name): Select def Ident(tree: Tree, name: Name): Ident @@ -470,8 +470,8 @@ trait Trees extends reflect.generic.Trees { self: SymbolTable => }).copyAttrs(tree) def ApplyDynamic(tree: Tree, qual: Tree, args: List[Tree]) = new ApplyDynamic(qual, args).copyAttrs(tree) - def Super(tree: Tree, qual: Name, mix: Name) = - new Super(qual.toTypeName, mix.toTypeName).copyAttrs(tree) + def Super(tree: Tree, qual: Tree, mix: TypeName) = + new Super(qual, mix).copyAttrs(tree) def This(tree: Tree, qual: Name) = new This(qual.toTypeName).copyAttrs(tree) def Select(tree: Tree, qualifier: Tree, selector: Name) = @@ -656,7 +656,7 @@ trait Trees extends reflect.generic.Trees { self: SymbolTable => if (qual0 == qual) && (args0 == args) => t case _ => treeCopy.ApplyDynamic(tree, qual, args) } - def Super(tree: Tree, qual: Name, mix: Name) = tree match { + def Super(tree: Tree, qual: Tree, mix: TypeName) = tree match { case t @ Super(qual0, mix0) if (qual0 == qual) && (mix0 == mix) => t case _ => treeCopy.Super(tree, qual, mix) @@ -824,7 +824,7 @@ trait Trees extends reflect.generic.Trees { self: SymbolTable => case ApplyDynamic(qual, args) => treeCopy.ApplyDynamic(tree, transform(qual), transformTrees(args)) case Super(qual, mix) => - treeCopy.Super(tree, qual, mix) + treeCopy.Super(tree, transform(qual), mix) case This(qual) => treeCopy.This(tree, qual) case Select(qualifier, selector) => @@ -901,6 +901,8 @@ trait Trees extends reflect.generic.Trees { self: SymbolTable => traverseTrees(ts) case TypeTreeWithDeferredRefCheck() => // TODO: should we traverse the wrapped tree? // (and rewrap the result? how to update the deferred check? would need to store wrapped tree instead of returning it from check) + case Super(qual, _) => + traverse(qual) // !!! remove when Super is done case _ => super.traverse(tree) } diff --git a/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala b/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala index ed92afe5de..cc515d957a 100644 --- a/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala +++ b/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala @@ -376,7 +376,7 @@ self => Nil, List(Nil), TypeTree(), - Block(List(Apply(Select(Super(tpnme.EMPTY, tpnme.EMPTY), nme.CONSTRUCTOR), Nil)), Literal(Constant(()))) + Block(List(Apply(Select(Super(This(tpnme.EMPTY), tpnme.EMPTY), nme.CONSTRUCTOR), Nil)), Literal(Constant(()))) ) // def main @@ -995,7 +995,7 @@ self => } } else if (in.token == SUPER) { in.nextToken() - t = atPos(start) { Super(tpnme.EMPTY, mixinQualifierOpt()) } + t = atPos(start) { Super(This(tpnme.EMPTY), mixinQualifierOpt()) } accept(DOT) t = selector(t) if (in.token == DOT) t = selectors(t, typeOK, in.skipToken()) @@ -1015,7 +1015,7 @@ self => t = selectors(t, typeOK, accept(DOT)) } else if (in.token == SUPER) { in.nextToken() - t = atPos(start) { Super(name.toTypeName, mixinQualifierOpt()) } + t = atPos(start) { Super(This(name.toTypeName), mixinQualifierOpt()) } accept(DOT) t = selector(t) if (in.token == DOT) t = selectors(t, typeOK, in.skipToken()) diff --git a/src/compiler/scala/tools/nsc/interactive/Global.scala b/src/compiler/scala/tools/nsc/interactive/Global.scala index 11ad5d9ce3..3fad69821f 100644 --- a/src/compiler/scala/tools/nsc/interactive/Global.scala +++ b/src/compiler/scala/tools/nsc/interactive/Global.scala @@ -629,7 +629,7 @@ class Global(settings: Settings, reporter: Reporter) val newsym = pre.decl(sym.name) filter { alt => sym.isType || { try { - val tp1 = pre.memberType(alt) onTypeError NoType + val tp1 = adaptToNewRunMap(pre.memberType(alt) onTypeError NoType) val tp2 = adaptToNewRunMap(sym.tpe) matchesType(tp1, tp2, false) } catch { @@ -645,6 +645,7 @@ class Global(settings: Settings, reporter: Reporter) debugLog("link not found "+sym+" "+source+" "+pre) NoPosition } else if (newsym.isOverloaded) { + settings.uniqid.value = true debugLog("link ambiguous "+sym+" "+source+" "+pre+" "+newsym.alternatives) NoPosition } else { diff --git a/src/compiler/scala/tools/nsc/symtab/classfile/Pickler.scala b/src/compiler/scala/tools/nsc/symtab/classfile/Pickler.scala index 8f560b772f..b57f89c020 100644 --- a/src/compiler/scala/tools/nsc/symtab/classfile/Pickler.scala +++ b/src/compiler/scala/tools/nsc/symtab/classfile/Pickler.scala @@ -358,7 +358,7 @@ abstract class Pickler extends SubComponent { putTrees(args) case Super(qual, mix) => - putEntry(qual:Name) + putTree(qual) putEntry(mix:Name) case This(qual) => diff --git a/src/compiler/scala/tools/nsc/transform/Mixin.scala b/src/compiler/scala/tools/nsc/transform/Mixin.scala index 01f90ec236..48742f4fcd 100644 --- a/src/compiler/scala/tools/nsc/transform/Mixin.scala +++ b/src/compiler/scala/tools/nsc/transform/Mixin.scala @@ -548,11 +548,25 @@ abstract class Mixin extends InfoTransform with ast.TreeDSL { /** Replace a super reference by this or the self parameter, depending * on whether we are in an implementation class or not. - * Leave all other trees unchanged */ - private def transformSuper(qual: Tree) = - if (!qual.isInstanceOf[Super]) qual - else if (currentOwner.enclClass.isImplClass) selfRef(qual.pos) - else gen.mkAttributedThis(currentOwner.enclClass) + * Leave all other trees unchanged. + */ + private def transformSuper(tree: Tree) = tree match { + case Super(qual, _) => + transformThis(qual) + case _ => + tree + } + + /** Replace a this reference to the current implementation class by the self + * parameter. Leave all other trees unchanged. + */ + private def transformThis(tree: Tree) = tree match { + case This(_) if tree.symbol.isImplClass => + assert(tree.symbol == currentOwner.enclClass) + selfRef(tree.pos) + case _ => + tree + } /** Create a static reference to given symbol <code>sym</code> of the * form <code>M.sym</code> where M is the symbol's implementation module. @@ -1178,10 +1192,8 @@ abstract class Mixin extends InfoTransform with ast.TreeDSL { tree } - case This(_) if tree.symbol.isImplClass => - // change `this' in implementation modules to references to the self parameter - assert(tree.symbol == currentOwner.enclClass) - selfRef(tree.pos) + case This(_) => + transformThis(tree) case Select(Super(_, _), name) => tree diff --git a/src/compiler/scala/tools/nsc/transform/Reifiers.scala b/src/compiler/scala/tools/nsc/transform/Reifiers.scala index e0ee4d3af8..6b0d441ad9 100644 --- a/src/compiler/scala/tools/nsc/transform/Reifiers.scala +++ b/src/compiler/scala/tools/nsc/transform/Reifiers.scala @@ -305,7 +305,7 @@ trait Reifiers { val rrhs = reify(rhs) reflect.DefDef(rsym, rparss, rret, rrhs) - case sp @ Super(qual: Name, mix: Name) => + case sp @ Super(qual, mix) => val rsym = reify(sp.symbol) reflect.Super(rsym) diff --git a/src/compiler/scala/tools/nsc/transform/SpecializeTypes.scala b/src/compiler/scala/tools/nsc/transform/SpecializeTypes.scala index 6673560b89..42ccae9a76 100644 --- a/src/compiler/scala/tools/nsc/transform/SpecializeTypes.scala +++ b/src/compiler/scala/tools/nsc/transform/SpecializeTypes.scala @@ -1396,7 +1396,7 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers { if (symbol.isConstructor) { val t = atOwner(symbol) { - val superRef: Tree = Select(Super(tpnme.EMPTY, tpnme.EMPTY), nme.CONSTRUCTOR) + val superRef: Tree = Select(Super(This(tpnme.EMPTY), tpnme.EMPTY), nme.CONSTRUCTOR) forwardCtorCall(tree.pos, superRef, vparamss, symbol.owner) } if (symbol.isPrimaryConstructor) localTyper typed { diff --git a/src/compiler/scala/tools/nsc/typechecker/Duplicators.scala b/src/compiler/scala/tools/nsc/typechecker/Duplicators.scala index cb03c61b50..286310cad0 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Duplicators.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Duplicators.scala @@ -276,12 +276,12 @@ abstract class Duplicators extends Analyzer { val tree1 = super.typed(tree, mode, pt) // log("plain this typed to: " + tree1) tree1 - +/* no longer needed, because Super now contains a This(...) case Super(qual, mix) if (oldClassOwner ne null) && (tree.symbol == oldClassOwner) => val tree1 = Super(qual, mix) log("changed " + tree + " to " + tree1) super.typed(atPos(tree.pos)(tree1)) - +*/ case Match(scrut, cases) => val scrut1 = typed(scrut, EXPRmode | BYVALmode, WildcardType) val scrutTpe = scrut1.tpe.widen diff --git a/src/compiler/scala/tools/nsc/typechecker/Namers.scala b/src/compiler/scala/tools/nsc/typechecker/Namers.scala index b578759c85..cd845ab9e5 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Namers.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Namers.scala @@ -757,7 +757,7 @@ trait Namers { self: Analyzer => // add apply and unapply methods to companion objects of case classes, // unless they exist already; here, "clazz" is the module class if (clazz.isModuleClass) { - Namers.this.caseClassOfModuleClass get clazz map { cdefRef => + Namers.this.caseClassOfModuleClass get clazz foreach { cdefRef => val cdef = cdefRef() addApplyUnapply(cdef, templateNamer) caseClassOfModuleClass -= clazz diff --git a/src/compiler/scala/tools/nsc/typechecker/SuperAccessors.scala b/src/compiler/scala/tools/nsc/typechecker/SuperAccessors.scala index 929eb0c4f3..83d72fc3a0 100644 --- a/src/compiler/scala/tools/nsc/typechecker/SuperAccessors.scala +++ b/src/compiler/scala/tools/nsc/typechecker/SuperAccessors.scala @@ -190,10 +190,12 @@ abstract class SuperAccessors extends transform.Transform with transform.TypingT mayNeedProtectedAccessor(sel, args, false) case sel @ Select(qual @ This(_), name) => + // direct calls to aliases of param accessors to the superclass in order to avoid + // duplicating fields. if (sym.isParamAccessor && sym.alias != NoSymbol) { val result = localTyper.typed { Select( - Super(qual.symbol, tpnme.EMPTY/*qual.symbol.info.parents.head.symbol.name*/) setPos qual.pos, + Super(qual, tpnme.EMPTY/*qual.symbol.info.parents.head.symbol.name*/) setPos qual.pos, sym.alias) setPos tree.pos } if (settings.debug.value) @@ -202,7 +204,7 @@ abstract class SuperAccessors extends transform.Transform with transform.TypingT } else mayNeedProtectedAccessor(sel, List(EmptyTree), false) - case Select(sup @ Super(_, mix), name) => + case Select(Super(_, mix), name) => if (sym.isValue && !sym.isMethod || sym.hasAccessorFlag) { unit.error(tree.pos, "super may be not be used on "+ (if (sym.hasAccessorFlag) sym.accessed else sym)) diff --git a/src/compiler/scala/tools/nsc/typechecker/Typers.scala b/src/compiler/scala/tools/nsc/typechecker/Typers.scala index cf28ea24fe..c0158a09c1 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Typers.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Typers.scala @@ -3378,41 +3378,44 @@ trait Typers extends Modes { def qualifyingClassSym(qual: Name): Symbol = if (tree.symbol != NoSymbol) tree.symbol else qualifyingClass(tree, qual, false) - def typedSuper(qual: Name, mix: Name) = { - val clazz = qualifyingClassSym(qual) - if (clazz == NoSymbol) setError(tree) - else { - def findMixinSuper(site: Type): Type = { - val ps = site.parents filter (_.typeSymbol.name == mix) - if (ps.isEmpty) { - if (settings.debug.value) - Console.println(site.parents map (_.typeSymbol.name))//debug - if (phase.erasedTypes && context.enclClass.owner.isImplClass) { - // the reference to super class got lost during erasure - restrictionError(tree.pos, unit, "traits may not select fields or methods from to super[C] where C is a class") - } else { - error(tree.pos, mix+" does not name a parent class of "+clazz) - } - ErrorType - } else if (!ps.tail.isEmpty) { - error(tree.pos, "ambiguous parent class qualifier") - ErrorType + def typedSuper(qual: Tree, mix: TypeName) = { + val qual1 = typed(qual) + val clazz = qual1.symbol + + def findMixinSuper(site: Type): Type = { + var ps = site.parents filter (_.typeSymbol.name == mix) + if (ps.isEmpty) + ps = site.parents filter (_.typeSymbol.toInterface.name == mix) + if (ps.isEmpty) { + if (settings.debug.value) + Console.println(site.parents map (_.typeSymbol.name))//debug + if (phase.erasedTypes && context.enclClass.owner.isImplClass) { + // the reference to super class got lost during erasure + restrictionError(tree.pos, unit, "traits may not select fields or methods from super[C] where C is a class") } else { - ps.head + error(tree.pos, mix+" does not name a parent class of "+clazz) } + ErrorType + } else if (!ps.tail.isEmpty) { + error(tree.pos, "ambiguous parent class qualifier") + ErrorType + } else { + ps.head } - val owntype = - if (mix.isEmpty) { - if ((mode & SUPERCONSTRmode) != 0) - if (clazz.info.parents.isEmpty) AnyRefClass.tpe // can happen due to cyclic references ==> #1036 - else clazz.info.parents.head - else intersectionType(clazz.info.parents) - } else { - findMixinSuper(clazz.info) - } - tree setSymbol clazz setType SuperType(clazz.thisType, owntype) } - } + + val owntype = + if (mix.isEmpty) { + if ((mode & SUPERCONSTRmode) != 0) + if (clazz.info.parents.isEmpty) AnyRefClass.tpe // can happen due to cyclic references ==> #1036 + else clazz.info.parents.head + else intersectionType(clazz.info.parents) + } else { + findMixinSuper(clazz.info) + } + + treeCopy.Super(tree, qual1, mix) setType SuperType(clazz.thisType, owntype) + } def typedThis(qual: Name) = { val clazz = qualifyingClassSym(qual) @@ -3609,11 +3612,11 @@ trait Typers extends Modes { } else { cx = cx.enclClass - defSym = pre.member(name) filter ( - sym => qualifies(sym) && context.isAccessible(sym, pre, false)) + val foundSym = pre.member(name) filter qualifies + defSym = foundSym filter (context.isAccessible(_, pre, false)) if (defSym == NoSymbol) { - if (inaccessibleSym eq NoSymbol) { - inaccessibleSym = pre.member(name) filter qualifies + if ((foundSym ne NoSymbol) && (inaccessibleSym eq NoSymbol)) { + inaccessibleSym = foundSym inaccessibleExplanation = analyzer.lastAccessCheckDetails } cx = cx.outer |