Skip to content

Commit

Permalink
Allow classOf[Foo.type] if Foo is an object
Browse files Browse the repository at this point in the history
And use this in SyntheticMethods instead of the
impossible-to-write-in-user-code `classOf[Foo$]`. This is necessary if
we want decompilation to produce valid source code for objects.

Note that the decompilation printer is currently wrong here and will
print `classOf[Foo]` instead of `classOf[Foo.type]`.
  • Loading branch information
smarter committed Jan 26, 2019
1 parent 03ed10e commit 3149a0c
Show file tree
Hide file tree
Showing 4 changed files with 10 additions and 4 deletions.
2 changes: 1 addition & 1 deletion compiler/src/dotty/tools/dotc/printing/PlainPrinter.scala
Original file line number Diff line number Diff line change
Expand Up @@ -471,7 +471,7 @@ class PlainPrinter(_ctx: Context) extends Printer {

def toText(const: Constant): Text = const.tag match {
case StringTag => stringText("\"" + escapedString(const.value.toString) + "\"")
case ClazzTag => "classOf[" ~ toText(const.typeValue.classSymbol) ~ "]"
case ClazzTag => "classOf[" ~ toText(const.typeValue) ~ "]"
case CharTag => literalText(s"'${escapedChar(const.charValue)}'")
case LongTag => literalText(const.longValue.toString + "L")
case EnumTag => literalText(const.symbolValue.name.toString)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -264,7 +264,7 @@ class SyntheticMethods(thisPhase: DenotTransformer) {
/** If this is a serializable static object `Foo`, add the method:
*
* private def writeReplace(): AnyRef =
* new scala.runtime.ModuleSerializationProxy(classOf[Foo$])
* new scala.runtime.ModuleSerializationProxy(classOf[Foo.type])
*
* unless an implementation already exists, otherwise do nothing.
*/
Expand All @@ -280,7 +280,7 @@ class SyntheticMethods(thisPhase: DenotTransformer) {
DefDef(writeReplace,
_ => New(defn.ModuleSerializationProxyType,
defn.ModuleSerializationProxyConstructor,
List(Literal(Constant(clazz.typeRef)))))
List(Literal(Constant(clazz.sourceModule.termRef)))))
.withSpan(ctx.owner.span.focus))
}
else
Expand Down
3 changes: 2 additions & 1 deletion compiler/src/dotty/tools/dotc/typer/Applications.scala
Original file line number Diff line number Diff line change
Expand Up @@ -907,7 +907,8 @@ trait Applications extends Compatibility { self: Typer with Dynamic =>
if (typedArgs.length <= pt.paramInfos.length && !isNamed)
if (typedFn.symbol == defn.Predef_classOf && typedArgs.nonEmpty) {
val arg = typedArgs.head
checkClassType(arg.tpe, arg.sourcePos, traitReq = false, stablePrefixReq = false)
if (!arg.symbol.is(Module)) // Allow `classOf[Foo.type]` if `Foo` is an object
checkClassType(arg.tpe, arg.sourcePos, traitReq = false, stablePrefixReq = false)
}
case _ =>
}
Expand Down
5 changes: 5 additions & 0 deletions tests/run/classof-object.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
object Test {
def main(args: Array[String]): Unit = {
assert(classOf[Test.type] == Test.getClass)
}
}

0 comments on commit 3149a0c

Please sign in to comment.