diff options
author | Martin Odersky <odersky@gmail.com> | 2014-12-18 15:39:55 +0100 |
---|---|---|
committer | Martin Odersky <odersky@gmail.com> | 2014-12-18 15:43:22 +0100 |
commit | 223fa2bea328fc53f87d6f9d0c28c67545e831af (patch) | |
tree | 0bfffb4a2168df6527779d4d97a87f7309ee333c | |
parent | e0bf1758ac32d69cf97d28f449cc0400755e3914 (diff) | |
download | dotty-223fa2bea328fc53f87d6f9d0c28c67545e831af.tar.gz dotty-223fa2bea328fc53f87d6f9d0c28c67545e831af.tar.bz2 dotty-223fa2bea328fc53f87d6f9d0c28c67545e831af.zip |
More careful usage of unforced decls in classes.
1) Rename `decls` to `unforcedDecls` to make it clear that
it is danegrous to use.
2) Prefer `info.decls` over `unforcedDecls`.
This fixes the problem reported in #305 where the primary
constructor was not found.
-rw-r--r-- | src/dotty/tools/dotc/ast/TreeTypeMap.scala | 2 | ||||
-rw-r--r-- | src/dotty/tools/dotc/core/SymDenotations.scala | 30 | ||||
-rw-r--r-- | src/dotty/tools/dotc/core/SymbolLoaders.scala | 2 | ||||
-rw-r--r-- | src/dotty/tools/dotc/core/Symbols.scala | 2 | ||||
-rw-r--r-- | src/dotty/tools/dotc/core/TypeApplications.scala | 2 | ||||
-rw-r--r-- | src/dotty/tools/dotc/core/Types.scala | 2 | ||||
-rw-r--r-- | src/dotty/tools/dotc/core/pickling/ClassfileParser.scala | 2 | ||||
-rw-r--r-- | src/dotty/tools/dotc/core/pickling/UnPickler.scala | 6 | ||||
-rw-r--r-- | src/dotty/tools/dotc/transform/Erasure.scala | 2 | ||||
-rw-r--r-- | src/dotty/tools/dotc/transform/LambdaLift.scala | 2 | ||||
-rw-r--r-- | src/dotty/tools/dotc/transform/Mixin.scala | 4 | ||||
-rw-r--r-- | src/dotty/tools/dotc/transform/ResolveSuper.scala | 4 | ||||
-rw-r--r-- | src/dotty/tools/dotc/transform/SymUtils.scala | 2 | ||||
-rw-r--r-- | src/dotty/tools/dotc/typer/Namer.scala | 2 | ||||
-rw-r--r-- | src/dotty/tools/dotc/typer/Typer.scala | 2 | ||||
-rw-r--r-- | tests/pos/annot-bootstrap.scala | 8 |
16 files changed, 45 insertions, 29 deletions
diff --git a/src/dotty/tools/dotc/ast/TreeTypeMap.scala b/src/dotty/tools/dotc/ast/TreeTypeMap.scala index 846c661f5..98027cd39 100644 --- a/src/dotty/tools/dotc/ast/TreeTypeMap.scala +++ b/src/dotty/tools/dotc/ast/TreeTypeMap.scala @@ -170,7 +170,7 @@ final class TreeTypeMap( val symsChanged = syms ne mapped val substMap = withSubstitution(syms, mapped) val fullMap = (substMap /: mapped.filter(_.isClass)) { (tmap, cls) => - val origDcls = cls.decls.toList + val origDcls = cls.info.decls.toList val mappedDcls = ctx.mapSymbols(origDcls, tmap) val tmap1 = tmap.withMappedSyms(origDcls, mappedDcls) if (symsChanged) (origDcls, mappedDcls).zipped.foreach(cls.asClass.replace) diff --git a/src/dotty/tools/dotc/core/SymDenotations.scala b/src/dotty/tools/dotc/core/SymDenotations.scala index eccdcbfb9..224b65b43 100644 --- a/src/dotty/tools/dotc/core/SymDenotations.scala +++ b/src/dotty/tools/dotc/core/SymDenotations.scala @@ -45,7 +45,7 @@ trait SymDenotations { this: Context => val owner = denot.owner.denot stillValid(owner) && ( !owner.isClass - || (owner.decls.lookupAll(denot.name) contains denot.symbol) + || (owner.unforcedDecls.lookupAll(denot.name) contains denot.symbol) || denot.isSelfSym ) } catch { @@ -234,12 +234,20 @@ object SymDenotations { final def ensureCompleted()(implicit ctx: Context): Unit = info /** The symbols defined in this class or object. + * Careful! This coes not force the type, so is compilation order dependent. + * This method should be used only in the following circumstances: + * + * 1. When accessing type parameters or type parameter accessors (both are entered before + * completion). + * 2. When obtaining the current scope in order to enter, rename or delete something there. + * 3. When playing it safe in order not to raise CylicReferences, e.g. for printing things + * or taking more efficient shortcuts (e.g. the stillValid test). */ - final def decls(implicit ctx: Context): Scope = myInfo match { + final def unforcedDecls(implicit ctx: Context): Scope = myInfo match { case cinfo: LazyType => val knownDecls = cinfo.decls if (knownDecls ne EmptyScope) knownDecls - else { completeFrom(cinfo); decls } // complete-once + else { completeFrom(cinfo); unforcedDecls } // complete-once case _ => info.decls } @@ -251,7 +259,7 @@ object SymDenotations { */ final def preDecls(implicit ctx: Context): MutableScope = myInfo match { case pinfo: SymbolLoaders # PackageLoader => pinfo.preDecls - case _ => decls.asInstanceOf[MutableScope] + case _ => unforcedDecls.asInstanceOf[MutableScope] } // ------ Names ---------------------------------------------- @@ -997,7 +1005,7 @@ object SymDenotations { def computeTypeParams = { if (ctx.erasedTypes || is(Module)) Nil // fast return for modules to avoid scanning package decls else if (this ne initial) initial.asSymDenotation.typeParams - else decls.filter(sym => + else unforcedDecls.filter(sym => (sym is TypeParam) && sym.owner == symbol).asInstanceOf[List[TypeSymbol]] } if (myTypeParams == null) myTypeParams = computeTypeParams @@ -1228,7 +1236,7 @@ object SymDenotations { def enter(sym: Symbol, scope: Scope = EmptyScope)(implicit ctx: Context): Unit = { val mscope = scope match { case scope: MutableScope => scope - case _ => decls.asInstanceOf[MutableScope] + case _ => unforcedDecls.asInstanceOf[MutableScope] } if (this is PackageClass) { val entry = mscope.lookupEntry(sym.name) @@ -1258,7 +1266,7 @@ object SymDenotations { */ def replace(prev: Symbol, replacement: Symbol)(implicit ctx: Context): Unit = { require(!(this is Frozen)) - decls.asInstanceOf[MutableScope].replace(prev, replacement) + unforcedDecls.asInstanceOf[MutableScope].replace(prev, replacement) if (myMemberCache != null) myMemberCache invalidate replacement.name } @@ -1281,7 +1289,7 @@ object SymDenotations { * have existing symbols. */ final def membersNamed(name: Name)(implicit ctx: Context): PreDenotation = { - val privates = decls.denotsNamed(name, selectPrivate) + val privates = info.decls.denotsNamed(name, selectPrivate) privates union nonPrivateMembersNamed(name).filterDisjoint(privates) } @@ -1311,7 +1319,7 @@ object SymDenotations { (memberFingerPrint contains name)) { Stats.record("computeNPMembersNamed after fingerprint") ensureCompleted() - val ownDenots = decls.denotsNamed(name, selectNonPrivate) + val ownDenots = info.decls.denotsNamed(name, selectNonPrivate) if (debugTrace) // DEBUG println(s"$this.member($name), ownDenots = $ownDenots") def collect(denots: PreDenotation, parents: List[TypeRef]): PreDenotation = parents match { @@ -1458,14 +1466,14 @@ object SymDenotations { override def primaryConstructor(implicit ctx: Context): Symbol = { val cname = if (this is ImplClass) nme.IMPLCLASS_CONSTRUCTOR else nme.CONSTRUCTOR - decls.denotsNamed(cname).last.symbol // denotsNamed returns Symbols in reverse order of occurrence + info.decls.denotsNamed(cname).last.symbol // denotsNamed returns Symbols in reverse order of occurrence } /** The parameter accessors of this class. Term and type accessors, * getters and setters are all returned int his list */ def paramAccessors(implicit ctx: Context): List[Symbol] = - decls.filter(_ is ParamAccessor).toList + unforcedDecls.filter(_ is ParamAccessor).toList /** If this class has the same `decls` scope reference in `phase` and * `phase.next`, install a new denotation with a cloned scope in `phase.next`. diff --git a/src/dotty/tools/dotc/core/SymbolLoaders.scala b/src/dotty/tools/dotc/core/SymbolLoaders.scala index 76ba3885e..41ec10c18 100644 --- a/src/dotty/tools/dotc/core/SymbolLoaders.scala +++ b/src/dotty/tools/dotc/core/SymbolLoaders.scala @@ -162,7 +162,7 @@ class SymbolLoaders { if (!maybeModuleClass(classRep)) initializeFromClassPath(root.symbol, classRep) for (classRep <- classpath.classes) - if (maybeModuleClass(classRep) && !root.decls.lookup(classRep.name.toTypeName).exists) + if (maybeModuleClass(classRep) && !root.unforcedDecls.lookup(classRep.name.toTypeName).exists) initializeFromClassPath(root.symbol, classRep) } if (!root.isEmptyPackage) diff --git a/src/dotty/tools/dotc/core/Symbols.scala b/src/dotty/tools/dotc/core/Symbols.scala index 9be75c11a..9817c12ee 100644 --- a/src/dotty/tools/dotc/core/Symbols.scala +++ b/src/dotty/tools/dotc/core/Symbols.scala @@ -192,7 +192,7 @@ trait Symbols { this: Context => def stubCompleter = new StubInfo() val normalizedOwner = if (owner is ModuleVal) owner.moduleClass else owner println(s"creating stub for ${name.show}, owner = ${normalizedOwner.denot.debugString}, file = $file") - println(s"decls = ${normalizedOwner.decls.toList.map(_.debugString).mkString("\n ")}") // !!! DEBUG + println(s"decls = ${normalizedOwner.unforcedDecls.toList.map(_.debugString).mkString("\n ")}") // !!! DEBUG //if (base.settings.debug.value) throw new Error() val stub = name match { case name: TermName => diff --git a/src/dotty/tools/dotc/core/TypeApplications.scala b/src/dotty/tools/dotc/core/TypeApplications.scala index 6443c5054..539ef5e0d 100644 --- a/src/dotty/tools/dotc/core/TypeApplications.scala +++ b/src/dotty/tools/dotc/core/TypeApplications.scala @@ -141,7 +141,7 @@ class TypeApplications(val self: Type) extends AnyVal { case arg :: args1 => if (tparams.isEmpty) { println(s"applied type mismatch: $self $args, typeParams = $typeParams, tsym = ${self.typeSymbol.debugString}") // !!! DEBUG - println(s"precomplete decls = ${self.typeSymbol.decls.toList.map(_.denot).mkString("\n ")}") + println(s"precomplete decls = ${self.typeSymbol.unforcedDecls.toList.map(_.denot).mkString("\n ")}") } val tparam = tparams.head val arg1 = diff --git a/src/dotty/tools/dotc/core/Types.scala b/src/dotty/tools/dotc/core/Types.scala index a1ca7796f..5862a934a 100644 --- a/src/dotty/tools/dotc/core/Types.scala +++ b/src/dotty/tools/dotc/core/Types.scala @@ -895,7 +895,7 @@ object Types { * no symbol it tries `member` as an alternative. */ def typeParamNamed(name: TypeName)(implicit ctx: Context): Symbol = - classSymbol.decls.lookup(name) orElse member(name).symbol + classSymbol.unforcedDecls.lookup(name) orElse member(name).symbol /** If this is a prototype with some ignored component, reveal one more * layer of it. Otherwise the type itself. diff --git a/src/dotty/tools/dotc/core/pickling/ClassfileParser.scala b/src/dotty/tools/dotc/core/pickling/ClassfileParser.scala index cc3d3eb7f..ef5f48047 100644 --- a/src/dotty/tools/dotc/core/pickling/ClassfileParser.scala +++ b/src/dotty/tools/dotc/core/pickling/ClassfileParser.scala @@ -368,7 +368,7 @@ class ClassfileParser( val s = ctx.newSymbol( owner, expname, owner.typeParamCreationFlags, typeParamCompleter(index), coord = indexCoord(index)) - if (owner.isClass) owner.asClass.enter(s, owner.decls) + if (owner.isClass) owner.asClass.enter(s) tparams = tparams + (tpname -> s) sig2typeBounds(tparams, skiptvs = true) newTParams += s diff --git a/src/dotty/tools/dotc/core/pickling/UnPickler.scala b/src/dotty/tools/dotc/core/pickling/UnPickler.scala index 728048700..56df65f96 100644 --- a/src/dotty/tools/dotc/core/pickling/UnPickler.scala +++ b/src/dotty/tools/dotc/core/pickling/UnPickler.scala @@ -343,7 +343,7 @@ class UnPickler(bytes: Array[Byte], classRoot: ClassDenotation, moduleClassRoot: if (denot.exists && !denot1.exists) { // !!!DEBUG val alts = denot.alternatives map (d => d+":"+d.info+"/"+d.signature) System.err.println(s"!!! disambiguation failure: $alts") - val members = denot.alternatives.head.symbol.owner.decls.toList map (d => d+":"+d.info+"/"+d.signature) + val members = denot.alternatives.head.symbol.owner.info.decls.toList map (d => d+":"+d.info+"/"+d.signature) System.err.println(s"!!! all members: $members") } if (tag == EXTref) sym else sym.moduleClass @@ -475,7 +475,7 @@ class UnPickler(bytes: Array[Byte], classRoot: ClassDenotation, moduleClassRoot: val unpickler = new LocalUnpickler() withDecls symScope(cls) if (flags is ModuleClass) unpickler withSourceModule (implicit ctx => - cls.owner.decls.lookup(cls.name.sourceModuleName) + cls.owner.info.decls.lookup(cls.name.sourceModuleName) .suchThat(_ is Module).symbol) else unpickler } @@ -637,7 +637,7 @@ class UnPickler(bytes: Array[Byte], classRoot: ClassDenotation, moduleClassRoot: // and also for the inner Transform class in all views. We fix it by // replacing the this with the appropriate super. if (sym.owner != thispre.cls) { - val overriding = thispre.cls.decls.lookup(sym.name) + val overriding = thispre.cls.info.decls.lookup(sym.name) if (overriding.exists && overriding != sym) { val base = pre.baseTypeWithArgs(sym.owner) assert(base.exists) diff --git a/src/dotty/tools/dotc/transform/Erasure.scala b/src/dotty/tools/dotc/transform/Erasure.scala index 933252ccd..a0370feca 100644 --- a/src/dotty/tools/dotc/transform/Erasure.scala +++ b/src/dotty/tools/dotc/transform/Erasure.scala @@ -443,7 +443,7 @@ object Erasure extends TypeTestsCasts{ if (isRequired) { // check for clashes - val clash: Option[Symbol] = oldSymbol.owner.decls.lookupAll(bridge.name).find { + val clash: Option[Symbol] = oldSymbol.owner.info.decls.lookupAll(bridge.name).find { sym => (sym.name eq bridge.name) && sym.info.widen =:= bridge.info.widen }.orElse( diff --git a/src/dotty/tools/dotc/transform/LambdaLift.scala b/src/dotty/tools/dotc/transform/LambdaLift.scala index c8dacd1d7..1363615a5 100644 --- a/src/dotty/tools/dotc/transform/LambdaLift.scala +++ b/src/dotty/tools/dotc/transform/LambdaLift.scala @@ -275,7 +275,7 @@ class LambdaLift extends MiniPhase with IdentityDenotTransformer { thisTransform initFlags = local.flags | Private | maybeStatic | maybeNotJavaPrivate, info = liftedInfo(local)).installAfter(thisTransform) if (local.isClass) - for (member <- local.asClass.decls) + for (member <- local.asClass.info.decls) if (member.isConstructor) { val linfo = liftedInfo(member) if (linfo ne member.info) diff --git a/src/dotty/tools/dotc/transform/Mixin.scala b/src/dotty/tools/dotc/transform/Mixin.scala index 230763fae..7e307c736 100644 --- a/src/dotty/tools/dotc/transform/Mixin.scala +++ b/src/dotty/tools/dotc/transform/Mixin.scala @@ -148,13 +148,13 @@ class Mixin extends MiniPhaseTransform with SymTransformer { thisTransform => ctx.atPhase(thisTransform) { implicit ctx => sym is Deferred } def traitInits(mixin: ClassSymbol): List[Tree] = - for (getter <- mixin.decls.filter(getr => getr.isGetter && !wasDeferred(getr)).toList) + for (getter <- mixin.info.decls.filter(getr => getr.isGetter && !wasDeferred(getr)).toList) yield { DefDef(implementation(getter.asTerm), superRef(initializer(getter)).appliedToNone) } def setters(mixin: ClassSymbol): List[Tree] = - for (setter <- mixin.decls.filter(setr => setr.isSetter && !wasDeferred(setr)).toList) + for (setter <- mixin.info.decls.filter(setr => setr.isSetter && !wasDeferred(setr)).toList) yield DefDef(implementation(setter.asTerm), unitLiteral.withPos(cls.pos)) cpy.Template(impl)( diff --git a/src/dotty/tools/dotc/transform/ResolveSuper.scala b/src/dotty/tools/dotc/transform/ResolveSuper.scala index 9f952f6de..953c8b74d 100644 --- a/src/dotty/tools/dotc/transform/ResolveSuper.scala +++ b/src/dotty/tools/dotc/transform/ResolveSuper.scala @@ -75,7 +75,7 @@ class ResolveSuper extends MiniPhaseTransform with IdentityDenotTransformer { th import ops._ def superAccessors(mixin: ClassSymbol): List[Tree] = - for (superAcc <- mixin.decls.filter(_ is SuperAccessor).toList) + for (superAcc <- mixin.info.decls.filter(_ is SuperAccessor).toList) yield polyDefDef(implementation(superAcc.asTerm), forwarder(rebindSuper(cls, superAcc))) def methodOverrides(mixin: ClassSymbol): List[Tree] = { @@ -84,7 +84,7 @@ class ResolveSuper extends MiniPhaseTransform with IdentityDenotTransformer { th meth.is(Method, butNot = PrivateOrDeferred) && !isOverridden(meth) && !meth.allOverriddenSymbols.forall(_ is Deferred) - for (meth <- mixin.decls.toList if needsDisambiguation(meth)) + for (meth <- mixin.info.decls.toList if needsDisambiguation(meth)) yield polyDefDef(implementation(meth.asTerm), forwarder(meth)) } diff --git a/src/dotty/tools/dotc/transform/SymUtils.scala b/src/dotty/tools/dotc/transform/SymUtils.scala index 9274150b1..0a5854ea7 100644 --- a/src/dotty/tools/dotc/transform/SymUtils.scala +++ b/src/dotty/tools/dotc/transform/SymUtils.scala @@ -80,7 +80,7 @@ class SymUtils(val self: Symbol) extends AnyVal { self.owner.info.decl(name).suchThat(_ is Accessor).symbol def caseAccessors(implicit ctx:Context) = - self.decls.filter(_ is CaseAccessor).toList + self.info.decls.filter(_ is CaseAccessor).toList def getter(implicit ctx: Context): Symbol = if (self.isGetter) self else accessorNamed(self.asTerm.name.getterName) diff --git a/src/dotty/tools/dotc/typer/Namer.scala b/src/dotty/tools/dotc/typer/Namer.scala index 86376356c..91de8fe1e 100644 --- a/src/dotty/tools/dotc/typer/Namer.scala +++ b/src/dotty/tools/dotc/typer/Namer.scala @@ -52,7 +52,7 @@ trait NamerContextOps { this: Context => * the declarations of the current class. */ def effectiveScope: Scope = - if (owner != null && owner.isClass) owner.asClass.decls + if (owner != null && owner.isClass) owner.asClass.unforcedDecls else scope /** The symbol (stored in some typer's symTree) of an enclosing context definition */ diff --git a/src/dotty/tools/dotc/typer/Typer.scala b/src/dotty/tools/dotc/typer/Typer.scala index 5d388e7de..7f1ff1ad1 100644 --- a/src/dotty/tools/dotc/typer/Typer.scala +++ b/src/dotty/tools/dotc/typer/Typer.scala @@ -454,7 +454,7 @@ class Typer extends Namer with TypeAssigner with Applications with Implicits wit def classLeaks(sym: ClassSymbol): Boolean = (ctx.owner is Method) || // can't hoist classes out of method bodies (sym.info.parents exists typeLeaks) || - (sym.decls.toList exists (t => typeLeaks(t.info))) + (sym.info.decls.toList exists (t => typeLeaks(t.info))) leakingTypes(block.tpe) } diff --git a/tests/pos/annot-bootstrap.scala b/tests/pos/annot-bootstrap.scala new file mode 100644 index 000000000..bef877dcd --- /dev/null +++ b/tests/pos/annot-bootstrap.scala @@ -0,0 +1,8 @@ +package scala.annotation.unchecked + +// note: if the case class is not inside an object, the error disappears +object test { + case class L(a: Int) +} + +final class uncheckedVariance extends scala.annotation.StaticAnnotation {} |