@@ -56,177 +56,155 @@ object Synthetics:
56
56
|| isSyntheticCompanionMethod(sym, nme.fromProduct)
57
57
|| needsTransform(sym))
58
58
59
- /** Add capture dependencies to the type of the `apply` or `copy` method of a case class.
60
- * An apply method in a case class like this:
61
- * case class CC(a: {d} A, b: B, {cap} c: C)
62
- * would get type
63
- * def apply(a': {d} A, b: B, {cap} c': C): {a', c'} CC { val a = {a'} A, val c = {c'} C }
64
- * where `'` is used to indicate the difference between parameter symbol and refinement name.
65
- * Analogous for the copy method.
59
+ /** Transform the type of a method either to its type under capture checking
60
+ * or back to its previous type.
61
+ * @param sym The method to transform @pre needsTransform(sym) must hold.
62
+ * @param toCC Whether to transform the type to capture checking or back.
66
63
*/
67
- private def addCaptureDeps (info : Type )(using Context ): Type = info match
68
- case info : MethodType =>
69
- val trackedParams = info.paramRefs.filter(atPhase(checkCapturesPhase)(_.isTracked))
70
- def augmentResult (tp : Type ): Type = tp match
71
- case tp : MethodOrPoly =>
72
- tp.derivedLambdaType(resType = augmentResult(tp.resType))
73
- case _ =>
74
- val refined = trackedParams.foldLeft(tp) { (parent, pref) =>
75
- RefinedType (parent, pref.paramName,
76
- CapturingType (
77
- atPhase(ctx.phase.next)(pref.underlying.stripCapturing),
78
- CaptureSet (pref)))
79
- }
80
- CapturingType (refined, CaptureSet (trackedParams* ))
81
- if trackedParams.isEmpty then info
82
- else augmentResult(info).showing(i " augment apply/copy type $info to $result" , capt)
83
- case info : PolyType =>
84
- info.derivedLambdaType(resType = addCaptureDeps(info.resType))
85
- case _ =>
86
- info
87
-
88
- /** Drop capture dependencies from the type of `apply` or `copy` method of a case class */
89
- private def dropCaptureDeps (tp : Type )(using Context ): Type = tp match
90
- case tp : MethodOrPoly =>
91
- tp.derivedLambdaType(resType = dropCaptureDeps(tp.resType))
92
- case CapturingType (parent, _) =>
93
- dropCaptureDeps(parent)
94
- case RefinedType (parent, _, _) =>
95
- dropCaptureDeps(parent)
96
- case _ =>
97
- tp
98
-
99
- /** Add capture information to the type of the default getter of a case class copy method */
100
- private def addDefaultGetterCapture (info : Type , owner : Symbol , idx : Int )(using Context ): Type = info match
101
- case info : MethodOrPoly =>
102
- info.derivedLambdaType(resType = addDefaultGetterCapture(info.resType, owner, idx))
103
- case info : ExprType =>
104
- info.derivedExprType(addDefaultGetterCapture(info.resType, owner, idx))
105
- case EventuallyCapturingType (parent, _) =>
106
- addDefaultGetterCapture(parent, owner, idx)
107
- case info @ AnnotatedType (parent, annot) =>
108
- info.derivedAnnotatedType(addDefaultGetterCapture(parent, owner, idx), annot)
109
- case _ if idx < owner.asClass.paramGetters.length =>
110
- val param = owner.asClass.paramGetters(idx)
111
- val pinfo = param.info
112
- atPhase(ctx.phase.next) {
113
- if pinfo.captureSet.isAlwaysEmpty then info
114
- else CapturingType (pinfo.stripCapturing, CaptureSet (param.termRef))
115
- }
116
- case _ =>
117
- info
118
-
119
- /** Drop capture information from the type of the default getter of a case class copy method */
120
- private def dropDefaultGetterCapture (info : Type )(using Context ): Type = info match
121
- case info : MethodOrPoly =>
122
- info.derivedLambdaType(resType = dropDefaultGetterCapture(info.resType))
123
- case CapturingType (parent, _) =>
124
- parent
125
- case info @ AnnotatedType (parent, annot) =>
126
- info.derivedAnnotatedType(dropDefaultGetterCapture(parent), annot)
127
- case _ =>
128
- info
129
-
130
- /** Augment an unapply of type `(x: C): D` to `(x: {cap} C): {x} D` */
131
- private def addUnapplyCaptures (info : Type )(using Context ): Type = info match
132
- case info : MethodType =>
133
- val paramInfo :: Nil = info.paramInfos: @ unchecked
134
- val newParamInfo =
135
- CapturingType (paramInfo, CaptureSet .universal)
136
- val trackedParam = info.paramRefs.head
137
- def newResult (tp : Type ): Type = tp match
138
- case tp : MethodOrPoly =>
139
- tp.derivedLambdaType(resType = newResult(tp.resType))
140
- case _ =>
141
- CapturingType (tp, CaptureSet (trackedParam))
142
- info.derivedLambdaType(paramInfos = newParamInfo :: Nil , resType = newResult(info.resType))
143
- .showing(i " augment unapply type $info to $result" , capt)
144
- case info : PolyType =>
145
- info.derivedLambdaType(resType = addUnapplyCaptures(info.resType))
146
-
147
- /** Drop added capture information from the type of an `unapply` */
148
- private def dropUnapplyCaptures (info : Type )(using Context ): Type = info match
149
- case info : MethodType =>
150
- info.paramInfos match
151
- case CapturingType (oldParamInfo, _) :: Nil =>
152
- def oldResult (tp : Type ): Type = tp match
64
+ def transform (sym : SymDenotation , toCC : Boolean )(using Context ): SymDenotation =
65
+
66
+ /** Add capture dependencies to the type of the `apply` or `copy` method of a case class.
67
+ * An apply method in a case class like this:
68
+ * case class CC(a: A^{d}, b: B, c: C^{cap})
69
+ * would get type
70
+ * def apply(a': A^{d}, b: B, c': C^{cap}): CC^{a', c'} { val a = A^{a'}, val c = C^{c'} }
71
+ * where `'` is used to indicate the difference between parameter symbol and refinement name.
72
+ * Analogous for the copy method.
73
+ */
74
+ def addCaptureDeps (info : Type ): Type = info match
75
+ case info : MethodType =>
76
+ val trackedParams = info.paramRefs.filter(atPhase(checkCapturesPhase)(_.isTracked))
77
+ def augmentResult (tp : Type ): Type = tp match
78
+ case tp : MethodOrPoly =>
79
+ tp.derivedLambdaType(resType = augmentResult(tp.resType))
80
+ case _ =>
81
+ val refined = trackedParams.foldLeft(tp) { (parent, pref) =>
82
+ RefinedType (parent, pref.paramName,
83
+ CapturingType (
84
+ atPhase(ctx.phase.next)(pref.underlying.stripCapturing),
85
+ CaptureSet (pref)))
86
+ }
87
+ CapturingType (refined, CaptureSet (trackedParams* ))
88
+ if trackedParams.isEmpty then info
89
+ else augmentResult(info).showing(i " augment apply/copy type $info to $result" , capt)
90
+ case info : PolyType =>
91
+ info.derivedLambdaType(resType = addCaptureDeps(info.resType))
92
+ case _ =>
93
+ info
94
+
95
+ /** Drop capture dependencies from the type of `apply` or `copy` method of a case class */
96
+ def dropCaptureDeps (tp : Type ): Type = tp match
97
+ case tp : MethodOrPoly =>
98
+ tp.derivedLambdaType(resType = dropCaptureDeps(tp.resType))
99
+ case CapturingType (parent, _) =>
100
+ dropCaptureDeps(parent)
101
+ case RefinedType (parent, _, _) =>
102
+ dropCaptureDeps(parent)
103
+ case _ =>
104
+ tp
105
+
106
+ /** Add capture information to the type of the default getter of a case class copy method
107
+ * if toCC = true, or remove the added info again if toCC = false.
108
+ */
109
+ def transformDefaultGetterCaptures (info : Type , owner : Symbol , idx : Int )(using Context ): Type = info match
110
+ case info : MethodOrPoly =>
111
+ info.derivedLambdaType(resType = transformDefaultGetterCaptures(info.resType, owner, idx))
112
+ case info : ExprType =>
113
+ info.derivedExprType(transformDefaultGetterCaptures(info.resType, owner, idx))
114
+ case EventuallyCapturingType (parent, _) =>
115
+ if toCC then transformDefaultGetterCaptures(parent, owner, idx)
116
+ else parent
117
+ case info @ AnnotatedType (parent, annot) =>
118
+ info.derivedAnnotatedType(transformDefaultGetterCaptures(parent, owner, idx), annot)
119
+ case _ if toCC && idx < owner.asClass.paramGetters.length =>
120
+ val param = owner.asClass.paramGetters(idx)
121
+ val pinfo = param.info
122
+ atPhase(ctx.phase.next) {
123
+ if pinfo.captureSet.isAlwaysEmpty then info
124
+ else CapturingType (pinfo.stripCapturing, CaptureSet (param.termRef))
125
+ }
126
+ case _ =>
127
+ info
128
+
129
+ /** Augment an unapply of type `(x: C): D` to `(x: C^{cap}): D^{x}` if toCC is true,
130
+ * or remove the added capture sets again if toCC = false.
131
+ */
132
+ def transformUnapplyCaptures (info : Type )(using Context ): Type = info match
133
+ case info : MethodType =>
134
+ if toCC then
135
+ val paramInfo :: Nil = info.paramInfos: @ unchecked
136
+ val newParamInfo = CapturingType (paramInfo, CaptureSet .universal)
137
+ val trackedParam = info.paramRefs.head
138
+ def newResult (tp : Type ): Type = tp match
153
139
case tp : MethodOrPoly =>
154
- tp.derivedLambdaType(resType = oldResult(tp.resType))
155
- case CapturingType (tp, _) =>
156
- tp
157
- info.derivedLambdaType(paramInfos = oldParamInfo :: Nil , resType = oldResult(info.resType))
158
- case _ =>
159
- info
160
- case info : PolyType =>
161
- info.derivedLambdaType(resType = dropUnapplyCaptures(info.resType))
162
-
163
- private def transformComposeCaptures (symd : SymDenotation , toCC : Boolean )(using Context ): Type =
164
- val (pt : PolyType ) = symd.info: @ unchecked
165
- val (mt : MethodType ) = pt.resType: @ unchecked
166
- val (enclThis : ThisType ) = symd.owner.thisType: @ unchecked
167
- val mt1 =
140
+ tp.derivedLambdaType(resType = newResult(tp.resType))
141
+ case _ =>
142
+ CapturingType (tp, CaptureSet (trackedParam))
143
+ info.derivedLambdaType(paramInfos = newParamInfo :: Nil , resType = newResult(info.resType))
144
+ .showing(i " augment unapply type $info to $result" , capt)
145
+ else info.paramInfos match
146
+ case CapturingType (oldParamInfo, _) :: Nil =>
147
+ def oldResult (tp : Type ): Type = tp match
148
+ case tp : MethodOrPoly =>
149
+ tp.derivedLambdaType(resType = oldResult(tp.resType))
150
+ case CapturingType (tp, _) =>
151
+ tp
152
+ info.derivedLambdaType(paramInfos = oldParamInfo :: Nil , resType = oldResult(info.resType))
153
+ case _ =>
154
+ info
155
+ case info : PolyType =>
156
+ info.derivedLambdaType(resType = transformUnapplyCaptures(info.resType))
157
+
158
+ def transformComposeCaptures (symd : SymDenotation ) =
159
+ val (pt : PolyType ) = symd.info: @ unchecked
160
+ val (mt : MethodType ) = pt.resType: @ unchecked
161
+ val (enclThis : ThisType ) = symd.owner.thisType: @ unchecked
162
+ val mt1 =
163
+ if toCC then
164
+ MethodType (mt.paramNames)(
165
+ mt1 => mt.paramInfos.map(_.capturing(CaptureSet .universal)),
166
+ mt1 => CapturingType (mt.resType, CaptureSet (enclThis, mt1.paramRefs.head)))
167
+ else
168
+ MethodType (mt.paramNames)(
169
+ mt1 => mt.paramInfos.map(_.stripCapturing),
170
+ mt1 => mt.resType.stripCapturing)
171
+ pt.derivedLambdaType(resType = mt1)
172
+
173
+ def transformCurriedTupledCaptures (symd : SymDenotation ) =
174
+ val (et : ExprType ) = symd.info: @ unchecked
175
+ val (enclThis : ThisType ) = symd.owner.thisType: @ unchecked
176
+ def mapFinalResult (tp : Type , f : Type => Type ): Type =
177
+ val defn .FunctionOf (args, res, isContextual) = tp : @ unchecked
178
+ if defn.isFunctionNType(res) then
179
+ defn.FunctionOf (args, mapFinalResult(res, f), isContextual)
180
+ else
181
+ f(tp)
182
+ val resType1 =
183
+ if toCC then
184
+ mapFinalResult(et.resType, CapturingType (_, CaptureSet (enclThis)))
185
+ else
186
+ et.resType.stripCapturing
187
+ ExprType (resType1)
188
+
189
+ def transformCompareCaptures =
168
190
if toCC then
169
- MethodType (mt.paramNames)(
170
- mt1 => mt.paramInfos.map(_.capturing(CaptureSet .universal)),
171
- mt1 => CapturingType (mt.resType, CaptureSet (enclThis, mt1.paramRefs.head)))
191
+ MethodType (defn.ObjectType .capturing(CaptureSet .universal) :: Nil , defn.BooleanType )
172
192
else
173
- MethodType (mt.paramNames)(
174
- mt1 => mt.paramInfos.map(_.stripCapturing),
175
- mt1 => mt.resType.stripCapturing)
176
- pt.derivedLambdaType(resType = mt1)
177
-
178
- def transformCurriedTupledCaptures (symd : SymDenotation , toCC : Boolean )(using Context ): Type =
179
- val (et : ExprType ) = symd.info: @ unchecked
180
- val (enclThis : ThisType ) = symd.owner.thisType: @ unchecked
181
- def mapFinalResult (tp : Type , f : Type => Type ): Type =
182
- val defn .FunctionOf (args, res, isContextual) = tp : @ unchecked
183
- if defn.isFunctionNType(res) then
184
- defn.FunctionOf (args, mapFinalResult(res, f), isContextual)
185
- else
186
- f(tp)
187
- val resType1 =
188
- if toCC then
189
- mapFinalResult(et.resType, CapturingType (_, CaptureSet (enclThis)))
190
- else
191
- et.resType.stripCapturing
192
- ExprType (resType1)
193
-
194
- /** If `sym` refers to a synthetic apply, unapply, copy, or copy default getter method
195
- * of a case class, transform it to account for capture information.
196
- * The method is run in phase CheckCaptures.Pre
197
- * @pre needsTransform(sym)
198
- */
199
- def transformToCC (sym : SymDenotation )(using Context ): SymDenotation = sym.name match
200
- case DefaultGetterName (nme.copy, n) =>
201
- sym.copySymDenotation(info = addDefaultGetterCapture(sym.info, sym.owner, n))
202
- case nme.unapply =>
203
- sym.copySymDenotation(info = addUnapplyCaptures(sym.info))
204
- case nme.apply | nme.copy =>
205
- sym.copySymDenotation(info = addCaptureDeps(sym.info))
206
- case nme.andThen | nme.compose =>
207
- sym.copySymDenotation(info = transformComposeCaptures(sym, toCC = true ))
208
- case nme.curried | nme.tupled =>
209
- sym.copySymDenotation(info = transformCurriedTupledCaptures(sym, toCC = true ))
210
- case n if n == nme.eq || n == nme.ne =>
211
- sym.copySymDenotation(info =
212
- MethodType (defn.ObjectType .capturing(CaptureSet .universal) :: Nil , defn.BooleanType ))
213
-
214
- /** If `sym` refers to a synthetic apply, unapply, copy, or copy default getter method
215
- * of a case class, transform it back to what it was before the CC phase.
216
- * @pre needsTransform(sym)
217
- */
218
- def transformFromCC (sym : SymDenotation )(using Context ): SymDenotation = sym.name match
219
- case DefaultGetterName (nme.copy, n) =>
220
- sym.copySymDenotation(info = dropDefaultGetterCapture(sym.info))
221
- case nme.unapply =>
222
- sym.copySymDenotation(info = dropUnapplyCaptures(sym.info))
223
- case nme.apply | nme.copy =>
224
- sym.copySymDenotation(info = dropCaptureDeps(sym.info))
225
- case nme.andThen | nme.compose =>
226
- sym.copySymDenotation(info = transformComposeCaptures(sym, toCC = false ))
227
- case nme.curried | nme.tupled =>
228
- sym.copySymDenotation(info = transformCurriedTupledCaptures(sym, toCC = false ))
229
- case n if n == nme.eq || n == nme.ne =>
230
- sym.copySymDenotation(info = defn.methOfAnyRef(defn.BooleanType ))
193
+ defn.methOfAnyRef(defn.BooleanType )
194
+
195
+ sym.copySymDenotation(info = sym.name match
196
+ case DefaultGetterName (nme.copy, n) =>
197
+ transformDefaultGetterCaptures(sym.info, sym.owner, n)
198
+ case nme.unapply =>
199
+ transformUnapplyCaptures(sym.info)
200
+ case nme.apply | nme.copy =>
201
+ if toCC then addCaptureDeps(sym.info) else dropCaptureDeps(sym.info)
202
+ case nme.andThen | nme.compose =>
203
+ transformComposeCaptures(sym)
204
+ case nme.curried | nme.tupled =>
205
+ transformCurriedTupledCaptures(sym)
206
+ case n if n == nme.eq || n == nme.ne =>
207
+ transformCompareCaptures)
208
+ end transform
231
209
232
210
end Synthetics
0 commit comments