diff options
author | Adriaan Moors <adriaan.moors@typesafe.com> | 2014-01-13 11:02:27 -0800 |
---|---|---|
committer | Adriaan Moors <adriaan.moors@typesafe.com> | 2014-01-13 11:02:27 -0800 |
commit | 0a96a20931d0aa5b2cd0da0758c507a9e2e805f6 (patch) | |
tree | ebfa7d375d3648c8d6e95855772941b348e936c6 /src/compiler | |
parent | 7fbc961c52aba7c5e5d98027dad541a24a7076ef (diff) | |
parent | a90f39cdb538ffccd4faca6aef57233bb690b4f0 (diff) | |
download | scala-0a96a20931d0aa5b2cd0da0758c507a9e2e805f6.tar.gz scala-0a96a20931d0aa5b2cd0da0758c507a9e2e805f6.tar.bz2 scala-0a96a20931d0aa5b2cd0da0758c507a9e2e805f6.zip |
Merge pull request #3247 from soc/SI-8058-enums
SI-8058 Better support for enum trees
Diffstat (limited to 'src/compiler')
5 files changed, 28 insertions, 12 deletions
diff --git a/src/compiler/scala/tools/nsc/backend/jvm/BCodeTypes.scala b/src/compiler/scala/tools/nsc/backend/jvm/BCodeTypes.scala index 5be5abd895..dd2d63ad17 100644 --- a/src/compiler/scala/tools/nsc/backend/jvm/BCodeTypes.scala +++ b/src/compiler/scala/tools/nsc/backend/jvm/BCodeTypes.scala @@ -835,6 +835,7 @@ abstract class BCodeTypes extends BCodeIdiomatic { if (sym.isBridge) ACC_BRIDGE | ACC_SYNTHETIC else 0, if (sym.isArtifact) ACC_SYNTHETIC else 0, if (sym.isClass && !sym.isInterface) ACC_SUPER else 0, + if (sym.hasEnumFlag) ACC_ENUM else 0, if (sym.isVarargsMethod) ACC_VARARGS else 0, if (sym.hasFlag(symtab.Flags.SYNCHRONIZED)) ACC_SYNCHRONIZED else 0 ) diff --git a/src/compiler/scala/tools/nsc/backend/jvm/GenASM.scala b/src/compiler/scala/tools/nsc/backend/jvm/GenASM.scala index e92f8c2541..7e1a82a155 100644 --- a/src/compiler/scala/tools/nsc/backend/jvm/GenASM.scala +++ b/src/compiler/scala/tools/nsc/backend/jvm/GenASM.scala @@ -244,6 +244,7 @@ abstract class GenASM extends SubComponent with BytecodeWriters with GenJVMASM { if (sym.isBridge) ACC_BRIDGE | ACC_SYNTHETIC else 0, if (sym.isArtifact) ACC_SYNTHETIC else 0, if (sym.isClass && !sym.isInterface) ACC_SUPER else 0, + if (sym.hasEnumFlag) ACC_ENUM else 0, if (sym.isVarargsMethod) ACC_VARARGS else 0, if (sym.hasFlag(Flags.SYNCHRONIZED)) ACC_SYNCHRONIZED else 0 ) diff --git a/src/compiler/scala/tools/nsc/javac/JavaParsers.scala b/src/compiler/scala/tools/nsc/javac/JavaParsers.scala index 7932dd3459..9875d27047 100644 --- a/src/compiler/scala/tools/nsc/javac/JavaParsers.scala +++ b/src/compiler/scala/tools/nsc/javac/JavaParsers.scala @@ -792,7 +792,7 @@ trait JavaParsers extends ast.parser.ParsersCommon with JavaScanners { val superclazz = AppliedTypeTree(javaLangDot(tpnme.Enum), List(enumType)) addCompanionObject(consts ::: statics ::: predefs, atPos(pos) { - ClassDef(mods, name, List(), + ClassDef(mods | Flags.ENUM, name, List(), makeTemplate(superclazz :: interfaces, body)) }) } @@ -811,10 +811,7 @@ trait JavaParsers extends ast.parser.ParsersCommon with JavaScanners { skipAhead() accept(RBRACE) } - // The STABLE flag is to signal to namer that this was read from a - // java enum, and so should be given a Constant type (thereby making - // it usable in annotations.) - ValDef(Modifiers(Flags.STABLE | Flags.JAVA | Flags.STATIC), name.toTermName, enumType, blankExpr) + ValDef(Modifiers(Flags.ENUM | Flags.STABLE | Flags.JAVA | Flags.STATIC), name.toTermName, enumType, blankExpr) } } diff --git a/src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala b/src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala index 2b96961291..664645e53e 100644 --- a/src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala +++ b/src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala @@ -515,7 +515,7 @@ abstract class ClassfileParser { val info = readType() val sym = ownerForFlags(jflags).newValue(name.toTermName, NoPosition, sflags) - // Note: the info may be overrwritten later with a generic signature + // Note: the info may be overwritten later with a generic signature // parsed from SignatureATTR sym setInfo { if (jflags.isEnum) ConstantType(Constant(sym)) diff --git a/src/compiler/scala/tools/nsc/typechecker/Namers.scala b/src/compiler/scala/tools/nsc/typechecker/Namers.scala index 14695f5939..27e8698676 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Namers.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Namers.scala @@ -122,10 +122,31 @@ trait Namers extends MethodSynthesis { || (vd.mods.isPrivateLocal && !vd.mods.isCaseAccessor) || (vd.name startsWith nme.OUTER) || (context.unit.isJava) + || isEnumConstant(vd) ) + def noFinishGetterSetter(vd: ValDef) = ( (vd.mods.isPrivateLocal && !vd.mods.isLazy) // all lazy vals need accessors, even private[this] - || vd.symbol.isModuleVar) + || vd.symbol.isModuleVar + || isEnumConstant(vd)) + + /** Determines whether this field holds an enum constant. + * To qualify, the following conditions must be met: + * - The field's class has the ENUM flag set + * - The field's class extends java.lang.Enum + * - The field has the ENUM flag set + * - The field is static + * - The field is stable + */ + def isEnumConstant(vd: ValDef) = { + val ownerHasEnumFlag = + // Necessary to check because scalac puts Java's static members into the companion object + // while Scala's enum constants live directly in the class. + // We don't check for clazz.superClass == JavaEnumClass, because this causes a illegal + // cyclic reference error. See the commit message for details. + if (context.unit.isJava) owner.companionClass.hasEnumFlag else owner.hasEnumFlag + vd.mods.hasAllFlags(ENUM | STABLE | STATIC) && ownerHasEnumFlag + } def setPrivateWithin[T <: Symbol](tree: Tree, sym: T, mods: Modifiers): T = if (sym.isPrivateLocal || !mods.hasAccessBoundary) sym @@ -620,11 +641,7 @@ trait Namers extends MethodSynthesis { else enterGetterSetter(tree) - // When java enums are read from bytecode, they are known to have - // constant types by the jvm flag and assigned accordingly. When - // they are read from source, the java parser marks them with the - // STABLE flag, and now we receive that signal. - if (tree.symbol hasAllFlags STABLE | JAVA) + if (isEnumConstant(tree)) tree.symbol setInfo ConstantType(Constant(tree.symbol)) } |