Skip to content

Fix #2067: Compute defKind at Typer, not Namer #2069

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Mar 9, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 10 additions & 17 deletions compiler/src/dotty/tools/dotc/ast/TreeInfo.scala
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down Expand Up @@ -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.
Expand Down
9 changes: 6 additions & 3 deletions compiler/src/dotty/tools/dotc/core/Flags.scala
Original file line number Diff line number Diff line change
Expand Up @@ -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")
Expand Down Expand Up @@ -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. */
Expand Down
2 changes: 1 addition & 1 deletion compiler/src/dotty/tools/dotc/core/SymDenotations.scala
Original file line number Diff line number Diff line change
Expand Up @@ -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)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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]) =
Expand Down
2 changes: 0 additions & 2 deletions compiler/src/dotty/tools/dotc/typer/Namer.scala
Original file line number Diff line number Diff line change
Expand Up @@ -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)
}
}
Expand Down
1 change: 1 addition & 0 deletions compiler/src/dotty/tools/dotc/typer/Typer.scala
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
3 changes: 3 additions & 0 deletions tests/pickling/innerclass.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
trait Foo {
class Inner(x: Int = 42)
}