Skip to content

Commit 6e9be57

Browse files
committed
Fix unpickler logic and beef up test
1 parent df9f466 commit 6e9be57

File tree

4 files changed

+98
-17
lines changed

4 files changed

+98
-17
lines changed

compiler/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala

Lines changed: 37 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -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
}
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
Bar
2+
Bar
3+
Bar
4+
Bar
5+
()
6+
Bat
7+
Bat
8+
Bat
9+
Bat
10+
()
11+
Bax
12+
Bax
13+
Bax
14+
Bax
15+
()
16+
Baz
17+
Baz
18+
Baz
19+
Baz
20+
()
Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,32 @@
1-
class Bar(using x: Int)(y: String)
1+
class Bar(using x: Int)(y: String):
2+
override def toString = "Bar"
23
object Bar:
34
given Int = 1
45
inline def foo =
56
println(new Bar()(""))
67
println(Bar()(""))
8+
9+
class Bat(using x: Int):
10+
override def toString = "Bat"
11+
object Bat:
12+
given Int = 1
13+
inline def foo =
14+
println(new Bat())
15+
println(Bat())
16+
17+
class Bax(using x: Int)():
18+
override def toString = "Bax"
19+
object Bax:
20+
given Int = 1
21+
inline def foo =
22+
println(new Bax())
23+
println(Bax())
24+
25+
class Baz(using x: Int)(using y: String):
26+
override def toString = "Baz"
27+
object Baz:
28+
given Int = 1
29+
given String = "x"
30+
inline def foo =
31+
println(new Baz())
32+
println(Baz())
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,19 @@
11
@main def Test =
22
given Int = 1
3+
given String = "x"
4+
35
println(new Bar(""))
46
println(Bar(""))
57
println(Bar.foo)
8+
9+
println(new Bat())
10+
println(Bat())
11+
println(Bat.foo)
12+
13+
println(new Bax())
14+
println(Bax())
15+
println(Bax.foo)
16+
17+
println(new Baz())
18+
println(Baz())
19+
println(Baz.foo)

0 commit comments

Comments
 (0)