From d283455a24148f43d33f69f4be1b627705d35ab6 Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Fri, 18 Aug 2006 17:09:14 +0000 Subject: fixed bug 704 --- src/compiler/scala/tools/nsc/ast/TreeGen.scala | 24 ++++++++ src/compiler/scala/tools/nsc/symtab/Flags.scala | 1 + src/compiler/scala/tools/nsc/transform/Mixin.scala | 68 +++++++++------------- .../scala/tools/nsc/typechecker/RefChecks.scala | 30 +--------- test/files/neg/bug708.check | 5 ++ test/files/neg/bug708.scala | 12 ++++ test/files/pos/bug704.scala | 14 +++++ 7 files changed, 86 insertions(+), 68 deletions(-) create mode 100644 test/files/neg/bug708.check create mode 100644 test/files/neg/bug708.scala create mode 100644 test/files/pos/bug704.scala diff --git a/src/compiler/scala/tools/nsc/ast/TreeGen.scala b/src/compiler/scala/tools/nsc/ast/TreeGen.scala index 4ec47829e2..92bd5ad0c0 100644 --- a/src/compiler/scala/tools/nsc/ast/TreeGen.scala +++ b/src/compiler/scala/tools/nsc/ast/TreeGen.scala @@ -171,6 +171,30 @@ abstract class TreeGen { ) } + // var m$: T = null; or, if class member: local var m$: T = _; + def mkModuleVarDef(accessor: Symbol) = { + val mvar = accessor.owner.newVariable(accessor.pos, nme.moduleVarName(accessor.name)) + .setInfo(accessor.tpe.finalResultType) + .setFlag(MODULEVAR); + if (mvar.owner.isClass) { + mvar setFlag (PRIVATE | LOCAL | SYNTHETIC); + mvar.owner.info.decls.enter(mvar); + } + ValDef(mvar, if (mvar.owner.isClass) EmptyTree else Literal(Constant(null))) + } + + // def m: T = { if (m$ == null) m$ = new m$class; m$ } + def mkModuleAccessDef(accessor: Symbol, mvar: Symbol) = + DefDef(accessor, vparamss => + mkCached(mvar, + New(TypeTree(mvar.tpe), + List(for (val pt <- mvar.tpe.symbol.primaryConstructor.info.paramTypes) + yield This(accessor.owner.enclClass))))) + + // def m: T; + def mkModuleAccessDcl(accessor: Symbol) = + DefDef(accessor setFlag lateDEFERRED, vparamss => EmptyTree) + def mkRuntimeCall(meth: Name, args: List[Tree]): Tree = Apply(Select(mkAttributedRef(ScalaRunTimeModule), meth), args) } diff --git a/src/compiler/scala/tools/nsc/symtab/Flags.scala b/src/compiler/scala/tools/nsc/symtab/Flags.scala index d54a12159b..12327875a0 100644 --- a/src/compiler/scala/tools/nsc/symtab/Flags.scala +++ b/src/compiler/scala/tools/nsc/symtab/Flags.scala @@ -85,6 +85,7 @@ object Flags { final val lateFINAL = (FINAL: long) << LateShift; final val lateMETHOD = (METHOD: long) << LateShift; final val notPRIVATE = (PRIVATE: long) << AntiShift; + final val notDEFERRED = (DEFERRED: long) << AntiShift; final val notPROTECTED = (PROTECTED: long) << AntiShift; final val notABSTRACT = (ABSTRACT: long) << AntiShift; final val notOVERRIDE = (OVERRIDE: long) << AntiShift; diff --git a/src/compiler/scala/tools/nsc/transform/Mixin.scala b/src/compiler/scala/tools/nsc/transform/Mixin.scala index 4879f59250..a1eb5d003c 100644 --- a/src/compiler/scala/tools/nsc/transform/Mixin.scala +++ b/src/compiler/scala/tools/nsc/transform/Mixin.scala @@ -90,11 +90,6 @@ abstract class Mixin extends InfoTransform { var setter = member.setter(clazz) if (setter == NoSymbol) setter = addMember(clazz, newSetter(member)) } -/* - } else if ((member hasFlag BRIDGE) && !(member hasFlag PRIVATE)) { - member.expandName(clazz); - addMember(clazz, member.cloneSymbol(clazz) resetFlag FINAL); -*/ } } if (settings.debug.value) log("new defs of " + clazz + " = " + clazz.info.decls); @@ -125,31 +120,6 @@ abstract class Mixin extends InfoTransform { member1.asInstanceOf[TermSymbol] setAlias member; } } -/* - //System.out.println("adding forwarded method " + member + " " + mmap(member) + member.locationString + " to " + clazz + " " + (clazz.info.member(member.name).alternatives));//DEBUG - if (isForwarded(member) && !isStatic(member)) { - if (clazz.info.findMember(member.name, 0, 0).alternatives contains mmap(member)) { - val mmember = member.overriddenSymbol(mixinClass.toInterface) - if (!mmember.hasFlag(lateDEFERRED)) - Console.println("SURPRISE0: "+member+" "+mmember+mmember.locationString+" is not late deferred") - if (mmember.overridingSymbol(clazz) != NoSymbol) - Console.println("SURPRISE1: "+member+" "+mmember+mmember.locationString+" is overridden by class") - if (!atPhase(phase.next)(clazz.info).findMember(member.name, 0, lateDEFERRED).alternatives.contains(mmember)) - Console.println("SURPRISE2: "+member+" "+mmember+mmember.locationString+" is not among late deferred members") - val member1 = addMember( - clazz, - member.cloneSymbol(clazz) setPos clazz.pos resetFlag (DEFERRED | lateDEFERRED)); - member1.asInstanceOf[TermSymbol] setAlias member; - } else { - val mmember = member.overriddenSymbol(mixinClass.toInterface) - if (!mmember.hasFlag(lateDEFERRED)) - Console.println("SURPRISE3: "+member+" "+mmember+mmember.locationString+" is not late deferred") - if (mmember.overridingSymbol(clazz) == NoSymbol) - if (atPhase(phase.next)(clazz.info).findMember(member.name, 0, lateDEFERRED).alternatives.contains(mmember)) - Console.println("SURPRISE4: "+member+" "+mmember+mmember.locationString+" is mixed in but violates conditions") - } - } -*/ } } else if (mixinClass.hasFlag(lateINTERFACE)) { addLateInterfaceMembers(mixinClass) @@ -289,16 +259,14 @@ abstract class Mixin extends InfoTransform { private def addNewDefs(clazz: Symbol, stats: List[Tree]): List[Tree] = { val newDefs = new ListBuffer[Tree] - def addDef(pos: int, tree: Tree): unit = { + def attributedDef(pos: int, tree: Tree): Tree = { if (settings.debug.value) System.out.println("add new def to " + clazz + ": " + tree); - newDefs += localTyper.typed { - atPos(pos) { - tree - } - } + localTyper.typed { atPos(pos) { tree } } } def position(sym: Symbol) = if (sym.pos == Position.NOPOS) clazz.pos else sym.pos + def addDef(pos: int, tree: Tree): unit = + newDefs += attributedDef(pos, tree) def addDefDef(sym: Symbol, rhs: List[Symbol] => Tree): unit = addDef(position(sym), DefDef(sym, vparamss => rhs(vparamss.head))) def add(stats: List[Tree], newDefs: List[Tree]) = { @@ -327,6 +295,23 @@ abstract class Mixin extends InfoTransform { case _ => stat } + def implementPrivateObject(stat: Tree): List[Tree] = { + val sym = stat.symbol + stat match { + case _: DefDef if (sym.isModule && sym.hasFlag(PRIVATE)) => + val vdef = attributedDef(position(sym), gen.mkModuleVarDef(sym)) + val adef = attributedDef( + position(sym), + DefDef(sym, vparamss => + gen.mkCached( + vdef.symbol, + New(TypeTree(vdef.symbol.tpe), vparamss map (.map(Ident)))))) + sym resetFlag lateDEFERRED + List(vdef, adef) + case _ => + List(stat) + } + } for (val sym <- clazz.info.decls.toList) { if (sym hasFlag MIXEDIN) { if (clazz hasFlag lateINTERFACE) { @@ -340,9 +325,9 @@ abstract class Mixin extends InfoTransform { } if (sym.isSetter) Assign(accessedRef, Ident(vparams.head)) else accessedRef}) } else if (sym.isModule && !(sym hasFlag LIFTED)) { - val vdef = refchecks.newModuleVarDef(sym); + val vdef = gen.mkModuleVarDef(sym); addDef(position(sym), vdef) - addDef(position(sym), refchecks.newModuleAccessDef(sym, vdef.symbol)) + addDef(position(sym), gen.mkModuleAccessDef(sym, vdef.symbol)) } else if (!sym.isMethod) { addDef(position(sym), ValDef(sym)) } else if (sym hasFlag SUPERACCESSOR) { @@ -353,10 +338,11 @@ abstract class Mixin extends InfoTransform { Apply(staticRef(sym.alias), gen.mkAttributedThis(clazz) :: (vparams map Ident))) } } - } } - val stats1 = add(stats, newDefs.toList) - if (clazz.isTrait) stats1 else stats1 map completeSuperAccessor; + var stats1 = add(stats, newDefs.toList) + if (!clazz.isTrait) stats1 = stats1 map completeSuperAccessor + if (clazz.isImplClass) stats1 = stats1 flatMap implementPrivateObject + stats1 } private def postTransform(tree: Tree): Tree = { diff --git a/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala b/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala index c745290cc9..5a2d7f8b7b 100644 --- a/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala +++ b/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala @@ -46,30 +46,6 @@ abstract class RefChecks extends InfoTransform { } else tp } - // var m$: T = null; or, if class member: local var m$: T = _; - def newModuleVarDef(accessor: Symbol) = { - val mvar = accessor.owner.newVariable(accessor.pos, nme.moduleVarName(accessor.name)) - .setInfo(accessor.tpe.finalResultType) - .setFlag(MODULEVAR); - if (mvar.owner.isClass) { - mvar setFlag (PRIVATE | LOCAL | SYNTHETIC); - mvar.owner.info.decls.enter(mvar); - } - ValDef(mvar, if (mvar.owner.isClass) EmptyTree else Literal(Constant(null))) - } - - // def m: T = { if (m$ == null) m$ = new m$class; m$ } - def newModuleAccessDef(accessor: Symbol, mvar: Symbol) = - DefDef(accessor, vparamss => - gen.mkCached(mvar, - New(TypeTree(mvar.tpe), - List(for (val pt <- mvar.tpe.symbol.primaryConstructor.info.paramTypes) - yield This(accessor.owner.enclClass))))) - - // def m: T; - def newModuleAccessDcl(accessor: Symbol) = - DefDef(accessor setFlag lateDEFERRED, vparamss => EmptyTree); - class RefCheckTransformer(unit: CompilationUnit) extends Transformer { var localTyper: analyzer.Typer = typer; @@ -458,15 +434,15 @@ abstract class RefChecks extends InfoTransform { val vdef = localTyper.typed { atPos(tree.pos) { - newModuleVarDef(sym) + gen.mkModuleVarDef(sym) } } val ddef = atPhase(phase.next) { localTyper.typed { - if (sym.owner.isTrait) newModuleAccessDcl(sym) - else newModuleAccessDef(sym, vdef.symbol) + if (sym.owner.isTrait) gen.mkModuleAccessDcl(sym) + else gen.mkModuleAccessDef(sym, vdef.symbol) } } diff --git a/test/files/neg/bug708.check b/test/files/neg/bug708.check new file mode 100644 index 0000000000..30b31b662a --- /dev/null +++ b/test/files/neg/bug708.check @@ -0,0 +1,5 @@ +bug708.scala:8 error: error overriding type A$$S in trait X with bounds >: scala.All <: A.this.T; + type A$$S has incompatible type scala.Any + override private[A] type S = Any; + ^ +one error found diff --git a/test/files/neg/bug708.scala b/test/files/neg/bug708.scala new file mode 100644 index 0000000000..f86a005811 --- /dev/null +++ b/test/files/neg/bug708.scala @@ -0,0 +1,12 @@ +trait A { + type T; + trait X { + private[A] type S <: T; + /*private[A]*/ def foo : S; + } + trait Y extends X { + override private[A] type S = Any; + override /*private[A]*/ def foo = null; + } +} + diff --git a/test/files/pos/bug704.scala b/test/files/pos/bug704.scala new file mode 100644 index 0000000000..aea8292f2d --- /dev/null +++ b/test/files/pos/bug704.scala @@ -0,0 +1,14 @@ +trait D { + private val x = 1 + private object xxxx { Console.println(x) } +} +object Go extends D { + def main(args : Array[String]) : Unit = {}; +} +trait D2 { + val x = 1 + object yyyy { Console.println(x) } +} +object Go2 extends D2 { + def main(args : Array[String]) : Unit = {}; +} -- cgit v1.2.3