diff options
Diffstat (limited to 'src/compiler/scala/tools/nsc/typechecker/Namers.scala')
-rw-r--r-- | src/compiler/scala/tools/nsc/typechecker/Namers.scala | 72 |
1 files changed, 34 insertions, 38 deletions
diff --git a/src/compiler/scala/tools/nsc/typechecker/Namers.scala b/src/compiler/scala/tools/nsc/typechecker/Namers.scala index 4ad81b60ae..8943ec810d 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Namers.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Namers.scala @@ -7,7 +7,6 @@ package scala.tools.nsc package typechecker import scala.collection.mutable -import scala.annotation.tailrec import symtab.Flags._ import scala.language.postfixOps import scala.reflect.internal.util.ListOfNil @@ -115,21 +114,14 @@ trait Namers extends MethodSynthesis { TypeSigError(tree, ex) alt } - // PRIVATE | LOCAL are fields generated for primary constructor arguments - // @PP: ...or fields declared as private[this]. PARAMACCESSOR marks constructor arguments. - // Neither gets accessors so the code is as far as I know still correct. - def noEnterGetterSetter(vd: ValDef) = !vd.mods.isLazy && ( - !owner.isClass - || (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 - || isEnumConstant(vd)) + // All lazy vals need accessors, including those owned by terms (e.g., in method) or private[this] in a class + def deriveAccessors(vd: ValDef) = vd.mods.isLazy || (owner.isClass && deriveAccessorsInClass(vd)) + + private def deriveAccessorsInClass(vd: ValDef) = + !vd.mods.isPrivateLocal && // note, private[this] lazy vals do get accessors -- see outer disjunction of deriveAccessors + !(vd.name startsWith nme.OUTER) && // outer accessors are added later, in explicitouter + !isEnumConstant(vd) // enums can only occur in classes, so only check here /** Determines whether this field holds an enum constant. * To qualify, the following conditions must be met: @@ -170,13 +162,9 @@ trait Namers extends MethodSynthesis { def updatePosFlags(sym: Symbol, pos: Position, flags: Long): Symbol = { debuglog("[overwrite] " + sym) val newFlags = (sym.flags & LOCKED) | flags - sym.rawInfo match { - case tr: TypeRef => - // !!! needed for: pos/t5954d; the uniques type cache will happily serve up the same TypeRef - // over this mutated symbol, and we witness a stale cache for `parents`. - tr.invalidateCaches() - case _ => - } + // !!! needed for: pos/t5954d; the uniques type cache will happily serve up the same TypeRef + // over this mutated symbol, and we witness a stale cache for `parents`. + invalidateCaches(sym.rawInfo, sym :: sym.moduleClass :: Nil) sym reset NoType setFlag newFlags setPos pos sym.moduleClass andAlso (updatePosFlags(_, pos, moduleClassFlags(flags))) @@ -655,14 +643,20 @@ trait Namers extends MethodSynthesis { } } - def enterValDef(tree: ValDef) { - if (noEnterGetterSetter(tree)) - assignAndEnterFinishedSymbol(tree) - else - enterGetterSetter(tree) + def enterValDef(tree: ValDef): Unit = { + val isScala = !context.unit.isJava + if (isScala) { + if (nme.isSetterName(tree.name)) ValOrVarWithSetterSuffixError(tree) + if (tree.mods.isPrivateLocal && tree.mods.isCaseAccessor) PrivateThisCaseClassParameterError(tree) + } - if (isEnumConstant(tree)) + if (isScala && deriveAccessors(tree)) enterGetterSetter(tree) + else assignAndEnterFinishedSymbol(tree) + + if (isEnumConstant(tree)) { tree.symbol setInfo ConstantType(Constant(tree.symbol)) + tree.symbol.owner.linkedClassOfClass addChild tree.symbol + } } def enterLazyVal(tree: ValDef, lazyAccessor: Symbol): TermSymbol = { @@ -1600,11 +1594,7 @@ trait Namers extends MethodSynthesis { import SymValidateErrors._ def fail(kind: SymValidateErrors.Value) = SymbolValidationError(sym, kind) - def checkWithDeferred(flag: Int) { - if (sym hasFlag flag) - AbstractMemberWithModiferError(sym, flag) - } - def checkNoConflict(flag1: Int, flag2: Int) { + def checkNoConflict(flag1: Int, flag2: Int) = { if (sym hasAllFlags flag1.toLong | flag2) IllegalModifierCombination(sym, flag1, flag2) } @@ -1643,6 +1633,10 @@ trait Namers extends MethodSynthesis { checkNoConflict(ABSTRACT, FINAL) if (sym.isDeferred) { + def checkWithDeferred(flag: Int) = { + if (sym hasFlag flag) + AbstractMemberWithModiferError(sym, flag) + } // Is this symbol type always allowed the deferred flag? def symbolAllowsDeferred = ( sym.isValueParameter @@ -1658,14 +1652,16 @@ trait Namers extends MethodSynthesis { ) if (sym hasAnnotation NativeAttr) sym resetFlag DEFERRED - else if (!symbolAllowsDeferred && ownerRequiresConcrete) - fail(AbstractVar) + else { + if (!symbolAllowsDeferred && ownerRequiresConcrete) fail(AbstractVar) - checkWithDeferred(PRIVATE) - checkWithDeferred(FINAL) + checkWithDeferred(PRIVATE) + checkWithDeferred(FINAL) + } } - checkNoConflict(FINAL, SEALED) + if (!sym.isJavaEnum) + checkNoConflict(FINAL, SEALED) checkNoConflict(PRIVATE, PROTECTED) // checkNoConflict(PRIVATE, OVERRIDE) // this one leads to bad error messages like #4174, so catch in refchecks // checkNoConflict(PRIVATE, FINAL) // can't do this because FINAL also means compile-time constant |