Skip to content

Commit cf55ddb

Browse files
committed
Polish Synthetics.scala
1 parent e15d31c commit cf55ddb

File tree

1 file changed

+36
-25
lines changed

1 file changed

+36
-25
lines changed

compiler/src/dotty/tools/dotc/cc/Synthetics.scala

Lines changed: 36 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,10 @@ package cc
55
import core.*
66
import Symbols.*, SymDenotations.*, Contexts.*, Flags.*, Types.*, Decorators.*
77
import StdNames.nme
8+
import Names.Name
89
import NameKinds.DefaultGetterName
10+
import Phases.checkCapturesPhase
11+
import config.Printers.capt
912

1013
/** Classification and transformation methods for synthetic
1114
* case class methods that need to be treated specially.
@@ -14,17 +17,14 @@ import NameKinds.DefaultGetterName
1417
* compilation.
1518
*/
1619
object Synthetics:
17-
def isSyntheticCopyMethod(sym: SymDenotation)(using Context) =
20+
private def isSyntheticCopyMethod(sym: SymDenotation)(using Context) =
1821
sym.name == nme.copy && sym.is(Synthetic) && sym.owner.isClass && sym.owner.is(Case)
1922

20-
def isSyntheticApplyMethod(sym: SymDenotation)(using Context) =
21-
sym.name == nme.apply && sym.is(Synthetic) && sym.owner.is(Module) && sym.owner.companionClass.is(Case)
23+
private def isSyntheticCompanionMethod(sym: SymDenotation, names: Name*)(using Context): Boolean =
24+
names.contains(sym.name) && sym.is(Synthetic) && sym.owner.is(Module) && sym.owner.companionClass.is(Case)
2225

23-
def isSyntheticUnapplyMethod(sym: SymDenotation)(using Context) =
24-
sym.name == nme.unapply && sym.is(Synthetic) && sym.owner.is(Module) && sym.owner.companionClass.is(Case)
25-
26-
def isSyntheticCopyDefaultGetterMethod(sym: SymDenotation)(using Context) = sym.name match
27-
case DefaultGetterName(nme.copy, _) => sym.is(Synthetic)
26+
private def isSyntheticCopyDefaultGetterMethod(sym: SymDenotation)(using Context) = sym.name match
27+
case DefaultGetterName(nme.copy, _) => sym.is(Synthetic) && sym.owner.isClass && sym.owner.is(Case)
2828
case _ => false
2929

3030
/** Is `sym` a synthetic apply, copy, or copy default getter method?
@@ -33,8 +33,7 @@ object Synthetics:
3333
*/
3434
def needsTransform(sym: SymDenotation)(using Context): Boolean =
3535
isSyntheticCopyMethod(sym)
36-
|| isSyntheticApplyMethod(sym)
37-
|| isSyntheticUnapplyMethod(sym)
36+
|| isSyntheticCompanionMethod(sym, nme.apply, nme.unapply)
3837
|| isSyntheticCopyDefaultGetterMethod(sym)
3938

4039
/** Method is excluded from regular capture checking.
@@ -48,14 +47,20 @@ object Synthetics:
4847
&& sym.owner.isClass
4948
&& ( defn.caseClassSynthesized.exists(
5049
ccsym => sym.overriddenSymbol(ccsym.owner.asClass) == ccsym)
51-
|| sym.name == nme.fromProduct
52-
|| needsTransform(sym)
53-
)
54-
55-
/** Add capture dependencies to the type of `apply` or `copy` method of a case class */
50+
|| isSyntheticCompanionMethod(sym, nme.fromProduct)
51+
|| needsTransform(sym))
52+
53+
/** Add capture dependencies to the type of the `apply` or `copy` method of a case class.
54+
* An apply method in a case class like this:
55+
* case class CC(a: {d} A, b: B, {*} c: C)
56+
* would get type
57+
* def apply(a': {d} A, b: B, {*} c': C): {a', c'} CC { val a = {a'} A, val c = {c'} C }
58+
* where `'` is used to indicate the difference between parameter symbol and refinement name.
59+
* Analogous for the copy method.
60+
*/
5661
private def addCaptureDeps(info: Type)(using Context): Type = info match
5762
case info: MethodType =>
58-
val trackedParams = info.paramRefs.filter(atPhase(ctx.phase.next)(_.isTracked))
63+
val trackedParams = info.paramRefs.filter(atPhase(checkCapturesPhase)(_.isTracked))
5964
def augmentResult(tp: Type): Type = tp match
6065
case tp: MethodOrPoly =>
6166
tp.derivedLambdaType(resType = augmentResult(tp.resType))
@@ -67,7 +72,8 @@ object Synthetics:
6772
CaptureSet(pref)))
6873
}
6974
CapturingType(refined, CaptureSet(trackedParams*))
70-
if trackedParams.isEmpty then info else augmentResult(info)
75+
if trackedParams.isEmpty then info
76+
else augmentResult(info).showing(i"augment apply/copy type $info to $result", capt)
7177
case info: PolyType =>
7278
info.derivedLambdaType(resType = addCaptureDeps(info.resType))
7379
case _ =>
@@ -115,6 +121,7 @@ object Synthetics:
115121
case _ =>
116122
info
117123

