Skip to content

Commit 34853b3

Browse files
committed
Merge pull request #366 from smarter/fix/value-classes-methods
Fix the synthetic methods of value classes
2 parents 2e72811 + b1d6de2 commit 34853b3

File tree

4 files changed

+27
-8
lines changed

4 files changed

+27
-8
lines changed

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

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,9 @@ class SymUtils(val self: Symbol) extends AnyVal {
7979
def accessorNamed(name: TermName)(implicit ctx: Context): Symbol =
8080
self.owner.info.decl(name).suchThat(_ is Accessor).symbol
8181

82+
def termParamAccessors(implicit ctx: Context): List[Symbol] =
83+
self.info.decls.filter(_ is TermParamAccessor).toList
84+
8285
def caseAccessors(implicit ctx:Context) =
8386
self.info.decls.filter(_ is CaseAccessor).toList
8487

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

Lines changed: 22 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,11 @@ class SyntheticMethods extends MiniPhaseTransform with IdentityDenotTransformer
4949
*/
5050
def syntheticMethods(clazz: ClassSymbol)(implicit ctx: Context): List[Tree] = {
5151
val clazzType = clazz.typeRef
52-
lazy val accessors = clazz.caseAccessors
52+
lazy val accessors =
53+
if (isDerivedValueClass(clazz))
54+
clazz.termParamAccessors
55+
else
56+
clazz.caseAccessors
5357

5458
val symbolsToSynthesize: List[Symbol] =
5559
if (clazz.is(Case)) caseSymbols
@@ -72,7 +76,8 @@ class SyntheticMethods extends MiniPhaseTransform with IdentityDenotTransformer
7276
ref(defn.runtimeMethod("_" + sym.name.toString)).appliedToArgs(This(clazz) :: vrefss.head)
7377

7478
def syntheticRHS(implicit ctx: Context): List[List[Tree]] => Tree = synthetic.name match {
75-
case nme.hashCode_ => vrefss => hashCodeBody
79+
case nme.hashCode_ if isDerivedValueClass(clazz) => vrefss => valueHashCodeBody
80+
case nme.hashCode_ => vrefss => caseHashCodeBody
7681
case nme.toString_ => forwardToRuntime
7782
case nme.equals_ => vrefss => equalsBody(vrefss.head.head)
7883
case nme.canEqual_ => vrefss => canEqualBody(vrefss.head.head)
@@ -116,11 +121,24 @@ class SyntheticMethods extends MiniPhaseTransform with IdentityDenotTransformer
116121
}
117122
}
118123

124+
/** The class
125+
*
126+
* class C(x: T) extends AnyVal
127+
*
128+
* gets the hashCode method:
129+
*
130+
* def hashCode: Int = x.hashCode()
131+
*/
132+
def valueHashCodeBody(implicit ctx: Context): Tree = {
133+
assert(accessors.length == 1)
134+
ref(accessors.head).select(nme.hashCode_).ensureApplied
135+
}
136+
119137
/** The class
120138
*
121139
* case class C(x: T, y: T)
122140
*
123-
* get the hashCode method:
141+
* gets the hashCode method:
124142
*
125143
* def hashCode: Int = {
126144
* <synthetic> var acc: Int = 0xcafebabe;
@@ -129,7 +147,7 @@ class SyntheticMethods extends MiniPhaseTransform with IdentityDenotTransformer
129147
* Statics.finalizeHash(acc, 2)
130148
* }
131149
*/
132-
def hashCodeBody(implicit ctx: Context): Tree = {
150+
def caseHashCodeBody(implicit ctx: Context): Tree = {
133151
val acc = ctx.newSymbol(ctx.owner, "acc".toTermName, Mutable | Synthetic, defn.IntType, coord = ctx.owner.pos)
134152
val accDef = ValDef(acc, Literal(Constant(0xcafebabe)))
135153
val mixes = for (accessor <- accessors.toList) yield

tests/pos/extmethods.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
trait That1[A]
2-
class T[A, This <: That1[A]] extends AnyVal {
2+
class T[A, This <: That1[A]](val x: Int) extends AnyVal {
33
self: This =>
44
var next: This = _
55
final def loop(x: This, cnt: Int): Int = loop(x, cnt + 1)

tests/pos/i143.scala

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,7 @@ import dotty.tools.dotc.core.Denotations._
55
import dotty.tools.dotc.core.Symbols._
66
import dotty.tools.dotc.core.Contexts._
77

8-
class TC5 extends AnyVal {
9-
implicit val ctx: Context = ???
10-
8+
class TC5(val ctx: Context) extends AnyVal {
119
def candidates(mbr: SingleDenotation): Boolean = {
1210
mbr.symbol.denot(ctx).exists
1311
}

0 commit comments

Comments
 (0)