Skip to content

Commit 22e9219

Browse files
committed
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.
1 parent c844809 commit 22e9219

File tree

7 files changed

+22
-24
lines changed

7 files changed

+22
-24
lines changed

compiler/src/dotty/tools/dotc/ast/TreeInfo.scala

Lines changed: 10 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -26,23 +26,6 @@ trait TreeInfo[T >: Untyped <: Type] { self: Trees.Instance[T] =>
2626
case _ => false
2727
}
2828

29-
/** The largest subset of {NoInits, PureInterface} that a
30-
* trait enclosing this statement can have as flags.
31-
* Does tree contain an initialization part when seen as a member of a class or trait?
32-
*/
33-
def defKind(tree: Tree): FlagSet = unsplice(tree) match {
34-
case EmptyTree | _: Import =>
35-
NoInitsInterface
36-
case tree: TypeDef =>
37-
if (tree.isClassDef) NoInits else NoInitsInterface
38-
case tree: DefDef =>
39-
if (tree.unforcedRhs == EmptyTree && tree.vparamss.forall(_.forall(_.unforcedRhs == EmptyTree))) NoInitsInterface else NoInits
40-
case tree: ValDef =>
41-
if (tree.unforcedRhs == EmptyTree) NoInitsInterface else EmptyFlags
42-
case _ =>
43-
EmptyFlags
44-
}
45-
4629
def isOpAssign(tree: Tree) = unsplice(tree) match {
4730
case Apply(fn, _ :: _) =>
4831
unsplice(fn) match {
@@ -588,6 +571,16 @@ trait TypedTreeInfo extends TreeInfo[Type] { self: Trees.Instance[Type] =>
588571
accum(Nil, root)
589572
}
590573

574+
/** The largest subset of {NoInits, PureInterface} that a
575+
* trait enclosing this statement can have as flags.
576+
*/
577+
def defKind(tree: Tree): FlagSet = unsplice(tree) match {
578+
case EmptyTree | _: Import => NoInitsInterface
579+
case tree: TypeDef => if (tree.isClassDef) NoInits else NoInitsInterface
580+
case tree: DefDef => if (tree.unforcedRhs == EmptyTree) NoInitsInterface else NoInits
581+
case tree: ValDef => if (tree.unforcedRhs == EmptyTree) NoInitsInterface else EmptyFlags
582+
case _ => EmptyFlags
583+
}
591584

592585
/** The top level classes in this tree, including only those module classes that
593586
* are not a linked class of some other class in the result.

compiler/src/dotty/tools/dotc/core/Flags.scala

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -287,9 +287,10 @@ object Flags {
287287

288288

289289
/** A trait that has only abstract methods as members
290-
* (and therefore can be represented by a Java interface
290+
* and therefore can be represented by a Java interface.
291+
* Warning: flag is set during regular typer pass, should be tested only after typer.
291292
*/
292-
final val PureInterface = typeFlag(22, "interface") // TODO when unpickling, reconstitute from context
293+
final val PureInterface = typeFlag(22, "interface")
293294

294295
/** Labeled with of abstract & override */
295296
final val AbsOverride = termFlag(22, "abstract override")
@@ -338,7 +339,9 @@ object Flags {
338339
final val JavaStaticTerm = JavaStatic.toTermFlags
339340
final val JavaStaticType = JavaStatic.toTypeFlags
340341

341-
/** Trait does not have fields or initialization code */
342+
/** Trait does not have fields or initialization code.
343+
* Warning: flag is set during regular typer pass, should be tested only after typer.
344+
*/
342345
final val NoInits = typeFlag(32, "<noInits>")
343346

344347
/** Variable is accessed from nested function. */

compiler/src/dotty/tools/dotc/core/SymDenotations.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -158,7 +158,7 @@ object SymDenotations {
158158
final def resetFlag(flags: FlagSet): Unit = { myFlags &~= flags }
159159

160160
/** Set applicable flags from `flags` which is a subset of {NoInits, PureInterface} */
161-
final def setApplicableFlags(flags: FlagSet): Unit = {
161+
final def setNoInitsFlags(flags: FlagSet): Unit = {
162162
val mask = if (myFlags.is(Trait)) NoInitsInterface else NoInits
163163
setFlag(flags & mask)
164164
}

compiler/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -768,7 +768,7 @@ class TreeUnpickler(reader: TastyReader, tastyName: TastyName.Table, posUnpickle
768768
}
769769
else EmptyValDef
770770
setClsInfo(parentRefs, if (self.isEmpty) NoType else self.tpt.tpe)
771-
cls.setApplicableFlags(fork.indexStats(end))
771+
cls.setNoInitsFlags(fork.indexStats(end))
772772
val constr = readIndexedDef().asInstanceOf[DefDef]
773773

774774
def mergeTypeParamsAndAliases(tparams: List[TypeDef], stats: List[Tree])(implicit ctx: Context): (List[Tree], List[Tree]) =

compiler/src/dotty/tools/dotc/typer/Namer.scala

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -818,8 +818,6 @@ class Namer { typer: Typer =>
818818

819819
Checking.checkWellFormed(cls)
820820
if (isDerivedValueClass(cls)) cls.setFlag(Final)
821-
cls.setApplicableFlags(
822-
(NoInitsInterface /: impl.body)((fs, stat) => fs & defKind(stat)))
823821
cls.info = avoidPrivateLeaks(cls, cls.pos)
824822
}
825823
}

compiler/src/dotty/tools/dotc/typer/Typer.scala

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1314,6 +1314,7 @@ class Typer extends Namer with TypeAssigner with Applications with Implicits wit
13141314
val self1 = typed(self)(ctx.outer).asInstanceOf[ValDef] // outer context where class members are not visible
13151315
val dummy = localDummy(cls, impl)
13161316
val body1 = typedStats(impl.body, dummy)(inClassContext(self1.symbol))
1317+
cls.setNoInitsFlags((NoInitsInterface /: body1)((fs, stat) => fs & defKind(stat)))
13171318

13181319
// Expand comments and type usecases
13191320
cookComments(body1.map(_.symbol), self1.symbol)(localContext(cdef, cls).setNewScope)

tests/pickling/innerclass.scala

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
trait Foo {
2+
class Inner(x: Int = 42)
3+
}

0 commit comments

Comments
 (0)