Skip to content

Commit

Permalink
Support inline overrides in value classes (#16523)
Browse files Browse the repository at this point in the history
Fixes #15725

Three fixes:

 - Don't make extension method copies of inline methods
- Make retainedBody methods discoverable by entering them in their
parent scope, so that they get an extension method
 - But strip the retainedBody in the extension method
  • Loading branch information
odersky authored Jan 17, 2023
2 parents d99d9bf + ac10053 commit 4cdd19b
Show file tree
Hide file tree
Showing 5 changed files with 18 additions and 5 deletions.
4 changes: 2 additions & 2 deletions compiler/src/dotty/tools/dotc/inlines/Inlines.scala
Original file line number Diff line number Diff line change
Expand Up @@ -229,8 +229,8 @@ object Inlines:

val retainer = meth.copy(
name = BodyRetainerName(meth.name),
flags = meth.flags &~ (Inline | Macro | Override) | Private,
coord = mdef.rhs.span.startPos).asTerm
flags = (meth.flags &~ (Inline | Macro | Override | AbsOverride)) | Private,
coord = mdef.rhs.span.startPos).asTerm.entered
retainer.deriveTargetNameAnnotation(meth, name => BodyRetainerName(name.asTermName))
DefDef(retainer, prefss =>
inlineCall(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import core._
import Types._, Contexts._, Names._, Flags._, DenotTransformers._, Phases._
import SymDenotations._, Symbols._, StdNames._, Denotations._
import TypeErasure.{ valueErasure, ErasedValueType }
import NameKinds.ExtMethName
import NameKinds.{ExtMethName, BodyRetainerName}
import Decorators._
import TypeUtils._

Expand Down Expand Up @@ -79,7 +79,7 @@ class ExtensionMethods extends MiniPhase with DenotTransformer with FullParamete
// because it adds extension methods before pickling.
if (!(valueClass.is(Scala2x)))
for (decl <- valueClass.classInfo.decls)
if (isMethodWithExtension(decl))
if isMethodWithExtension(decl) then
enterInModuleClass(createExtensionMethod(decl, moduleClassSym.symbol))

// Create synthetic methods to cast values between the underlying type
Expand Down Expand Up @@ -179,7 +179,10 @@ object ExtensionMethods {

/** Name of the extension method that corresponds to given instance method `meth`. */
def extensionName(imeth: Symbol)(using Context): TermName =
ExtMethName(imeth.name.asTermName)
ExtMethName(
imeth.name.asTermName match
case BodyRetainerName(name) => name
case name => name)

/** Return the extension method that corresponds to given instance method `meth`. */
def extensionMethod(imeth: Symbol)(using Context): TermSymbol =
Expand Down
1 change: 1 addition & 0 deletions compiler/src/dotty/tools/dotc/transform/ValueClasses.scala
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ object ValueClasses {
isDerivedValueClass(d.owner) &&
!d.isConstructor &&
!d.symbol.isSuperAccessor &&
!d.isInlineMethod &&
!d.is(Macro)
}

Expand Down
1 change: 1 addition & 0 deletions tests/run/i15725.check
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
2 meters
8 changes: 8 additions & 0 deletions tests/run/i15725.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
class ToString(d: Int) extends AnyVal :
inline override def toString():String = s"$d meters"

@main def Test =
val ts = ToString(2)
val a: Any = ts
println(a)

0 comments on commit 4cdd19b

Please sign in to comment.