diff options
Diffstat (limited to 'compiler')
-rw-r--r-- | compiler/src/dotty/tools/dotc/ast/untpd.scala | 1 | ||||
-rw-r--r-- | compiler/src/dotty/tools/dotc/typer/Namer.scala | 63 |
2 files changed, 35 insertions, 29 deletions
diff --git a/compiler/src/dotty/tools/dotc/ast/untpd.scala b/compiler/src/dotty/tools/dotc/ast/untpd.scala index 99bc3240f..8ca91590f 100644 --- a/compiler/src/dotty/tools/dotc/ast/untpd.scala +++ b/compiler/src/dotty/tools/dotc/ast/untpd.scala @@ -149,6 +149,7 @@ object untpd extends Trees.Instance[Untyped] with UntypedTreeInfo { def is(fs: FlagSet): Boolean = flags is fs def is(fc: FlagConjunction): Boolean = flags is fc + def is(fc: FlagSet, butNot: FlagSet): Boolean = flags.is(fc, butNot = butNot) def | (fs: FlagSet): Modifiers = withFlags(flags | fs) def & (fs: FlagSet): Modifiers = withFlags(flags & fs) diff --git a/compiler/src/dotty/tools/dotc/typer/Namer.scala b/compiler/src/dotty/tools/dotc/typer/Namer.scala index 7d8c5f95f..6e1c564cd 100644 --- a/compiler/src/dotty/tools/dotc/typer/Namer.scala +++ b/compiler/src/dotty/tools/dotc/typer/Namer.scala @@ -484,7 +484,7 @@ class Namer { typer: Typer => /** Create top-level symbols for statements and enter them into symbol table */ def index(stats: List[Tree])(implicit ctx: Context): Context = { - // module name -> (stat, moduleCls / moduleVal) + // module name -> (stat, moduleCls | moduleVal) val moduleClsDef = mutable.Map[TypeName, (Tree, TypeDef)]() val moduleValDef = mutable.Map[TermName, (Tree, ValDef)]() @@ -512,49 +512,54 @@ class Namer { typer: Typer => res } + /** Merge `fromCls` of `fromStat` into `toCls` of `toStat` + * if the former is synthetic and the latter not. + * + * Note: + * 1. `fromStat` and `toStat` could be the same stat + * 2. `fromCls` and `toCls` are necessarily different + */ + def mergeIfSynthetic(fromStat: Tree, fromCls: TypeDef, toStat: Tree, toCls: TypeDef): Unit = + if (fromCls.mods.is(Synthetic) && !toCls.mods.is(Synthetic)) { + removeInExpanded(fromStat, fromCls) + val mcls = mergeModuleClass(toStat, toCls, fromCls.rhs.asInstanceOf[Template].body) + moduleClsDef(fromCls.name) = (toStat, mcls) + } + /** Merge the definitions of a synthetic companion generated by a case class * and the real companion, if both exist. */ def mergeCompanionDefs() = { - def valid(mdef: MemberDef): Boolean = !mdef.mods.is(Package) && mdef.mods.is(Module) + def valid(mdef: MemberDef): Boolean = mdef.mods.is(Module, butNot = Package) for (stat <- stats) expanded(stat) match { case Thicket(trees) => // companion object always expands to thickets trees.map { case mcls @ TypeDef(name, impl: Template) if valid(mcls) => - if (moduleClsDef.contains(name)) { - val (stat1, mcls1 @ TypeDef(_, impl1: Template)) = moduleClsDef(name) - if (mcls.mods.is(Synthetic) && !mcls1.mods.is(Synthetic)) { // merge synthetic into user-defined module - removeInExpanded(stat, mcls) - val mcls2 = mergeModuleClass(stat1, mcls1, impl.body) - moduleClsDef(name) = (stat1, mcls2) - } - else if (!mcls.mods.is(Synthetic) && mcls1.mods.is(Synthetic)) { - removeInExpanded(stat1, mcls1) - val mcls2 = mergeModuleClass(stat, mcls, impl1.body) - moduleClsDef(name) = (stat, mcls2) - } - else { - // redefinition of objects or case classes, handled elsewhere - } + moduleClsDef.get(name) match { + case Some((stat1, mcls1@TypeDef(_, impl1: Template))) => + mergeIfSynthetic(stat, mcls, stat1, mcls1) + mergeIfSynthetic(stat1, mcls1, stat, mcls) + case None => + moduleClsDef(name) = (stat, mcls) } - else moduleClsDef(name) = (stat, mcls) case vdef @ ValDef(name, _, _) if valid(vdef) => - if (moduleValDef.contains(name)) { - val (stat1, vdef1) = moduleValDef(name) - if (vdef.mods.is(Synthetic) && !vdef1.mods.is(Synthetic)) // merge synthetic into user-defined module - removeInExpanded(stat, vdef) - else if (!vdef.mods.is(Synthetic) && vdef1.mods.is(Synthetic)) { - removeInExpanded(stat1, vdef1) + moduleValDef.get(name) match { + case Some((stat1, vdef1)) => + if (vdef.mods.is(Synthetic) && !vdef1.mods.is(Synthetic)) + removeInExpanded(stat, vdef) + else if (!vdef.mods.is(Synthetic) && vdef1.mods.is(Synthetic)) { + removeInExpanded(stat1, vdef1) + moduleValDef(name) = (stat, vdef) + } + else { + // double definition of objects or case classes, handled elsewhere + } + case None => moduleValDef(name) = (stat, vdef) - } - else { - // redefinition of objects or case classes, handled elsewhere - } } - else moduleValDef(name) = (stat, vdef) case _ => } |