Skip to content
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
59 changes: 42 additions & 17 deletions src/dotty/tools/dotc/transform/FirstTransform.scala
Original file line number Diff line number Diff line change
Expand Up @@ -44,15 +44,32 @@ class FirstTransform extends MiniPhaseTransform with IdentityDenotTransformer wi
this
}

def transformInfo(tp: Type, sym: Symbol)(implicit ctx: Context): Type = tp

override def checkPostCondition(tree: Tree)(implicit ctx: Context): Unit = tree match {
case Select(qual, _) if tree.symbol.exists =>
assert(qual.tpe derivesFrom tree.symbol.owner, i"non member selection of ${tree.symbol.showLocated} from ${qual.tpe}")
case _: TypeTree =>
case _: Import | _: NamedArg | _: TypTree =>
assert(false, i"illegal tree: $tree")
case _ =>
def transformInfo(tp: Type, sym: Symbol)(implicit ctx: Context): Type = {
tp match {
//create companions for value classes that are not from currently compiled source file
case tp@ClassInfo(_, cls, _, decls, _)
if (ValueClasses.isDerivedValueClass(cls)) &&
!sym.isDefinedInCurrentRun && sym.scalacLinkedClass == NoSymbol =>
println(s"needsCompanion for: $sym")
val newDecls = decls.cloneScope
val (modul, mcMethod, symMethod) = newCompanion(sym.name.toTermName, sym)
modul.entered
mcMethod.entered
newDecls.enter(symMethod)
tp.derivedClassInfo(decls = newDecls)
case _ => tp
}
}

override def checkPostCondition(tree: Tree)(implicit ctx: Context): Unit = {
tree match {
case Select(qual, _) if tree.symbol.exists =>
assert(qual.tpe derivesFrom tree.symbol.owner, i"non member selection of ${tree.symbol.showLocated} from ${qual.tpe}")
case _: TypeTree =>
case _: Import | _: NamedArg | _: TypTree =>
assert(false, i"illegal tree: $tree")
case _ =>
}
}

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

def newCompanion(name: TermName, forClass: Symbol): Thicket = {
val modul = ctx.newCompleteModuleSymbol(ctx.owner, name, Synthetic, Synthetic,
defn.ObjectType :: Nil, Scopes.newScope)
val mc = modul.moduleClass
def registerCompanion(name: TermName, forClass: Symbol): TermSymbol = {
val (modul, mcCompanion, classCompanion) = newCompanion(name, forClass)
if (ctx.owner.isClass) modul.enteredAfter(thisTransformer)
ctx.synthesizeCompanionMethod(nme.COMPANION_CLASS_METHOD, forClass, mc).enteredAfter(thisTransformer)
ctx.synthesizeCompanionMethod(nme.COMPANION_MODULE_METHOD, mc, forClass).enteredAfter(thisTransformer)
ModuleDef(modul, Nil)
mcCompanion.enteredAfter(thisTransformer)
classCompanion.enteredAfter(thisTransformer)
modul
}

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

addMissingCompanions(reorder(stats))
}

private def newCompanion(name: TermName, forClass: Symbol)(implicit ctx: Context) = {
val modul = ctx.newCompleteModuleSymbol(forClass.owner, name, Synthetic, Synthetic,
defn.ObjectType :: Nil, Scopes.newScope)
val mc = modul.moduleClass

val mcComp = ctx.synthesizeCompanionMethod(nme.COMPANION_CLASS_METHOD, forClass, mc)
val classComp = ctx.synthesizeCompanionMethod(nme.COMPANION_MODULE_METHOD, mc, forClass)
(modul, mcComp, classComp)
}

override def transformDefDef(ddef: DefDef)(implicit ctx: Context, info: TransformerInfo) = {
if (ddef.symbol.hasAnnotation(defn.NativeAnnot)) {
ddef.symbol.resetFlag(Deferred)
Expand Down
1 change: 1 addition & 0 deletions tests/pos/i1137-1/A_1.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
class A(val self: Double) extends AnyVal
3 changes: 3 additions & 0 deletions tests/pos/i1137-1/B_2.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
object B {
def foo: A = new A(1)
}
3 changes: 3 additions & 0 deletions tests/pos/i1137-2/A_1.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
object ATest {
class A(val self: Double) extends AnyVal
}
4 changes: 4 additions & 0 deletions tests/pos/i1137-2/B_2.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
object B {
import ATest._
def foo: A = new A(1)
}
2 changes: 2 additions & 0 deletions tests/pos/i1137-3/A_1.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
class A(val self: Double) extends AnyVal
object A
3 changes: 3 additions & 0 deletions tests/pos/i1137-3/B_2.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
object B {
def foo: A = new A(1)
}