Skip to content

Commit 635094a

Browse files
VladimirNikodersky
authored andcommitted
Fix for separate compilation with value class issue (missing companion object - #1137)
1 parent fdf83b2 commit 635094a

File tree

7 files changed

+58
-17
lines changed

7 files changed

+58
-17
lines changed

src/dotty/tools/dotc/transform/FirstTransform.scala

Lines changed: 42 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -44,15 +44,32 @@ class FirstTransform extends MiniPhaseTransform with IdentityDenotTransformer wi
4444
this
4545
}
4646

47-
def transformInfo(tp: Type, sym: Symbol)(implicit ctx: Context): Type = tp
48-
49-
override def checkPostCondition(tree: Tree)(implicit ctx: Context): Unit = tree match {
50-
case Select(qual, _) if tree.symbol.exists =>
51-
assert(qual.tpe derivesFrom tree.symbol.owner, i"non member selection of ${tree.symbol.showLocated} from ${qual.tpe}")
52-
case _: TypeTree =>
53-
case _: Import | _: NamedArg | _: TypTree =>
54-
assert(false, i"illegal tree: $tree")
55-
case _ =>
47+
def transformInfo(tp: Type, sym: Symbol)(implicit ctx: Context): Type = {
48+
tp match {
49+
//create companions for value classes that are not from currently compiled source file
50+
case tp@ClassInfo(_, cls, _, decls, _)
51+
if (ValueClasses.isDerivedValueClass(cls)) &&
52+
!sym.isDefinedInCurrentRun && sym.scalacLinkedClass == NoSymbol =>
53+
println(s"needsCompanion for: $sym")
54+
val newDecls = decls.cloneScope
55+
val (modul, mcMethod, symMethod) = newCompanion(sym.name.toTermName, sym)
56+
modul.entered
57+
mcMethod.entered
58+
newDecls.enter(symMethod)
59+
tp.derivedClassInfo(decls = newDecls)
60+
case _ => tp
61+
}
62+
}
63+
64+
override def checkPostCondition(tree: Tree)(implicit ctx: Context): Unit = {
65+
tree match {
66+
case Select(qual, _) if tree.symbol.exists =>
67+
assert(qual.tpe derivesFrom tree.symbol.owner, i"non member selection of ${tree.symbol.showLocated} from ${qual.tpe}")
68+
case _: TypeTree =>
69+
case _: Import | _: NamedArg | _: TypTree =>
70+
assert(false, i"illegal tree: $tree")
71+
case _ =>
72+
}
5673
}
5774

5875
/** Reorder statements so that module classes always come after their companion classes, add missing companion classes */
@@ -81,14 +98,12 @@ class FirstTransform extends MiniPhaseTransform with IdentityDenotTransformer wi
8198
case Nil => Nil
8299
}
83100

84-
def newCompanion(name: TermName, forClass: Symbol): Thicket = {
85-
val modul = ctx.newCompleteModuleSymbol(ctx.owner, name, Synthetic, Synthetic,
86-
defn.ObjectType :: Nil, Scopes.newScope)
87-
val mc = modul.moduleClass
101+
def registerCompanion(name: TermName, forClass: Symbol): TermSymbol = {
102+
val (modul, mcCompanion, classCompanion) = newCompanion(name, forClass)
88103
if (ctx.owner.isClass) modul.enteredAfter(thisTransformer)
89-
ctx.synthesizeCompanionMethod(nme.COMPANION_CLASS_METHOD, forClass, mc).enteredAfter(thisTransformer)
90-
ctx.synthesizeCompanionMethod(nme.COMPANION_MODULE_METHOD, mc, forClass).enteredAfter(thisTransformer)
91-
ModuleDef(modul, Nil)
104+
mcCompanion.enteredAfter(thisTransformer)
105+
classCompanion.enteredAfter(thisTransformer)
106+
modul
92107
}
93108

94109
def addMissingCompanions(stats: List[Tree]): List[Tree] = stats map {
@@ -101,13 +116,23 @@ class FirstTransform extends MiniPhaseTransform with IdentityDenotTransformer wi
101116
false
102117
}
103118
val uniqueName = if (nameClash) objName.avoidClashName else objName
104-
Thicket(stat :: newCompanion(uniqueName, stat.symbol).trees)
119+
Thicket(stat :: ModuleDef(registerCompanion(uniqueName, stat.symbol), Nil).trees)
105120
case stat => stat
106121
}
107122

108123
addMissingCompanions(reorder(stats))
109124
}
110125

126+
private def newCompanion(name: TermName, forClass: Symbol)(implicit ctx: Context) = {
127+
val modul = ctx.newCompleteModuleSymbol(forClass.owner, name, Synthetic, Synthetic,
128+
defn.ObjectType :: Nil, Scopes.newScope)
129+
val mc = modul.moduleClass
130+
131+
val mcComp = ctx.synthesizeCompanionMethod(nme.COMPANION_CLASS_METHOD, forClass, mc)
132+
val classComp = ctx.synthesizeCompanionMethod(nme.COMPANION_MODULE_METHOD, mc, forClass)
133+
(modul, mcComp, classComp)
134+
}
135+
111136
override def transformDefDef(ddef: DefDef)(implicit ctx: Context, info: TransformerInfo) = {
112137
if (ddef.symbol.hasAnnotation(defn.NativeAnnot)) {
113138
ddef.symbol.resetFlag(Deferred)

tests/pos/i1137-1/A_1.scala

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
class A(val self: Double) extends AnyVal

tests/pos/i1137-1/B_2.scala

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
object B {
2+
def foo: A = new A(1)
3+
}

tests/pos/i1137-2/A_1.scala

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
object ATest {
2+
class A(val self: Double) extends AnyVal
3+
}

tests/pos/i1137-2/B_2.scala

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
object B {
2+
import ATest._
3+
def foo: A = new A(1)
4+
}

tests/pos/i1137-3/A_1.scala

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
class A(val self: Double) extends AnyVal
2+
object A

tests/pos/i1137-3/B_2.scala

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
object B {
2+
def foo: A = new A(1)
3+
}

0 commit comments

Comments
 (0)