Skip to content

Commit 5c21114

Browse files
committed
Keep track of opaque companion links
maintain the link from a module class to its opaque type companion, using the same technique as for companion classes.
1 parent e959c7a commit 5c21114

File tree

4 files changed

+43
-25
lines changed

4 files changed

+43
-25
lines changed

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -143,6 +143,7 @@ object StdNames {
143143
val INITIALIZER_PREFIX: N = "initial$"
144144
val COMPANION_MODULE_METHOD: N = "companion$module"
145145
val COMPANION_CLASS_METHOD: N = "companion$class"
146+
val COMPANION_TYPE_METHOD: N = "companion$type"
146147
val BOUNDTYPE_ANNOT: N = "$boundType$"
147148
val QUOTE: N = "'"
148149
val TYPE_QUOTE: N = "type_'"

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

Lines changed: 22 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -382,7 +382,7 @@ object SymDenotations {
382382

383383
final def normalizeOpaque()(implicit ctx: Context) = {
384384
if (is(Opaque)) {
385-
addAnnotation(Annotation.OpaqueAlias(info))
385+
addAnnotation(Annotation.OpaqueAlias(info.bounds.lo))
386386
setFlag(Deferred)
387387
info = TypeBounds.empty
388388
}
@@ -494,14 +494,15 @@ object SymDenotations {
494494
final def isAnonymousModuleVal(implicit ctx: Context) =
495495
this.symbol.is(ModuleVal) && (initial.name startsWith str.ANON_CLASS)
496496

497-
/** Is this a companion class method or companion object method?
497+
/** Is this a companion class or type method or companion object method?
498498
* These methods are generated by Symbols#synthesizeCompanionMethod
499499
* and used in SymDenotations#companionClass and
500500
* SymDenotations#companionModule .
501501
*/
502502
final def isCompanionMethod(implicit ctx: Context) =
503503
name.toTermName == nme.COMPANION_CLASS_METHOD ||
504-
name.toTermName == nme.COMPANION_MODULE_METHOD
504+
name.toTermName == nme.COMPANION_MODULE_METHOD ||
505+
name.toTermName == nme.COMPANION_TYPE_METHOD
505506

506507
/** Is this a synthetic method that represents conversions between representations of a value class
507508
* These methods are generated in ExtensionMethods
@@ -967,20 +968,28 @@ object SymDenotations {
967968
}
968969
}
969970

970-
/** The class with the same (type-) name as this module or module class,
971-
* and which is also defined in the same scope and compilation unit.
972-
* NoSymbol if this class does not exist.
973-
*/
974-
final def companionClass(implicit ctx: Context): Symbol =
971+
private def companionType(name: TermName)(implicit ctx: Context): Symbol =
975972
if (is(Package)) NoSymbol
976973
else {
977-
val companionMethod = info.decls.denotsNamed(nme.COMPANION_CLASS_METHOD, selectPrivate).first
978-
if (companionMethod.exists)
979-
companionMethod.info.resultType.classSymbol
980-
else
981-
NoSymbol
974+
val companionMethod = info.decls.denotsNamed(name, selectPrivate).first
975+
if (companionMethod.exists) companionMethod.info.resultType.typeSymbol
976+
else NoSymbol
982977
}
983978

979+
/** The class with the same (type-) name as this module or module class,
980+
* and which is also defined in the same scope and compilation unit.
981+
* NoSymbol if this class does not exist.
982+
*/
983+
final def companionClass(implicit ctx: Context): Symbol =
984+
companionType(nme.COMPANION_CLASS_METHOD).suchThat(_.isClass).symbol
985+
986+
/** The opaque type with the same (type-) name as this module or module class,
987+
* and which is also defined in the same scope and compilation unit.
988+
* NoSymbol if this type does not exist.
989+
*/
990+
final def companionOpaqueType(implicit ctx: Context): Symbol =
991+
companionType(nme.COMPANION_TYPE_METHOD).suchThat(_.is(Opaque)).symbol
992+
984993
final def scalacLinkedClass(implicit ctx: Context): Symbol =
985994
if (this is ModuleClass) companionNamed(effectiveName.toTypeName)
986995
else if (this.isClass) companionNamed(effectiveName.moduleClassName).sourceModule.moduleClass

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

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -743,8 +743,14 @@ class TreeUnpickler(reader: TastyReader,
743743
def isCodefined =
744744
roots.contains(companion.denot) == seenRoots.contains(companion)
745745
if (companion.exists && isCodefined) {
746-
if (sym is Flags.ModuleClass) sym.registerCompanionMethod(nme.COMPANION_CLASS_METHOD, companion)
747-
else sym.registerCompanionMethod(nme.COMPANION_MODULE_METHOD, companion)
746+
if (sym is Module) {
747+
if (companion.isClass)
748+
sym.registerCompanionMethod(nme.COMPANION_CLASS_METHOD, companion)
749+
else if (companion.is(Opaque))
750+
sym.registerCompanionMethod(nme.COMPANION_TYPE_METHOD, companion)
751+
}
752+
else
753+
sym.registerCompanionMethod(nme.COMPANION_MODULE_METHOD, companion)
748754
}
749755
TypeDef(readTemplate(localCtx))
750756
} else {

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

Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -603,22 +603,24 @@ class Namer { typer: Typer =>
603603
def createLinks(classTree: TypeDef, moduleTree: TypeDef)(implicit ctx: Context) = {
604604
val claz = ctx.effectiveScope.lookup(classTree.name)
605605
val modl = ctx.effectiveScope.lookup(moduleTree.name)
606-
if (claz.isClass && modl.isClass) {
607-
ctx.synthesizeCompanionMethod(nme.COMPANION_CLASS_METHOD, claz, modl).entered
608-
ctx.synthesizeCompanionMethod(nme.COMPANION_MODULE_METHOD, modl, claz).entered
609-
}
606+
if (modl.isClass)
607+
if (claz.isClass) {
608+
ctx.synthesizeCompanionMethod(nme.COMPANION_CLASS_METHOD, claz, modl).entered
609+
ctx.synthesizeCompanionMethod(nme.COMPANION_MODULE_METHOD, modl, claz).entered
610+
}
611+
else if (claz.is(Opaque))
612+
ctx.synthesizeCompanionMethod(nme.COMPANION_TYPE_METHOD, claz, modl).entered
610613
}
611614

612615
def createCompanionLinks(implicit ctx: Context): Unit = {
613616
val classDef = mutable.Map[TypeName, TypeDef]()
614617
val moduleDef = mutable.Map[TypeName, TypeDef]()
615618

616-
def updateCache(cdef: TypeDef): Unit = {
617-
if (!cdef.isClassDef || cdef.mods.is(Package)) return
618-
619-
if (cdef.mods.is(ModuleClass)) moduleDef(cdef.name) = cdef
620-
else classDef(cdef.name) = cdef
621-
}
619+
def updateCache(cdef: TypeDef): Unit =
620+
if (cdef.isClassDef && !cdef.mods.is(Package) || cdef.mods.is(Opaque)) {
621+
if (cdef.mods.is(ModuleClass)) moduleDef(cdef.name) = cdef
622+
else classDef(cdef.name) = cdef
623+
}
622624

623625
for (stat <- stats)
624626
expanded(stat) match {

0 commit comments

Comments
 (0)