Skip to content

Commit 0bf7e62

Browse files
committed
Simplify lubs in TreeUnpickler
A difference between Typer and TreeUnpickler is that Typer performs a simplification step after type assigning a tree mode and unpickler doesn't. This makes a difference for lubs in unsafeNulls mode. We fix this by also doing simplification in Unpickler for trees that can have types resulting from lubs.
1 parent 9b40981 commit 0bf7e62

File tree

2 files changed

+38
-17
lines changed

2 files changed

+38
-17
lines changed

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

Lines changed: 25 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,7 @@ class TreeUnpickler(reader: TastyReader,
113113
class Completer(reader: TastyReader)(using @constructorOnly _ctx: Context) extends LazyType {
114114
import reader._
115115
val owner = ctx.owner
116+
val mode = ctx.mode
116117
val source = ctx.source
117118
def complete(denot: SymDenotation)(using Context): Unit =
118119
def fail(ex: Throwable) =
@@ -129,7 +130,7 @@ class TreeUnpickler(reader: TastyReader,
129130
try
130131
atPhaseBeforeTransforms {
131132
new TreeReader(reader).readIndexedDef()(
132-
using ctx.withOwner(owner).withSource(source))
133+
using ctx.withOwner(owner).withModeBits(mode).withSource(source))
133134
}
134135
catch
135136
case ex: AssertionError => fail(ex)
@@ -1193,6 +1194,10 @@ class TreeUnpickler(reader: TastyReader,
11931194
res.withAttachment(SuppressedApplyToNone, ())
11941195
else res
11951196

1197+
def simplifyLub(tree: Tree): Tree =
1198+
tree.overwriteType(tree.tpe.simplified)
1199+
tree
1200+
11961201
def readLengthTerm(): Tree = {
11971202
val end = readEnd()
11981203
val result =
@@ -1231,34 +1236,37 @@ class TreeUnpickler(reader: TastyReader,
12311236
val expansion = exprReader.readTerm() // need bindings in scope, so needs to be read before
12321237
Inlined(call, bindings, expansion)
12331238
case IF =>
1234-
if (nextByte == INLINE) {
1235-
readByte()
1236-
InlineIf(readTerm(), readTerm(), readTerm())
1237-
}
1238-
else
1239-
If(readTerm(), readTerm(), readTerm())
1239+
simplifyLub(
1240+
if (nextByte == INLINE) {
1241+
readByte()
1242+
InlineIf(readTerm(), readTerm(), readTerm())
1243+
}
1244+
else
1245+
If(readTerm(), readTerm(), readTerm()))
12401246
case LAMBDA =>
12411247
val meth = readTerm()
12421248
val tpt = ifBefore(end)(readTpt(), EmptyTree)
12431249
Closure(Nil, meth, tpt)
12441250
case MATCH =>
1245-
if (nextByte == IMPLICIT) {
1246-
readByte()
1247-
InlineMatch(EmptyTree, readCases(end))
1248-
}
1249-
else if (nextByte == INLINE) {
1250-
readByte()
1251-
InlineMatch(readTerm(), readCases(end))
1252-
}
1253-
else Match(readTerm(), readCases(end))
1251+
simplifyLub(
1252+
if (nextByte == IMPLICIT) {
1253+
readByte()
1254+
InlineMatch(EmptyTree, readCases(end))
1255+
}
1256+
else if (nextByte == INLINE) {
1257+
readByte()
1258+
InlineMatch(readTerm(), readCases(end))
1259+
}
1260+
else Match(readTerm(), readCases(end)))
12541261
case RETURN =>
12551262
val from = readSymRef()
12561263
val expr = ifBefore(end)(readTerm(), EmptyTree)
12571264
Return(expr, Ident(from.termRef))
12581265
case WHILE =>
12591266
WhileDo(readTerm(), readTerm())
12601267
case TRY =>
1261-
Try(readTerm(), readCases(end), ifBefore(end)(readTerm(), EmptyTree))
1268+
simplifyLub(
1269+
Try(readTerm(), readCases(end), ifBefore(end)(readTerm(), EmptyTree)))
12621270
case SELECTouter =>
12631271
val levels = readNat()
12641272
readTerm().outerSelect(levels, SkolemType(readType()))

tests/pos/i15097.scala

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
import scala.language.unsafeNulls
2+
class C {
3+
def g: String | Null = ???
4+
5+
def f =
6+
try g catch case _ => ""
7+
8+
def f2 = if ??? then g else ""
9+
10+
def f3 = (??? : Boolean) match
11+
case true => g
12+
case _ => ""
13+
}

0 commit comments

Comments
 (0)