@@ -1163,6 +1163,36 @@ class TreeUnpickler(reader: TastyReader,
1163
1163
readPathTerm()
1164
1164
}
1165
1165
1166
+ /** Adapt constructor calls where class has only using clauses from old to new scheme.
1167
+ * or class has mixed using clauses and other clauses.
1168
+ * Old: leading (), new: nothing, or trailing () if all clauses are using clauses.
1169
+ * This is neccessary so that we can read pre-3.2 Tasty correctly. There,
1170
+ * constructor calls use the old scheme, but constructor definitions already
1171
+ * use the new scheme, since they are reconstituted with normalizeIfConstructor.
1172
+ */
1173
+ def constructorApply (fn : Tree , args : List [Tree ]): Tree =
1174
+ if fn.tpe.widen.isContextualMethod && args.isEmpty then
1175
+ fn.withAttachment(SuppressedApplyToNone , ())
1176
+ else
1177
+ val fn1 = fn match
1178
+ case Apply (fn1, Nil ) if fn.removeAttachment(InsertedApplyToNone ).isDefined =>
1179
+ // We thought we inserted a final `()` but hit a user-written `()` instead.
1180
+ // Remove the inserted `()`.
1181
+ fn1
1182
+ case _ =>
1183
+ fn
1184
+ val res = tpd.Apply (fn1, args)
1185
+ if fn.removeAttachment(SuppressedApplyToNone ).isEmpty then
1186
+ res
1187
+ else res.tpe.widen match
1188
+ case mt @ MethodType (params) =>
1189
+ if params.isEmpty then
1190
+ // Assume it's the final synthesized `()` parameter
1191
+ res.appliedToNone.withAttachment(InsertedApplyToNone , ())
1192
+ else if mt.isContextualMethod then
1193
+ res.withAttachment(SuppressedApplyToNone , ())
1194
+ else res
1195
+
1166
1196
def readLengthTerm (): Tree = {
1167
1197
val end = readEnd()
1168
1198
val result =
@@ -1174,22 +1204,8 @@ class TreeUnpickler(reader: TastyReader,
1174
1204
case APPLY =>
1175
1205
val fn = readTerm()
1176
1206
val args = until(end)(readTerm())
1177
- // Adapt constructor calls where class has only using clauses from old to new scheme.
1178
- // Old: leading (), new: trailing ().
1179
- // This is neccessary so that we can read pre-3.2 Tasty correctly. There,
1180
- // constructor calls use the old scheme, but constructor definitions already
1181
- // use the new scheme, since they are reconstituted with normalizeIfConstructor.
1182
- if fn.symbol.isConstructor && fn.tpe.widen.isContextualMethod && args.isEmpty then
1183
- fn.withAttachment(SuppressedApplyToNone , ())
1184
- else
1185
- val res = tpd.Apply (fn, args)
1186
- if fn.removeAttachment(SuppressedApplyToNone ).isEmpty then
1187
- res
1188
- else res.tpe.widen match
1189
- case MethodType (Nil ) =>
1190
- res.appliedToNone
1191
- case mt : MethodType if mt.isContextualMethod =>
1192
- res.withAttachment(SuppressedApplyToNone , ())
1207
+ if fn.symbol.isConstructor then constructorApply(fn, args)
1208
+ else tpd.Apply (fn, args)
1193
1209
case TYPEAPPLY =>
1194
1210
tpd.TypeApply (readTerm(), until(end)(readTpt()))
1195
1211
case TYPED =>
@@ -1581,4 +1597,9 @@ object TreeUnpickler {
1581
1597
* call that has otherwise only using clauses was suppressed.
1582
1598
*/
1583
1599
val SuppressedApplyToNone : Property .Key [Unit ] = Property .Key ()
1600
+
1601
+ /** An attachment key indicating that an trailing () in a constructor
1602
+ * call that has otherwise only using clauses was inserted.
1603
+ */
1604
+ val InsertedApplyToNone : Property .Key [Unit ] = Property .Key ()
1584
1605
}
0 commit comments