diff options
29 files changed, 228 insertions, 184 deletions
diff --git a/src/compiler/scala/tools/nsc/Global.scala b/src/compiler/scala/tools/nsc/Global.scala index 66b264a4ce..e8d72fb88d 100644 --- a/src/compiler/scala/tools/nsc/Global.scala +++ b/src/compiler/scala/tools/nsc/Global.scala @@ -231,7 +231,7 @@ class Global(val settings: Settings, val reporter: Reporter) extends SymbolTable val global: Global.this.type = Global.this; } - object mixin extends Mixin { + object mixer extends Mixin { val global: Global.this.type = Global.this; } @@ -274,7 +274,7 @@ class Global(val settings: Settings, val reporter: Reporter) extends SymbolTable lambdaLift, constructors, flatten, - mixin, + mixer, genicode, genJVM, sampleTransform); diff --git a/src/compiler/scala/tools/nsc/ast/TreeBrowsers.scala b/src/compiler/scala/tools/nsc/ast/TreeBrowsers.scala index 9e4821a734..20c7ce05dd 100644 --- a/src/compiler/scala/tools/nsc/ast/TreeBrowsers.scala +++ b/src/compiler/scala/tools/nsc/ast/TreeBrowsers.scala @@ -317,8 +317,8 @@ abstract class TreeBrowsers { case Apply(fun, args) => Pair("Apply", EMPTY); - case Super(qualif, mixin) => - Pair("Super", qualif.toString() + ", mixin: " + mixin.toString()); + case Super(qualif, mix) => + Pair("Super", qualif.toString() + ", mix: " + mix.toString()); case This(qualifier) => Pair("This", qualifier); @@ -458,7 +458,7 @@ abstract class TreeBrowsers { case Apply(fun, args) => List(fun) ::: args; - case Super(qualif, mixin) => + case Super(qualif, mix) => Nil; case This(qualif) => diff --git a/src/compiler/scala/tools/nsc/ast/TreePrinters.scala b/src/compiler/scala/tools/nsc/ast/TreePrinters.scala index 206fa58061..4d13548a08 100644 --- a/src/compiler/scala/tools/nsc/ast/TreePrinters.scala +++ b/src/compiler/scala/tools/nsc/ast/TreePrinters.scala @@ -82,17 +82,20 @@ abstract class TreePrinters { def printModifiers(tree: Tree, mods: Modifiers): unit = { if (tree.symbol == NoSymbol) printFlags(mods.flags, mods.privateWithin) - else if (tree.symbol.privateWithin == null) + else if (tree.symbol.privateWithin == NoSymbol || + tree.symbol.privateWithin == tree.symbol.owner) printFlags(tree.symbol.flags, nme.EMPTY.toTypeName) else printFlags(tree.symbol.flags, tree.symbol.privateWithin.name) } def printFlags(flags: long, privateWithin: Name): unit = { - val mask = if (settings.debug.value) -1 else PrintableFlags; - val suffixes: List[Pair[long, String]] = - if (privateWithin.isEmpty) List() else List(Pair(PRIVATE, privateWithin.toString())); - val s = flagsToString(flags & mask, suffixes); + var mask = if (settings.debug.value) -1 else PrintableFlags; + if (!privateWithin.isEmpty) { + print("private["+privateWithin+"] "); + mask = mask & ~PRIVATE + } + val s = flagsToString(flags & mask); if (s.length() != 0) print(s + " ") } @@ -106,7 +109,7 @@ abstract class TreePrinters { case ClassDef(mods, name, tparams, tp, impl) => printModifiers(tree, mods); - print((if (mods.hasFlag(TRAIT)) "trait " else "class ") + symName(tree, name)); + print("class " + symName(tree, name)); printTypeParams(tparams); printOpt(": ", tp); print(" extends "); print(impl); @@ -221,11 +224,11 @@ abstract class TreePrinters { case Apply(fun, vargs) => print(fun); printRow(vargs, "(", ", ", ")"); - case Super(qual, mixin) => + case Super(qual, mix) => if (!qual.isEmpty || tree.symbol != NoSymbol) print(symName(tree, qual) + "."); print("super"); - if (!mixin.isEmpty) - print("[" + mixin + "]") + if (!mix.isEmpty) + print("[" + mix + "]") case This(qual) => if (!qual.isEmpty) print(symName(tree, qual) + "."); diff --git a/src/compiler/scala/tools/nsc/ast/Trees.scala b/src/compiler/scala/tools/nsc/ast/Trees.scala index 92b147c947..48f6cbbd7b 100644 --- a/src/compiler/scala/tools/nsc/ast/Trees.scala +++ b/src/compiler/scala/tools/nsc/ast/Trees.scala @@ -19,7 +19,7 @@ import symtab.Flags._; case class Modifiers(flags: int, privateWithin: Name) { def isPrivate = ((flags & PRIVATE ) != 0); def isProtected = ((flags & PROTECTED) != 0); - def isVariable = ((flags & MUTABLE) != 0); + def isVariable = ((flags & MUTABLE ) != 0); def isPublic = !isPrivate && !isProtected; def hasFlag(flag: int) = (flags & flag) != 0; def | (flag: int): Modifiers = { @@ -452,10 +452,10 @@ import symtab.Flags._; } /** Super reference */ - case class Super(qual: Name, mixin: Name) + case class Super(qual: Name, mix: Name) extends TermTree with SymTree; - def Super(sym: Symbol, mixin: Name): Tree = Super(sym.name, mixin) setSymbol sym; + def Super(sym: Symbol, mix: Name): Tree = Super(sym.name, mix) setSymbol sym; /** Self reference */ case class This(qual: Name) @@ -590,7 +590,7 @@ import symtab.Flags._; case Typed(expr, tpt) => (eliminated by erasure) case TypeApply(fun, args) => case Apply(fun, args) => - case Super(qual, mixin) => + case Super(qual, mix) => case This(qual) => case Select(qualifier, selector) => case Ident(name) => @@ -633,7 +633,7 @@ import symtab.Flags._; def Typed(tree: Tree, expr: Tree, tpt: Tree): Typed; def TypeApply(tree: Tree, fun: Tree, args: List[Tree]): TypeApply; def Apply(tree: Tree, fun: Tree, args: List[Tree]): Apply; - def Super(tree: Tree, qual: Name, mixin: Name): Super; + def Super(tree: Tree, qual: Name, mix: Name): Super; def This(tree: Tree, qual: Name): This; def Select(tree: Tree, qualifier: Tree, selector: Name): Select; def Ident(tree: Tree, name: Name): Ident; @@ -706,8 +706,8 @@ import symtab.Flags._; new TypeApply(fun, args).copyAttrs(tree); def Apply(tree: Tree, fun: Tree, args: List[Tree]) = new Apply(fun, args).copyAttrs(tree); - def Super(tree: Tree, qual: Name, mixin: Name) = - new Super(qual, mixin).copyAttrs(tree); + def Super(tree: Tree, qual: Name, mix: Name) = + new Super(qual, mix).copyAttrs(tree); def This(tree: Tree, qual: Name) = new This(qual).copyAttrs(tree); def Select(tree: Tree, qualifier: Tree, selector: Name) = @@ -880,10 +880,10 @@ import symtab.Flags._; if ((fun0 == fun) && (args0 == args)) => t case _ => copy.Apply(tree, fun, args) } - def Super(tree: Tree, qual: Name, mixin: Name) = tree match { - case t @ Super(qual0, mixin0) - if ((qual0 == qual) && (mixin0 == mixin)) => t - case _ => copy.Super(tree, qual, mixin) + 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) } def This(tree: Tree, qual: Name) = tree match { case t @ This(qual0) @@ -1012,8 +1012,8 @@ import symtab.Flags._; copy.TypeApply(tree, transform(fun), transformTrees(args)) case Apply(fun, args) => copy.Apply(tree, transform(fun), transformTrees(args)) - case Super(qual, mixin) => - copy.Super(tree, qual, mixin) + case Super(qual, mix) => + copy.Super(tree, qual, mix) case This(qual) => copy.This(tree, qual) case Select(qualifier, selector) => diff --git a/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala b/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala index 36f6d5890e..00c8cf99a5 100644 --- a/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala +++ b/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala @@ -133,12 +133,12 @@ import Tokens._; /////// TOKEN CLASSES ////////////////////////////////////////////////////// def isModifier: boolean = in.token match { - case ABSTRACT | FINAL | SEALED | PRIVATE | PROTECTED | OVERRIDE | IMPLICIT => true + case ABSTRACT | FINAL | SEALED | MIXIN | PRIVATE | PROTECTED | OVERRIDE | IMPLICIT => true case _ => false } def isLocalModifier: boolean = in.token match { - case ABSTRACT | FINAL | SEALED => true + case ABSTRACT | FINAL | SEALED | MIXIN => true case _ => false } @@ -1061,22 +1061,29 @@ import Tokens._; ////////// MODIFIERS //////////////////////////////////////////////////////////// /** Modifiers ::= {Modifier} - * Modifier ::= final - * | private [ "[" Id "]" ] - * | protected - * | override - * | abstract + * Modifier ::= LocalClassModifier + * | private [ "[" Id "]" ] + * | protected | override | implicit */ def modifiers(): Modifiers = { + var privateWithin: Name = nme.EMPTY.toTypeName; def loop(mods: int): int = in.token match { case ABSTRACT => loop(addMod(mods, Flags.ABSTRACT)) + case MIXIN => + loop(addMod(mods, Flags.MIXIN)) case FINAL => loop(addMod(mods, Flags.FINAL)) case SEALED => loop(addMod(mods, Flags.SEALED)) case PRIVATE => - loop(addMod(mods, Flags.PRIVATE)) + val mods1 = addMod(mods, Flags.PRIVATE); + if (in.token == LBRACKET) { + in.nextToken(); + privateWithin = ident().toTypeName; + accept(RBRACKET) + } + loop(mods1) case PROTECTED => loop(addMod(mods, Flags.PROTECTED)) case OVERRIDE => @@ -1089,17 +1096,18 @@ import Tokens._; var mods = loop(0); if ((mods & (Flags.ABSTRACT | Flags.OVERRIDE)) == (Flags.ABSTRACT | Flags.OVERRIDE)) mods = mods & ~(Flags.ABSTRACT | Flags.OVERRIDE) | Flags.ABSOVERRIDE; - Modifiers(mods) + Modifiers(mods, privateWithin) } /** LocalClassModifiers ::= {LocalClassModifier} - * LocalClassModifier ::= final - * | private + * LocalClassModifier ::= abstract | mixin | final | sealed */ def localClassModifiers(): Modifiers = { def loop(mods: int): int = in.token match { case ABSTRACT => loop(addMod(mods, Flags.ABSTRACT)) + case MIXIN => + loop(addMod(mods, Flags.MIXIN)) case FINAL => loop(addMod(mods, Flags.FINAL)) case SEALED => @@ -1506,20 +1514,23 @@ import Tokens._; /** TmplDef ::= ([case] class | trait) ClassDef * | [case] object ObjectDef */ - def tmplDef(mods: Modifiers): Tree = in.token match { - case TRAIT => - classDef(mods | Flags.TRAIT | Flags.ABSTRACT); - case CLASS => - classDef(mods); - case CASECLASS => - classDef(mods | Flags.CASE); - case OBJECT => - objectDef(mods); - case CASEOBJECT => - objectDef(mods | Flags.CASE); - case _ => - syntaxError("illegal start of definition", true); + def tmplDef(mods: Modifiers): Tree = { + val mods1 = if (mods.hasFlag(Flags.MIXIN)) mods | Flags.ABSTRACT else mods; + in.token match { + case TRAIT => + classDef(mods1 | Flags.MIXIN | Flags.ABSTRACT); + case CLASS => + classDef(mods1); + case CASECLASS => + classDef(mods1 | Flags.CASE); + case OBJECT => + objectDef(mods1); + case CASEOBJECT => + objectDef(mods1 | Flags.CASE); + case _ => + syntaxError("illegal start of definition", true); EmptyTree + } } /** ClassDef ::= ClassSig RequiresTypeOpt ClassTemplate @@ -1534,7 +1545,7 @@ import Tokens._; val vparamss = paramClauses(name, implicitViews.toList, mods.hasFlag(Flags.CASE)); val thistpe = requiresTypeOpt(); val template = classTemplate(mods, name, vparamss); - val mods1 = if (mods.hasFlag(Flags.TRAIT) && (template.body forall treeInfo.isInterfaceMember)) + val mods1 = if (mods.hasFlag(Flags.MIXIN) && (template.body forall treeInfo.isInterfaceMember)) mods | Flags.INTERFACE else mods; ClassDef(mods1, name, tparams, thistpe, template) @@ -1583,7 +1594,7 @@ import Tokens._; var body = if (in.token == LBRACE) templateBody() else { acceptEmptyTemplateBody("`{' expected"); List() } - if (!mods.hasFlag(Flags.TRAIT)) Template(ps, vparamss, argss.toList, body) + if (!mods.hasFlag(Flags.MIXIN)) Template(ps, vparamss, argss.toList, body) else Template(ps, body) } @@ -1644,7 +1655,7 @@ import Tokens._; isModifier) { val attrs = attributeClauses(); (stats ++ - joinAttributes(attrs, joinComment(List(tmplDef(modifiers() | traitAttribute(attrs)))))) + joinAttributes(attrs, joinComment(List(tmplDef(modifiers() | mixinAttribute(attrs)))))) } else if (in.token != SEMI && in.token != NEWLINE) { syntaxError("illegal start of class or object definition", true); } @@ -1670,7 +1681,7 @@ import Tokens._; } else if (isDefIntro || isModifier || in.token == LBRACKET) { val attrs = attributeClauses(); (stats ++ - joinAttributes(attrs, joinComment(defOrDcl(modifiers() | traitAttribute(attrs))))) + joinAttributes(attrs, joinComment(defOrDcl(modifiers() | mixinAttribute(attrs))))) } else if (in.token != SEMI && in.token != NEWLINE) { syntaxError("illegal start of definition", true); } @@ -1708,14 +1719,15 @@ import Tokens._; atPos(pos) { New(t, List(args)) } } - def traitAttribute(attrs: List[Tree]) = { - def isTraitAttribute(attr: Tree) = attr match { - case Apply(Select(New(Ident(name)), constr), List()) if (name.toString() == "_trait_") => + def mixinAttribute(attrs: List[Tree]) = { + def isMixinAttribute(attr: Tree) = attr match { + case Apply(Select(New(Ident(name)), constr), List()) + if (name.toString() == "_mixin_" || name.toString() == "_trait_") => true case _ => false } - if (attrs exists isTraitAttribute) Flags.TRAIT else 0 + if (attrs exists isMixinAttribute) Flags.MIXIN else 0 } def joinAttributes(attrs: List[Tree], defs: List[Tree]): List[Tree] = diff --git a/src/compiler/scala/tools/nsc/ast/parser/Scanners.scala b/src/compiler/scala/tools/nsc/ast/parser/Scanners.scala index 091a4faa05..717d4fd23a 100644 --- a/src/compiler/scala/tools/nsc/ast/parser/Scanners.scala +++ b/src/compiler/scala/tools/nsc/ast/parser/Scanners.scala @@ -768,7 +768,7 @@ import scala.tools.nsc.util.CharArrayReader enterKeyword(nme.IMPLICITkw, IMPLICIT) enterKeyword(nme.IMPORTkw, IMPORT) enterKeyword(nme.MATCHkw, MATCH) - enterKeyword(nme.REQUIRESkw, REQUIRES) + enterKeyword(nme.MIXINkw, MIXIN) enterKeyword(nme.NEWkw, NEW) enterKeyword(nme.NULLkw, NULL) enterKeyword(nme.OBJECTkw, OBJECT) @@ -776,6 +776,7 @@ import scala.tools.nsc.util.CharArrayReader enterKeyword(nme.PACKAGEkw, PACKAGE) enterKeyword(nme.PRIVATEkw, PRIVATE) enterKeyword(nme.PROTECTEDkw, PROTECTED) + enterKeyword(nme.REQUIRESkw, REQUIRES) enterKeyword(nme.RETURNkw, RETURN) enterKeyword(nme.SEALEDkw, SEALED) enterKeyword(nme.SUPERkw, SUPER) diff --git a/src/compiler/scala/tools/nsc/ast/parser/Tokens.scala b/src/compiler/scala/tools/nsc/ast/parser/Tokens.scala index b99ee08811..2f07497ede 100644 --- a/src/compiler/scala/tools/nsc/ast/parser/Tokens.scala +++ b/src/compiler/scala/tools/nsc/ast/parser/Tokens.scala @@ -67,6 +67,7 @@ object Tokens { final val RETURN = 57; final val MATCH = 58; final val REQUIRES = 59; + final val MIXIN = 60; /** special symbols */ final val COMMA = 61; diff --git a/src/compiler/scala/tools/nsc/backend/WorklistAlgorithm.scala b/src/compiler/scala/tools/nsc/backend/WorklistAlgorithm.scala index 6676c820bc..d6b81a84fe 100644 --- a/src/compiler/scala/tools/nsc/backend/WorklistAlgorithm.scala +++ b/src/compiler/scala/tools/nsc/backend/WorklistAlgorithm.scala @@ -15,7 +15,7 @@ import scala.collection.mutable.MutableList; * function is applied repeatedly to the first element in the * worklist, as long as the stack is not empty. * - * The client class should mix-in this trait and initialize the + * The client class should mix-in this class and initialize the * worklist field and define the processElement method. Then call * the 'run' method providing a function that initializes the * worklist. diff --git a/src/compiler/scala/tools/nsc/backend/icode/Checkers.scala b/src/compiler/scala/tools/nsc/backend/icode/Checkers.scala index be6aef6251..00741a1e0e 100644 --- a/src/compiler/scala/tools/nsc/backend/icode/Checkers.scala +++ b/src/compiler/scala/tools/nsc/backend/icode/Checkers.scala @@ -419,7 +419,7 @@ abstract class Checkers { stack.push(toTypeKind(method.info.resultType)); } - case SuperCall(mixin) => + case SuperCall(mix) => checkStack(1 + method.info.paramTypes.length); checkMethodArgs(method); checkMethod(stack.pop, method); diff --git a/src/compiler/scala/tools/nsc/backend/icode/GenICode.scala b/src/compiler/scala/tools/nsc/backend/icode/GenICode.scala index a7940cd66a..0e7c126f0d 100644 --- a/src/compiler/scala/tools/nsc/backend/icode/GenICode.scala +++ b/src/compiler/scala/tools/nsc/backend/icode/GenICode.scala @@ -526,11 +526,11 @@ abstract class GenICode extends SubComponent { // to call super constructors explicitly and/or use their 'returned' value. // therefore, we can ignore this fact, and generate code that leaves nothing // on the stack (contrary to what the type in the AST says). - case Apply(fun @ Select(Super(_, mixin), _), args) => + case Apply(fun @ Select(Super(_, mix), _), args) => if (settings.debug.value) log("Call to super: " + tree); - val invokeStyle = SuperCall(mixin); -// if (fun.symbol.isConstructor) Static(true) else SuperCall(mixin); + val invokeStyle = SuperCall(mix); +// if (fun.symbol.isConstructor) Static(true) else SuperCall(mix); ctx.bb.emit(THIS(ctx.clazz.symbol), tree.pos); val ctx1 = genLoadArguments(args, fun.symbol.info.paramTypes, ctx); diff --git a/src/compiler/scala/tools/nsc/backend/icode/Opcodes.scala b/src/compiler/scala/tools/nsc/backend/icode/Opcodes.scala index 24eb1132f6..bb2b0c39eb 100644 --- a/src/compiler/scala/tools/nsc/backend/icode/Opcodes.scala +++ b/src/compiler/scala/tools/nsc/backend/icode/Opcodes.scala @@ -454,7 +454,7 @@ import scala.tools.nsc.util.Position; case Dynamic => "dynamic"; case Static(false) => "static-class"; case Static(true) => "static-instance"; - case SuperCall(mixin) => "super(" + mixin + ")"; + case SuperCall(mix) => "super(" + mix + ")"; } } @@ -466,8 +466,8 @@ import scala.tools.nsc.util.Position; */ case class Static(onInstance: Boolean) extends InvokeStyle; - /** Call through super[mixin]. */ - case class SuperCall(mixin: Name) extends InvokeStyle; + /** Call through super[mix]. */ + case class SuperCall(mix: Name) extends InvokeStyle; } } diff --git a/src/compiler/scala/tools/nsc/matching/CodeFactory.scala b/src/compiler/scala/tools/nsc/matching/CodeFactory.scala index 1d6882a0fa..d4678738ec 100644 --- a/src/compiler/scala/tools/nsc/matching/CodeFactory.scala +++ b/src/compiler/scala/tools/nsc/matching/CodeFactory.scala @@ -134,6 +134,7 @@ import scala.tools.nsc.util.Position; } // used by Equals + /* private def getCoerceToInt(left: Type): Symbol = { val sym = left.nonPrivateMember( nme.coerce ); //assert sym != Symbol.NONE : Debug.show(left); @@ -145,7 +146,7 @@ import scala.tools.nsc.util.Position; } }.get } - + */ // used by Equals /* private def getEqEq(left: Type, right: Type): Symbol = { diff --git a/src/compiler/scala/tools/nsc/symtab/Definitions.scala b/src/compiler/scala/tools/nsc/symtab/Definitions.scala index b4f760220f..af2f8e55d8 100644 --- a/src/compiler/scala/tools/nsc/symtab/Definitions.scala +++ b/src/compiler/scala/tools/nsc/symtab/Definitions.scala @@ -80,7 +80,7 @@ import Flags._; def SeqFactory = getMember(ScalaRunTimeModule, "Seq"); var RepeatedParamClass: Symbol = _; var ByNameParamClass: Symbol = _; - var TraitClass: Symbol = _; + //var TraitClass: Symbol = _; val MaxTupleArity = 9; val MaxFunctionArity = 9; @@ -310,10 +310,10 @@ import Flags._; AnyRefClass = newAlias(ScalaPackageClass, "AnyRef", ObjectClass.typeConstructor); AllRefClass = newClass(ScalaPackageClass, "AllRef", List(AnyRefClass.typeConstructor)) - .setFlag(ABSTRACT | TRAIT | FINAL); + .setFlag(ABSTRACT | MIXIN | FINAL); AllClass = newClass(ScalaPackageClass, "All", List(AnyClass.typeConstructor)) - .setFlag(ABSTRACT | TRAIT | FINAL); + .setFlag(ABSTRACT | MIXIN | FINAL); StringClass = getClass("java.lang.String"); ThrowableClass = getClass("java.lang.Throwable"); @@ -352,7 +352,7 @@ import Flags._; tparam => typeRef(SeqClass.typeConstructor.prefix, SeqClass, List(tparam.typeConstructor))); ByNameParamClass = newCovariantPolyClass( ScalaPackageClass, nme.BYNAME_PARAM_CLASS_NAME, tparam => AnyClass.typeConstructor); - TraitClass = getClass("scala._trait_"); + //TraitClass = getClass("scala._trait_"); TupleClass = new Array(MaxTupleArity + 1); for (val i <- List.range(1, MaxTupleArity + 1)) TupleClass(i) = getClass("scala.Tuple" + i); diff --git a/src/compiler/scala/tools/nsc/symtab/Flags.scala b/src/compiler/scala/tools/nsc/symtab/Flags.scala index 2627640d2e..39563cab29 100644 --- a/src/compiler/scala/tools/nsc/symtab/Flags.scala +++ b/src/compiler/scala/tools/nsc/symtab/Flags.scala @@ -43,8 +43,8 @@ object Flags { final val STATIC = 0x00800000; // static field, method or class final val CASEACCESSOR = 0x01000000; // symbol is a case parameter (or its accessor) - final val TRAIT = 0x02000000; // symbol is a trait - final val BRIDGE = 0x04000000; // function is a bridge method. Set by Erasure + final val MIXIN = 0x02000000; // symbol is a mixin class + final val BRIDGE = 0x04000000; // function is a bridge method. Set by Erasure final val ACCESSOR = 0x08000000; // a value or variable accessor final val SUPERACCESSOR = 0x10000000; // a super accessor @@ -100,7 +100,7 @@ object Flags { MODULE | PACKAGE | FINAL | JAVA; final val ExplicitFlags = // these modifiers can be set explicitly in source programs. - PRIVATE | PROTECTED | ABSTRACT | FINAL | SEALED | OVERRIDE | CASE | IMPLICIT | ABSOVERRIDE; + PRIVATE | PROTECTED | ABSTRACT | MIXIN | FINAL | SEALED | OVERRIDE | CASE | IMPLICIT | ABSOVERRIDE; final val PrintableFlags = // these modifiers appear in TreePrinter output. (ExplicitFlags | LOCAL | SYNTHETIC | STABLE | CASEACCESSOR | ACCESSOR | @@ -116,17 +116,9 @@ object Flags { /** Module flags inherited by their module-class */ final val ModuleToClassFlags = AccessFlags | PACKAGE | CASE; - def flagsToString(flags: long, suffixes: List[Pair[long, String]]): String = - (for (val i <- List.range(0, 63)) yield { - var s = flagToString(flags & (1L << i)); - suffixes.find(._1.==(i)) match { - case Some(Pair(i, suffix)) => s = s + "[" + suffix + "]" - case None => - } - s - }).filter("" !=).mkString("", " ", ""); - - def flagsToString(flags: long): String = flagsToString(flags, List()); + def flagsToString(flags: long): String = + (for (val i <- List.range(0, 63)) yield flagToString(flags & (1L << i))) + .filter("" !=).mkString("", " ", ""); private def flagToString(flag: long): String = { if (flag == LABEL) "<label>" @@ -153,7 +145,7 @@ object Flags { case DEFERRED => "<deferred>" case METHOD => "<method>" - case TRAIT => "<trait>" + case MIXIN => "mixin" case MODULE => "<module>" case MUTABLE => "<mutable>" diff --git a/src/compiler/scala/tools/nsc/symtab/StdNames.scala b/src/compiler/scala/tools/nsc/symtab/StdNames.scala index d0bf3da3ac..a07933af4f 100644 --- a/src/compiler/scala/tools/nsc/symtab/StdNames.scala +++ b/src/compiler/scala/tools/nsc/symtab/StdNames.scala @@ -28,6 +28,7 @@ import scala.tools.nsc.util.NameTransformer; val IMPLICITkw = newTermName("implicit"); val IMPORTkw = newTermName("import"); val MATCHkw = newTermName("match"); + val MIXINkw = newTermName("mixin"); val NEWkw = newTermName("new"); val NULLkw = newTermName("null"); val OBJECTkw = newTermName("object"); diff --git a/src/compiler/scala/tools/nsc/symtab/Symbols.scala b/src/compiler/scala/tools/nsc/symtab/Symbols.scala index f4d2bc38a1..2d7966add0 100644 --- a/src/compiler/scala/tools/nsc/symtab/Symbols.scala +++ b/src/compiler/scala/tools/nsc/symtab/Symbols.scala @@ -57,7 +57,7 @@ import Flags._; var attributes: List[AttrInfo] = List(); - var privateWithin: Symbol = null; + var privateWithin: Symbol = NoSymbol; // Creators ------------------------------------------------------------------- @@ -156,7 +156,7 @@ import Flags._; final def isThisSym = isTerm && name == nme.this_; final def isThisSkolem = isTerm && deSkolemize != this; final def isError = hasFlag(IS_ERROR); - final def isTrait = isClass & hasFlag(TRAIT); + final def isMixin = isClass & hasFlag(MIXIN); final def isAliasType = isType && !isClass && !hasFlag(DEFERRED); final def isAbstractType = isType && !isClass && hasFlag(DEFERRED); final def isTypeParameterOrSkolem = isType && hasFlag(PARAM); @@ -176,20 +176,19 @@ import Flags._; final def isStable = isTerm && !hasFlag(MUTABLE) && (!hasFlag(METHOD | BYNAMEPARAM) || hasFlag(STABLE)); - /** Does this symbol denote the primary constructor - * of its enclosing class or trait? */ + /** Does this symbol denote the primary constructor of its enclosing class? */ final def isPrimaryConstructor = isConstructor && owner.primaryConstructor == this; - /** Is this symbol an implementation class for a trait ? */ + /** Is this symbol an implementation class for a mixin? */ final def isImplClass: boolean = isClass && hasFlag(IMPLCLASS); final def needsImplClass: boolean = - isTrait && (!hasFlag(INTERFACE) || hasFlag(lateINTERFACE)) && !isImplClass; + isMixin && (!hasFlag(INTERFACE) || hasFlag(lateINTERFACE)) && !isImplClass; final def isImplOnly: boolean = ( hasFlag(PRIVATE) || - (owner.isImplClass || owner.isTrait) && + (owner.isImplClass || owner.isMixin) && (hasFlag(notPRIVATE | LIFTED) && !hasFlag(ACCESSOR | SUPERACCESSOR) || isConstructor) ); @@ -512,7 +511,7 @@ import Flags._; /** The primary constructor of a class */ def primaryConstructor: Symbol = { - val c = info.decl(if (isTrait || isImplClass) nme.MIXIN_CONSTRUCTOR else nme.CONSTRUCTOR); + val c = info.decl(if (isMixin || isImplClass) nme.MIXIN_CONSTRUCTOR else nme.CONSTRUCTOR); if (c hasFlag OVERLOADED) c.alternatives.head else c } @@ -686,8 +685,7 @@ import Flags._; /** String representation of symbol's definition key word */ final def keyString: String = - if (isTrait) - if (hasFlag(JAVA)) "interface" else "trait" + if (isMixin && hasFlag(JAVA)) "interface" else if (isClass) "class" else if (isType && !hasFlag(PARAM)) "type" else if (isVariable) "var" @@ -704,7 +702,6 @@ import Flags._; else if (isAnonymousClass) "<template>" else if (isRefinementClass) "" else if (isModuleClass) "singleton class" - else if (isTrait) "trait" else if (isClass) "class" else if (isType) "type" else if (isVariable) "variable" @@ -754,10 +751,10 @@ import Flags._; /** String representation of symbol's definition following its name */ final def infoString(tp: Type): String = { def typeParamsString: String = tp match { - case PolyType(tparams, _) if (tparams.length != 0) => - (tparams map (.defString)).mkString("[", ",", "]") - case _ => - "" + case PolyType(tparams, _) if (tparams.length != 0) => + (tparams map (.defString)).mkString("[", ",", "]") + case _ => + "" } if (isClass) typeParamsString + " extends " + tp.resultType diff --git a/src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala b/src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala index 6b633f389f..e5803d18e5 100644 --- a/src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala +++ b/src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala @@ -392,7 +392,7 @@ abstract class ClassfileParser { if ((flags & JAVA_ACC_FINAL) != 0) res = res | FINAL; if ((flags & JAVA_ACC_INTERFACE) != 0) - res = res | TRAIT | INTERFACE | ABSTRACT; + res = res | MIXIN | INTERFACE | ABSTRACT; if ((flags & JAVA_ACC_SYNTHETIC) != 0) res = res | SYNTHETIC; if ((flags & JAVA_ACC_STATIC) != 0) diff --git a/src/compiler/scala/tools/nsc/transform/AddInterfaces.scala b/src/compiler/scala/tools/nsc/transform/AddInterfaces.scala index 016de25857..8e87e85200 100644 --- a/src/compiler/scala/tools/nsc/transform/AddInterfaces.scala +++ b/src/compiler/scala/tools/nsc/transform/AddInterfaces.scala @@ -84,9 +84,9 @@ abstract class AddInterfaces extends InfoTransform { override def complete(sym: Symbol): unit = { def implType(tp: Type): Type = tp match { case ClassInfoType(parents, decls, _) => - //ClassInfoType(traitToImplClass(parents) ::: List(iface.tpe), implDecls(sym, decls), sym) + //ClassInfoType(mixinToImplClass(parents) ::: List(iface.tpe), implDecls(sym, decls), sym) ClassInfoType( - ObjectClass.tpe :: (parents.tail map traitToImplClass) ::: List(iface.tpe), + ObjectClass.tpe :: (parents.tail map mixinToImplClass) ::: List(iface.tpe), implDecls(sym, decls), sym) case PolyType(tparams, restpe) => @@ -98,14 +98,14 @@ abstract class AddInterfaces extends InfoTransform { override def load(clazz: Symbol): unit = complete(clazz) } - private def traitToImplClass(tp: Type): Type = tp match { + private def mixinToImplClass(tp: Type): Type = tp match { case TypeRef(pre, sym, args) if (sym.needsImplClass) => typeRef(pre, implClass(sym), args) case _ => tp } - def transformTraitInfo(tp: Type): Type = tp match { + def transformMixinInfo(tp: Type): Type = tp match { case ClassInfoType(parents, decls, clazz) => if (clazz.needsImplClass) { clazz setFlag lateINTERFACE; @@ -114,10 +114,10 @@ abstract class AddInterfaces extends InfoTransform { val parents1 = if (parents.isEmpty) List() else { - assert(!parents.head.symbol.isTrait || clazz == RepeatedParamClass, clazz); + assert(!parents.head.symbol.isMixin || clazz == RepeatedParamClass, clazz); if (clazz hasFlag INTERFACE) erasedTypeRef(ObjectClass) :: parents.tail else if (clazz.isImplClass || clazz == ArrayClass) parents - else parents map traitToImplClass + else parents map mixinToImplClass } val decls1 = if (clazz hasFlag INTERFACE) new Scope(decls.toList filter isInterfaceMember) else decls; @@ -186,7 +186,7 @@ abstract class AddInterfaces extends InfoTransform { buf.toList } - protected val traitTransformer = new Transformer { + protected val mixinTransformer = new Transformer { override def transformStats(stats: List[Tree], exprOwner: Symbol): List[Tree] = (super.transformStats(stats, exprOwner) ::: super.transformStats(implClassDefs(stats), exprOwner)); diff --git a/src/compiler/scala/tools/nsc/transform/Erasure.scala b/src/compiler/scala/tools/nsc/transform/Erasure.scala index 8971d5787b..3555bee62b 100644 --- a/src/compiler/scala/tools/nsc/transform/Erasure.scala +++ b/src/compiler/scala/tools/nsc/transform/Erasure.scala @@ -122,7 +122,7 @@ abstract class Erasure extends AddInterfaces with typechecker.Analyzer { } else erasure(tp) } else - transformTraitInfo(erasure(tp)); + transformMixinInfo(erasure(tp)); // -------- boxing/unboxing -------------------------------------------------------- @@ -498,7 +498,7 @@ abstract class Erasure extends AddInterfaces with typechecker.Analyzer { */ def addBridges(stats: List[Tree], base: Symbol): List[Tree] = - if (base.isTrait) stats + if (base.isMixin) stats else { val bridges = bridgeDefs(base); if (bridges.isEmpty) stats else stats ::: bridges @@ -571,7 +571,7 @@ abstract class Erasure extends AddInterfaces with typechecker.Analyzer { override def transform(tree: Tree): Tree = { val tree1 = preTransformer.transform(tree); atPhase(phase.next) { - val tree2 = traitTransformer.transform(tree1); + val tree2 = mixinTransformer.transform(tree1); if (settings.debug.value) log("tree after addinterfaces: \n" + tree2); newTyper(startContext.make( unit, tree, startContext.owner, startContext.scope, startContext.imports)) diff --git a/src/compiler/scala/tools/nsc/transform/ExplicitOuter.scala b/src/compiler/scala/tools/nsc/transform/ExplicitOuter.scala index 466ed4674c..45629ec4e0 100644 --- a/src/compiler/scala/tools/nsc/transform/ExplicitOuter.scala +++ b/src/compiler/scala/tools/nsc/transform/ExplicitOuter.scala @@ -33,13 +33,13 @@ abstract class ExplicitOuter extends InfoTransform { /** The type transformation method: * 1. Add an outer paramter to the formal parameters of a constructor or mixin constructor * in a non-static class; - * 2. Add a mixin constructor $init$ to all traits except interfaces + * 2. Add a mixin constructor $init$ to all mixins except interfaces * Leave all other types unchanged. */ def transformInfo(sym: Symbol, tp: Type): Type = tp match { case MethodType(formals, restpe) => //todo: needed? - if (sym.owner.isTrait && (sym hasFlag PROTECTED)) sym setFlag notPROTECTED; + if (sym.owner.isMixin && (sym hasFlag PROTECTED)) sym setFlag notPROTECTED; if (sym.isConstructor && !isStatic(sym.owner)) MethodType(formals ::: List(outerClass(sym.owner).toInterface.thisType), restpe) else tp; @@ -49,7 +49,7 @@ abstract class ExplicitOuter extends InfoTransform { if (!isStatic(clazz)) { decls1 = new Scope(decls1.toList); val outerAcc = clazz.newMethod(clazz.pos, nme.OUTER); - if ((clazz hasFlag TRAIT) || (decls.toList exists (.isClass))) + if (clazz.isMixin || (decls.toList exists (.isClass))) outerAcc.expandName(clazz); decls1 enter ( outerAcc setFlag (PARAMACCESSOR | ACCESSOR | STABLE) @@ -58,7 +58,7 @@ abstract class ExplicitOuter extends InfoTransform { setFlag (LOCAL | PRIVATE | PARAMACCESSOR | (outerAcc getFlag EXPANDEDNAME)) setInfo outerClass(clazz).thisType); } - if (clazz.isTrait) { + if (clazz.isMixin) { decls1 = new Scope(decls1.toList); decls1 enter makeMixinConstructor(clazz); } @@ -201,19 +201,19 @@ abstract class ExplicitOuter extends InfoTransform { * to `tree'. `tree' which is assumed to be the body of a constructor of class `clazz'. */ def addMixinConstructorCalls(tree: Tree, clazz: Symbol): Tree = { - def mixinConstructorCall(mixin: Symbol): Tree = + def mixinConstructorCall(mixinClass: Symbol): Tree = atPos(tree.pos) { Apply( localTyper.typedOperator { - Select(Super(clazz, mixin.name), mixin.primaryConstructor) + Select(Super(clazz, mixinClass.name), mixinClass.primaryConstructor) }, List()) setType UnitClass.tpe; // don't type this with typed(...), // as constructor arguments might be missing } val mixinConstructorCalls = - for (val mixin <- clazz.info.parents.tail; - !(mixin.symbol hasFlag INTERFACE) && mixin.symbol != ScalaObjectClass) yield - mixinConstructorCall(mixin.symbol); + for (val mixinClass <- clazz.info.parents.tail; + !(mixinClass.symbol hasFlag INTERFACE) && mixinClass.symbol != ScalaObjectClass) yield + mixinConstructorCall(mixinClass.symbol); tree match { case Block(supercall :: stats, expr) => assert(supercall match { @@ -239,7 +239,7 @@ abstract class ExplicitOuter extends InfoTransform { if (!(currentOwner hasFlag INTERFACE)) { if (!isStatic(currentOwner)) decls1 = decls1 ::: outerDefs(currentOwner); // (1) - if (currentOwner.isTrait) + if (currentOwner.isMixin) decls1 = decls1 ::: List(mixinConstructorDef(currentOwner)) // (2) } localTyper = savedLocalTyper; @@ -295,7 +295,7 @@ abstract class ExplicitOuter extends InfoTransform { val tree1 = super.transform(tree); tree1 match { case DefDef(_, _, _, _, _, _) => - if (sym.owner.isTrait && (sym hasFlag (ACCESSOR | SUPERACCESSOR))) + if (sym.owner.isMixin && (sym hasFlag (ACCESSOR | SUPERACCESSOR))) sym.makeNotPrivate(sym.owner); //(2) tree1 case Select(qual, name) => diff --git a/src/compiler/scala/tools/nsc/transform/Mixin.scala b/src/compiler/scala/tools/nsc/transform/Mixin.scala index bcdd9b09b8..580365c713 100644 --- a/src/compiler/scala/tools/nsc/transform/Mixin.scala +++ b/src/compiler/scala/tools/nsc/transform/Mixin.scala @@ -101,17 +101,17 @@ abstract class Mixin extends InfoTransform { def addMixedinMembers(clazz: Symbol): unit = { if (!(clazz hasFlag MIXEDIN) && (clazz != ObjectClass)) { - assert(!clazz.isTrait, clazz); + assert(!clazz.isMixin, clazz); clazz setFlag MIXEDIN; assert(!clazz.info.parents.isEmpty, clazz); val superclazz = clazz.info.parents.head.symbol; addMixedinMembers(superclazz); //System.out.println("adding members of " + clazz.info.baseClasses.tail.takeWhile(superclazz !=) + " to " + clazz);//DEBUG val mixins = clazz.info.baseClasses.tail.takeWhile(superclazz !=); - def mixinMembers(mixin: Symbol, mmap: Symbol => Symbol): unit = { - if (mixin.isImplClass) { - addLateInterfaceMembers(mixin.toInterface); - for (val member <- mixin.info.decls.toList) { + def mixinMembers(mixinClass: Symbol, mmap: Symbol => Symbol): unit = { + if (mixinClass.isImplClass) { + addLateInterfaceMembers(mixinClass.toInterface); + for (val member <- mixinClass.info.decls.toList) { //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) && (clazz.info.findMember(member.name, 0, 0).alternatives contains mmap(member))) { @@ -121,12 +121,12 @@ abstract class Mixin extends InfoTransform { member1.asInstanceOf[TermSymbol] setAlias member; } } - } else if (mixin.hasFlag(lateINTERFACE)) { - addLateInterfaceMembers(mixin); - val impl = implClass(mixin); - //System.out.println("late impl " + mixin + " " + impl);//DEBUG - if (!(mixins contains impl)) mixinMembers(impl, .overriddenSymbol(mixin)); - for (val member <- mixin.info.decls.toList) { + } else if (mixinClass.hasFlag(lateINTERFACE)) { + addLateInterfaceMembers(mixinClass); + val impl = implClass(mixinClass); + //System.out.println("late impl " + mixinClass + " " + impl);//DEBUG + if (!(mixins contains impl)) mixinMembers(impl, .overriddenSymbol(mixinClass)); + for (val member <- mixinClass.info.decls.toList) { if (member hasFlag ACCESSOR) { val member1 = addMember( clazz, @@ -146,7 +146,7 @@ abstract class Mixin extends InfoTransform { } else if (member hasFlag SUPERACCESSOR) { val member1 = addMember(clazz, member.cloneSymbol(clazz)) setPos clazz.pos; assert(member1.alias != NoSymbol, member1); - val alias1 = rebindSuper(clazz, member.alias, mixin); + val alias1 = rebindSuper(clazz, member.alias, mixinClass); member1.asInstanceOf[TermSymbol] setAlias alias1; } else if (member.isMethod && member.isModule && !(member hasFlag (LIFTED | BRIDGE))) { addMember(clazz, member.cloneSymbol(clazz)) @@ -156,8 +156,8 @@ abstract class Mixin extends InfoTransform { } } } -// for (val mixin <- mixins) if (mixin.hasFlag(lateINTERFACE)) addLateInterfaceMembers(mixin); - for (val mixin <- mixins) mixinMembers(mixin, identity); +// for (val mixinClass <- mixins) if (mixinClass.hasFlag(lateINTERFACE)) addLateInterfaceMembers(mixinClass); + for (val mixinClass <- mixins) mixinMembers(mixinClass, identity); if (settings.debug.value) log("new defs of " + clazz + " = " + clazz.info.decls); } } @@ -216,7 +216,7 @@ abstract class Mixin extends InfoTransform { case Template(parents, body) => localTyper = erasure.newTyper(rootContext.make(tree, currentOwner)); atPhase(phase.next)(currentOwner.owner.info);//needed? - if (!currentOwner.isTrait) addMixedinMembers(currentOwner) + if (!currentOwner.isMixin) addMixedinMembers(currentOwner) else if (currentOwner hasFlag lateINTERFACE) addLateInterfaceMembers(currentOwner); tree case DefDef(mods, name, tparams, List(vparams), tpt, rhs) if currentOwner.isImplClass => @@ -300,7 +300,7 @@ abstract class Mixin extends InfoTransform { if (sym hasFlag MIXEDIN) { if (clazz hasFlag lateINTERFACE) { addDefDef(sym, vparamss => EmptyTree) - } else if (!clazz.isTrait) { + } else if (!clazz.isMixin) { if (sym hasFlag ACCESSOR) { addDefDef(sym, vparams => { val accessedRef = sym.tpe match { @@ -325,7 +325,7 @@ abstract class Mixin extends InfoTransform { } } val stats1 = add(stats, newDefs.toList); - if (clazz.isTrait) stats1 else stats1 map completeSuperAccessor; + if (clazz.isMixin) stats1 else stats1 map completeSuperAccessor; } private def postTransform(tree: Tree): Tree = { diff --git a/src/compiler/scala/tools/nsc/transform/TailCalls.scala b/src/compiler/scala/tools/nsc/transform/TailCalls.scala index c6fa574228..c2681b2d3b 100644 --- a/src/compiler/scala/tools/nsc/transform/TailCalls.scala +++ b/src/compiler/scala/tools/nsc/transform/TailCalls.scala @@ -228,7 +228,7 @@ abstract class TailCalls extends Transform else copy.Apply(tree, fun, transformTrees(args, mkContext(ctx, false))); - case Super(qual, mixin) => + case Super(qual, mix) => tree; case This(qual) => tree; diff --git a/src/compiler/scala/tools/nsc/typechecker/Namers.scala b/src/compiler/scala/tools/nsc/typechecker/Namers.scala index 6f9df75223..ce53aa40c2 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Namers.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Namers.scala @@ -40,7 +40,13 @@ trait Namers: Analyzer { class Namer(val context: Context) { - def setPrivate(sym: Symbol, mods: Modifiers): Symbol = sym; + val typer = newTyper(context); + + def setPrivate(sym: Symbol, mods: Modifiers): Symbol = { + if (!mods.privateWithin.isEmpty) + sym.privateWithin = typer.qualifyingClassContext(EmptyTree, mods.privateWithin).owner; + sym + } def updatePosFlags(sym: Symbol, pos: int, flags: int): Symbol = { if (settings.debug.value) log("overwriting " + sym); @@ -271,8 +277,6 @@ trait Namers: Analyzer { // --- Lazy Type Assignment -------------------------------------------------- - val typer = newTyper(context); - def typeCompleter(tree: Tree) = new TypeCompleter(tree) { override def complete(sym: Symbol): unit = { if (settings.debug.value) log("defining " + sym); @@ -499,7 +503,7 @@ trait Namers: Analyzer { * - `abstract' modifier only for classes * - `override' modifier never for classes * - `def' modifier never for parameters of case classes - * - declarations only in traits or abstract classes + * - declarations only in mixins or abstract classes */ def validate(sym: Symbol): unit = { def checkNoConflict(flag1: int, flag2: int): unit = @@ -512,13 +516,15 @@ trait Namers: Analyzer { Flags.flagsToString(flag1) + " and " + Flags.flagsToString(flag2)); if (sym.hasFlag(IMPLICIT) && !sym.isTerm) context.error(sym.pos, "`implicit' modifier can be used only for values, variables and methods"); + if (sym.hasFlag(MIXIN) && !sym.isClass) + context.error(sym.pos, "`mixin' modifier can be used only for classes"); if (sym.hasFlag(ABSTRACT) && !sym.isClass) context.error(sym.pos, "`abstract' modifier can be used only for classes; " + "\nit should be omitted for abstract members"); if (sym.hasFlag(OVERRIDE | ABSOVERRIDE) && sym.isClass) context.error(sym.pos, "`override' modifier not allowed for classes"); - if (sym.hasFlag(ABSOVERRIDE) && !sym.owner.isTrait) - context.error(sym.pos, "`abstract override' modifier only allowed for members of traits"); + if (sym.hasFlag(ABSOVERRIDE) && !sym.owner.isMixin) + context.error(sym.pos, "`abstract override' modifier only allowed for members of mixin classes"); if (sym.info.symbol == FunctionClass(0) && sym.isValueParameter && sym.owner.isClass && sym.owner.hasFlag(CASE)) context.error(sym.pos, "pass-by-name arguments not allowed for case class parameters"); diff --git a/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala b/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala index f6552d9fc5..d69b6d540c 100644 --- a/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala +++ b/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala @@ -226,11 +226,11 @@ abstract class RefChecks extends InfoTransform { } */ // 2. Check that only abstract classes have deferred members - if (clazz.isClass && !clazz.isTrait) { - def abstractClassError(mustBeTrait: boolean, msg: String): unit = { + if (clazz.isClass && !clazz.isMixin) { + def abstractClassError(mustBeMixin: boolean, msg: String): unit = { unit.error(clazz.pos, (if (clazz.isAnonymousClass || clazz.isModuleClass) "object creation impossible" - else if (mustBeTrait) clazz.toString() + " needs to be a trait" + else if (mustBeMixin) clazz.toString() + " needs to be a mixin" else clazz.toString() + " needs to be abstract") + ", since " + msg); clazz.setFlag(ABSTRACT); } @@ -265,7 +265,7 @@ abstract class RefChecks extends InfoTransform { // Basetype Checking -------------------------------------------------------- /** 1. Check that later type instances in the base-type sequence - * are subtypes of earlier type instances of the same trait. + * are subtypes of earlier type instances of the same mixin. * 2. Check that case classes do not inherit from case classes. * 3. Check that at most one base type is a case-class. */ @@ -460,12 +460,12 @@ abstract class RefChecks extends InfoTransform { val ddef = atPhase(phase.next) { localTyper.typed { - if (sym.owner.isTrait) newModuleAccessDcl(sym) + if (sym.owner.isMixin) newModuleAccessDcl(sym) else newModuleAccessDef(sym, vdef.symbol) } } - if (sym.owner.isTrait) transformTrees(List(cdef, ddef)) + if (sym.owner.isMixin) transformTrees(List(cdef, ddef)) else transformTrees(List(cdef, vdef, ddef)) } @@ -553,16 +553,16 @@ abstract class RefChecks extends InfoTransform { if (sym.isSourceMethod && sym.hasFlag(CASE)) result = toConstructor else qual match { - case Super(qualifier, mixin) => + case Super(qualifier, mix) => val base = currentOwner.enclClass; if (sym hasFlag DEFERRED) { val member = sym.overridingSymbol(base);//??? - if (mixin != nme.EMPTY.toTypeName || member == NoSymbol || + if (mix != nme.EMPTY.toTypeName || member == NoSymbol || !((member hasFlag ABSOVERRIDE) && member.isIncompleteIn(base))) unit.error(tree.pos, "symbol accessed from super may not be abstract"); } //System.out.println("super: " + tree + " in " + base);//DEBUG - if (base.isTrait && sym.isTerm && mixin == nme.EMPTY.toTypeName) { + if (base.isMixin && sym.isTerm && mix == nme.EMPTY.toTypeName) { val superAccName = nme.superName(sym.name); val superAcc = base.info.decl(superAccName) suchThat (.alias.==(sym)); assert(superAcc != NoSymbol, "" + sym + " " + base + " " + superAccName);//debug diff --git a/src/compiler/scala/tools/nsc/typechecker/SuperAccessors.scala b/src/compiler/scala/tools/nsc/typechecker/SuperAccessors.scala index 4eb38f349b..7e0562d633 100644 --- a/src/compiler/scala/tools/nsc/typechecker/SuperAccessors.scala +++ b/src/compiler/scala/tools/nsc/typechecker/SuperAccessors.scala @@ -46,7 +46,7 @@ abstract class SuperAccessors extends transform.Transform { case Select(sup @ Super(_, mix), name) => val clazz = sup.symbol; if (tree.isTerm && mix == nme.EMPTY.toTypeName && - (clazz.isTrait || clazz != currentOwner.enclClass || !validCurrentOwner)) { + (clazz.isMixin || clazz != currentOwner.enclClass || !validCurrentOwner)) { val supername = nme.superName(tree.symbol.name); var superAcc = clazz.info.decl(supername).suchThat(.alias.==(tree.symbol)); if (superAcc == NoSymbol) { diff --git a/src/compiler/scala/tools/nsc/typechecker/Typers.scala b/src/compiler/scala/tools/nsc/typechecker/Typers.scala index 0814defc9e..551fb0bd6c 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Typers.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Typers.scala @@ -3,7 +3,7 @@ * @author Martin Odersky */ // $Id$ -//todo: rewrite or disallow new T where T is a trait (currently: <init> not a member of T) +//todo: rewrite or disallow new T where T is a mixin (currently: <init> not a member of T) package scala.tools.nsc.typechecker import symtab.Flags._ @@ -237,6 +237,20 @@ import scala.collection.mutable.{HashMap, ListBuffer} }) } + /** The qualifying class of a this or super with prefix `qual' */ + def qualifyingClassContext(tree: Tree, qual: Name): Context = { + if (qual.isEmpty) { + if (context.enclClass.owner.isPackageClass) + error(tree.pos, ""+tree+" can be used only in a class, object, or template") + context.enclClass + } else { + var c = context.enclClass + while (c != NoContext && c.owner.name != qual) c = c.outer.enclClass + if (c == NoContext) error(tree.pos, ""+qual+" is not an enclosing class") + c + } + } + /** Post-process an identifier or selection node, performing the following: * (1) Check that non-function pattern expressions are stable * (2) Check that packages and static modules are not used as values @@ -469,8 +483,8 @@ import scala.collection.mutable.{HashMap, ListBuffer} else { var supertpt = typedTypeConstructor(templ.parents.head) var mixins = templ.parents.tail map typedType - // If first parent is trait, make it first mixin and add its superclass as first parent - while (supertpt.tpe.symbol != null && supertpt.tpe.symbol.initialize.isTrait) { + // If first parent is a mixin class, make it first mixin and add its superclass as first parent + while (supertpt.tpe.symbol != null && supertpt.tpe.symbol.initialize.isMixin) { mixins = typedType(supertpt) :: mixins supertpt = TypeTree(supertpt.tpe.parents.head) setPos supertpt.pos } @@ -501,7 +515,7 @@ import scala.collection.mutable.{HashMap, ListBuffer} /** Check that * - all parents are class types, - * - first parent cluss is not a trait; following classes are traits, + * - first parent cluss is not a mixin; following classes are mixins, * - final classes are not inherited, * - sealed classes are only inherited by classes which are * nested within definition of base class, or that occur within same @@ -519,8 +533,8 @@ import scala.collection.mutable.{HashMap, ListBuffer} val psym = parent.tpe.symbol.initialize if (!psym.isClass) error(parent.pos, "class type expected") - else if (!isFirst && !psym.isTrait) - error(parent.pos, ""+psym+" is not a trait; cannot be used as mixin") + else if (!isFirst && !psym.isMixin) + error(parent.pos, ""+psym+" is not declared to be a mixin class") else if (psym.hasFlag(FINAL)) error(parent.pos, "illegal inheritance from final class") else if (psym.isSealed && !phase.erasedTypes) { @@ -944,20 +958,6 @@ import scala.collection.mutable.{HashMap, ListBuffer} errorTree(tree, ""+fun+" does not take parameters") } - /** The qualifying class of a this or super with prefix `qual' */ - def qualifyingClassContext(qual: Name): Context = { - if (qual == nme.EMPTY.toTypeName) { - if (context.enclClass.owner.isPackageClass) - error(tree.pos, ""+tree+" can be used only in a class, object, or template") - context.enclClass - } else { - var c = context.enclClass - while (c != NoContext && c.owner.name != qual) c = c.outer.enclClass - if (c == NoContext) error(tree.pos, ""+qual+" is not an enclosing class") - c - } - } - /** Attribute a selection where `tree' is `qual.name'. * `qual' is already attributed. */ @@ -1261,7 +1261,7 @@ import scala.collection.mutable.{HashMap, ListBuffer} .setPos(tpt1.pos) .setType(appliedType(tpt1.tpe, context.undetparams map (.tpe))) } - if (tpt1.tpe.symbol.isTrait) error(tree.pos, "traits cannot be instantiated") + if (tpt1.tpe.symbol.isMixin) error(tree.pos, "mixin classes cannot be instantiated") copy.New(tree, tpt1).setType(tpt1.tpe) case Typed(expr, tpt @ Ident(name)) if (name == nme.WILDCARD_STAR.toTypeName) => @@ -1314,13 +1314,13 @@ import scala.collection.mutable.{HashMap, ListBuffer} if (tree.symbol != NoSymbol) { Pair(tree.symbol, tree.symbol.thisType) } else { - val clazzContext = qualifyingClassContext(qual) + val clazzContext = qualifyingClassContext(tree, qual) Pair(clazzContext.owner, clazzContext.prefix) } if (clazz == NoSymbol) setError(tree) else { val owntype = - if (mix == nme.EMPTY.toTypeName) + if (mix.isEmpty) if ((mode & SUPERCONSTRmode) != 0) clazz.info.parents.head else intersectionType(clazz.info.parents) else { @@ -1339,7 +1339,7 @@ import scala.collection.mutable.{HashMap, ListBuffer} if (tree.symbol != NoSymbol) { Pair(tree.symbol, tree.symbol.thisType) } else { - val clazzContext = qualifyingClassContext(qual) + val clazzContext = qualifyingClassContext(tree, qual) Pair(clazzContext.owner, clazzContext.prefix) } if (clazz == NoSymbol) setError(tree) diff --git a/src/compiler/scala/tools/nsc/util/Set.scala b/src/compiler/scala/tools/nsc/util/Set.scala index dab7898e39..cd6d8ceaae 100644 --- a/src/compiler/scala/tools/nsc/util/Set.scala +++ b/src/compiler/scala/tools/nsc/util/Set.scala @@ -5,7 +5,7 @@ // $Id$ package scala.tools.nsc.util; -/** A common trait for lightweight sets. +/** A common class for lightweight sets. */ abstract class Set[T <: AnyRef] { diff --git a/src/library/scala/NotDefinedError.scala b/src/library/scala/NotDefinedError.scala new file mode 100755 index 0000000000..9c7d7695a8 --- /dev/null +++ b/src/library/scala/NotDefinedError.scala @@ -0,0 +1,12 @@ +/* __ *\ +** ________ ___ / / ___ Scala API ** +** / __/ __// _ | / / / _ | (c) 2002, LAMP/EPFL ** +** __\ \/ /__/ __ |/ /__/ __ | ** +** /____/\___/_/ |_/____/_/ | | ** +** |/ ** +** ** +** $Id: MatchError.scala 5390 2005-12-19 13:49:03Z dubochet $ +\* */ +package scala; + +final class NotDefinedError(msg: String) extends Error("not defined: " + msg); diff --git a/src/library/scala/_mixin_.scala b/src/library/scala/_mixin_.scala new file mode 100644 index 0000000000..5d80167992 --- /dev/null +++ b/src/library/scala/_mixin_.scala @@ -0,0 +1,18 @@ +/* __ *\ +** ________ ___ / / ___ Scala API ** +** / __/ __// _ | / / / _ | (c) 2002-2005, LAMP/EPFL ** +** __\ \/ /__/ __ |/ /__/ __ | ** +** /____/\___/_/ |_/____/_/ | | ** +** |/ ** +*/ + +// $Id:_trait_.scala 5359 2005-12-16 16:33:49 +0100 (Fri, 16 Dec 2005) dubochet $ + +package scala; + +/** Temporary class. + * When this appears in the attribute list of an abstract class, the class + * is assumed to be a mixin. Used to ensure that code that compiles under + * (old) <code>scalac</code> can also compile under <code>nsc</code>. + */ +class _mixin_ extends Attribute {} |