124+
/** Augment an unapply of type `(x: C): D` to `(x: {*} C): {x} D` */
118125
private def addUnapplyCaptures(info: Type)(using Context): Type = info match
119126
case info: MethodType =>
120127
val paramInfo :: Nil = info.paramInfos: @unchecked
@@ -127,9 +134,11 @@ object Synthetics:
127134
case _ =>
128135
CapturingType(tp, CaptureSet(trackedParam))
129136
info.derivedLambdaType(paramInfos = newParamInfo :: Nil, resType = newResult(info.resType))
137+
.showing(i"augment unapply type $info to $result", capt)
130138
case info: PolyType =>
131139
info.derivedLambdaType(resType = addUnapplyCaptures(info.resType))
132140

141+
/** Drop added capture information from the type of an `unapply` */
133142
private def dropUnapplyCaptures(info: Type)(using Context): Type = info match
134143
case info: MethodType =>
135144
val CapturingType(oldParamInfo, _) :: Nil = info.paramInfos: @unchecked
@@ -142,28 +151,30 @@ object Synthetics:
142151
case info: PolyType =>
143152
info.derivedLambdaType(resType = dropUnapplyCaptures(info.resType))
144153

145-
/** If `sym` refers to a synthetic apply, copy, or copy default getter method
154+
/** If `sym` refers to a synthetic apply, unapply, copy, or copy default getter method
146155
* of a case class, transform it to account for capture information.
156+
* The method is run in phase CheckCaptures.Pre
147157
* @pre needsTransform(sym)
148158
*/
149159
def transformToCC(sym: SymDenotation)(using Context): SymDenotation = sym.name match
150-
case DefaultGetterName(nme.copy, n) if sym.is(Synthetic) && sym.owner.is(Case) =>
160+
case DefaultGetterName(nme.copy, n) =>
151161
sym.copySymDenotation(info = addDefaultGetterCapture(sym.info, sym.owner, n))
152162
case nme.unapply =>
153163
sym.copySymDenotation(info = addUnapplyCaptures(sym.info))
154-
case _ =>
164+
case nme.apply | nme.copy =>
155165
sym.copySymDenotation(info = addCaptureDeps(sym.info))
156166

157-
/** If `sym` refers to a synthetic apply, copy, or copy default getter method
167+
168+
/** If `sym` refers to a synthetic apply, unapply, copy, or copy default getter method
158169
* of a case class, transform it back to what it was before the CC phase.
159170
* @pre needsTransform(sym)
160171
*/
161-
def transformFromCC(sym: SymDenotation)(using Context): SymDenotation =
162-
if isSyntheticCopyDefaultGetterMethod(sym) then
172+
def transformFromCC(sym: SymDenotation)(using Context): SymDenotation = sym.name match
173+
case DefaultGetterName(nme.copy, n) =>
163174
sym.copySymDenotation(info = dropDefaultGetterCapture(sym.info))
164-
else if sym.name == nme.unapply then
175+
case nme.unapply =>
165176
sym.copySymDenotation(info = dropUnapplyCaptures(sym.info))
166-
else
177+
case nme.apply | nme.copy =>
167178
sym.copySymDenotation(info = dropCaptureDeps(sym.info))
168179

169180
end Synthetics

0 commit comments

Comments
 (0)