@@ -1125,6 +1125,36 @@ class TreeUnpickler(reader: TastyReader,
11251125 readPathTerm()
11261126 }
11271127
1128+ /** Adapt constructor calls where class has only using clauses from old to new scheme.
1129+ * or class has mixed using clauses and other clauses.
1130+ * Old: leading (), new: nothing, or trailing () if all clauses are using clauses.
1131+ * This is neccessary so that we can read pre-3.2 Tasty correctly. There,
1132+ * constructor calls use the old scheme, but constructor definitions already
1133+ * use the new scheme, since they are reconstituted with normalizeIfConstructor.
1134+ */
1135+ def constructorApply (fn : Tree , args : List [Tree ]): Tree =
1136+ if fn.tpe.widen.isContextualMethod && args.isEmpty then
1137+ fn.withAttachment(SuppressedApplyToNone , ())
1138+ else
1139+ val fn1 = fn match
1140+ case Apply (fn1, Nil ) if fn.removeAttachment(InsertedApplyToNone ).isDefined =>
1141+ // We thought we inserted a final `()` but hit a user-written `()` instead.
1142+ // Remove the inserted `()`.
1143+ fn1
1144+ case _ =>
1145+ fn
1146+ val res = tpd.Apply (fn1, args)
1147+ if fn.removeAttachment(SuppressedApplyToNone ).isEmpty then
1148+ res
1149+ else res.tpe.widen match
1150+ case mt @ MethodType (params) =>
1151+ if params.isEmpty then
1152+ // Assume it's the final synthesized `()` parameter
1153+ res.appliedToNone.withAttachment(InsertedApplyToNone , ())
1154+ else if mt.isContextualMethod then
1155+ res.withAttachment(SuppressedApplyToNone , ())
1156+ else res
1157+
11281158 def readLengthTerm (): Tree = {
11291159 val end = readEnd()
11301160 val result =
@@ -1136,22 +1166,8 @@ class TreeUnpickler(reader: TastyReader,
11361166 case APPLY =>
11371167 val fn = readTerm()
11381168 val args = until(end)(readTerm())
1139- // Adapt constructor calls where class has only using clauses from old to new scheme.
1140- // Old: leading (), new: trailing ().
1141- // This is neccessary so that we can read pre-3.2 Tasty correctly. There,
1142- // constructor calls use the old scheme, but constructor definitions already
1143- // use the new scheme, since they are reconstituted with normalizeIfConstructor.
1144- if fn.symbol.isConstructor && fn.tpe.widen.isContextualMethod && args.isEmpty then
1145- fn.withAttachment(SuppressedApplyToNone , ())
1146- else
1147- val res = tpd.Apply (fn, args)
1148- if fn.removeAttachment(SuppressedApplyToNone ).isEmpty then
1149- res
1150- else res.tpe.widen match
1151- case MethodType (Nil ) =>
1152- res.appliedToNone
1153- case mt : MethodType if mt.isContextualMethod =>
1154- res.withAttachment(SuppressedApplyToNone , ())
1169+ if fn.symbol.isConstructor then constructorApply(fn, args)
1170+ else tpd.Apply (fn, args)
11551171 case TYPEAPPLY =>
11561172 tpd.TypeApply (readTerm(), until(end)(readTpt()))
11571173 case TYPED =>
@@ -1544,4 +1560,9 @@ object TreeUnpickler {
15441560 * call that has otherwise only using clauses was suppressed.
15451561 */
15461562 val SuppressedApplyToNone : Property .Key [Unit ] = Property .Key ()
1563+
1564+ /** An attachment key indicating that an trailing () in a constructor
1565+ * call that has otherwise only using clauses was inserted.
1566+ */
1567+ val InsertedApplyToNone : Property .Key [Unit ] = Property .Key ()
15471568}
0 commit comments