diff options
author | Martin Odersky <odersky@gmail.com> | 2017-03-08 16:51:06 +0100 |
---|---|---|
committer | Martin Odersky <odersky@gmail.com> | 2017-03-08 16:52:43 +0100 |
commit | 22e9219dd46eeb3b4ba3823d6dc45bc42c41dca1 (patch) | |
tree | 7a6f87b1e615c218258666004cca2766895640a4 /compiler/src/dotty | |
parent | c84480960cf618c29705dbaab9332d304a081524 (diff) | |
download | dotty-22e9219dd46eeb3b4ba3823d6dc45bc42c41dca1.tar.gz dotty-22e9219dd46eeb3b4ba3823d6dc45bc42c41dca1.tar.bz2 dotty-22e9219dd46eeb3b4ba3823d6dc45bc42c41dca1.zip |
Fix #2067: Compute defKind at Typer, not Namer
It's hard to predict for defKind all the desugarings that can be
applied to a definition. Better to do it once the desugarings have been
applied. NoInit and PureInterface are both tested only after Typer,
so it's OK to delay their initialization until regular Typer.
Diffstat (limited to 'compiler/src/dotty')
6 files changed, 19 insertions, 24 deletions
diff --git a/compiler/src/dotty/tools/dotc/ast/TreeInfo.scala b/compiler/src/dotty/tools/dotc/ast/TreeInfo.scala index dd890dc50..b00d7df71 100644 --- a/compiler/src/dotty/tools/dotc/ast/TreeInfo.scala +++ b/compiler/src/dotty/tools/dotc/ast/TreeInfo.scala @@ -26,23 +26,6 @@ trait TreeInfo[T >: Untyped <: Type] { self: Trees.Instance[T] => case _ => false } - /** The largest subset of {NoInits, PureInterface} that a - * trait enclosing this statement can have as flags. - * Does tree contain an initialization part when seen as a member of a class or trait? - */ - def defKind(tree: Tree): FlagSet = unsplice(tree) match { - case EmptyTree | _: Import => - NoInitsInterface - case tree: TypeDef => - if (tree.isClassDef) NoInits else NoInitsInterface - case tree: DefDef => - if (tree.unforcedRhs == EmptyTree && tree.vparamss.forall(_.forall(_.unforcedRhs == EmptyTree))) NoInitsInterface else NoInits - case tree: ValDef => - if (tree.unforcedRhs == EmptyTree) NoInitsInterface else EmptyFlags - case _ => - EmptyFlags - } - def isOpAssign(tree: Tree) = unsplice(tree) match { case Apply(fn, _ :: _) => unsplice(fn) match { @@ -588,6 +571,16 @@ trait TypedTreeInfo extends TreeInfo[Type] { self: Trees.Instance[Type] => accum(Nil, root) } + /** The largest subset of {NoInits, PureInterface} that a + * trait enclosing this statement can have as flags. + */ + def defKind(tree: Tree): FlagSet = unsplice(tree) match { + case EmptyTree | _: Import => NoInitsInterface + case tree: TypeDef => if (tree.isClassDef) NoInits else NoInitsInterface + case tree: DefDef => if (tree.unforcedRhs == EmptyTree) NoInitsInterface else NoInits + case tree: ValDef => if (tree.unforcedRhs == EmptyTree) NoInitsInterface else EmptyFlags + case _ => EmptyFlags + } /** The top level classes in this tree, including only those module classes that * are not a linked class of some other class in the result. diff --git a/compiler/src/dotty/tools/dotc/core/Flags.scala b/compiler/src/dotty/tools/dotc/core/Flags.scala index d2a1c58f5..c1267d8a2 100644 --- a/compiler/src/dotty/tools/dotc/core/Flags.scala +++ b/compiler/src/dotty/tools/dotc/core/Flags.scala @@ -287,9 +287,10 @@ object Flags { /** A trait that has only abstract methods as members - * (and therefore can be represented by a Java interface + * and therefore can be represented by a Java interface. + * Warning: flag is set during regular typer pass, should be tested only after typer. */ - final val PureInterface = typeFlag(22, "interface") // TODO when unpickling, reconstitute from context + final val PureInterface = typeFlag(22, "interface") /** Labeled with of abstract & override */ final val AbsOverride = termFlag(22, "abstract override") @@ -338,7 +339,9 @@ object Flags { final val JavaStaticTerm = JavaStatic.toTermFlags final val JavaStaticType = JavaStatic.toTypeFlags - /** Trait does not have fields or initialization code */ + /** Trait does not have fields or initialization code. + * Warning: flag is set during regular typer pass, should be tested only after typer. + */ final val NoInits = typeFlag(32, "<noInits>") /** Variable is accessed from nested function. */ diff --git a/compiler/src/dotty/tools/dotc/core/SymDenotations.scala b/compiler/src/dotty/tools/dotc/core/SymDenotations.scala index 9b9caf8e7..c98b444d9 100644 --- a/compiler/src/dotty/tools/dotc/core/SymDenotations.scala +++ b/compiler/src/dotty/tools/dotc/core/SymDenotations.scala @@ -158,7 +158,7 @@ object SymDenotations { final def resetFlag(flags: FlagSet): Unit = { myFlags &~= flags } /** Set applicable flags from `flags` which is a subset of {NoInits, PureInterface} */ - final def setApplicableFlags(flags: FlagSet): Unit = { + final def setNoInitsFlags(flags: FlagSet): Unit = { val mask = if (myFlags.is(Trait)) NoInitsInterface else NoInits setFlag(flags & mask) } diff --git a/compiler/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala b/compiler/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala index fcba957c0..fdb8a97ae 100644 --- a/compiler/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala +++ b/compiler/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala @@ -768,7 +768,7 @@ class TreeUnpickler(reader: TastyReader, tastyName: TastyName.Table, posUnpickle } else EmptyValDef setClsInfo(parentRefs, if (self.isEmpty) NoType else self.tpt.tpe) - cls.setApplicableFlags(fork.indexStats(end)) + cls.setNoInitsFlags(fork.indexStats(end)) val constr = readIndexedDef().asInstanceOf[DefDef] def mergeTypeParamsAndAliases(tparams: List[TypeDef], stats: List[Tree])(implicit ctx: Context): (List[Tree], List[Tree]) = diff --git a/compiler/src/dotty/tools/dotc/typer/Namer.scala b/compiler/src/dotty/tools/dotc/typer/Namer.scala index 96660f15c..83ae8ad9f 100644 --- a/compiler/src/dotty/tools/dotc/typer/Namer.scala +++ b/compiler/src/dotty/tools/dotc/typer/Namer.scala @@ -818,8 +818,6 @@ class Namer { typer: Typer => Checking.checkWellFormed(cls) if (isDerivedValueClass(cls)) cls.setFlag(Final) - cls.setApplicableFlags( - (NoInitsInterface /: impl.body)((fs, stat) => fs & defKind(stat))) cls.info = avoidPrivateLeaks(cls, cls.pos) } } diff --git a/compiler/src/dotty/tools/dotc/typer/Typer.scala b/compiler/src/dotty/tools/dotc/typer/Typer.scala index b2e9d639d..ba14b7498 100644 --- a/compiler/src/dotty/tools/dotc/typer/Typer.scala +++ b/compiler/src/dotty/tools/dotc/typer/Typer.scala @@ -1314,6 +1314,7 @@ class Typer extends Namer with TypeAssigner with Applications with Implicits wit val self1 = typed(self)(ctx.outer).asInstanceOf[ValDef] // outer context where class members are not visible val dummy = localDummy(cls, impl) val body1 = typedStats(impl.body, dummy)(inClassContext(self1.symbol)) + cls.setNoInitsFlags((NoInitsInterface /: body1)((fs, stat) => fs & defKind(stat))) // Expand comments and type usecases cookComments(body1.map(_.symbol), self1.symbol)(localContext(cdef, cls).setNewScope) |