Skip to content

Commit e940726

Browse files
committed
Simplify the types of trees before and after pickling
1 parent 215aa72 commit e940726

File tree

2 files changed

+30
-10
lines changed

2 files changed

+30
-10
lines changed

compiler/src/dotty/tools/dotc/core/TypeComparer.scala

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2141,7 +2141,7 @@ class TypeComparer(@constructorOnly initctx: Context) extends ConstraintHandling
21412141
* @note We do not admit singleton types in or-types as lubs.
21422142
*/
21432143
def lub(tp1: Type, tp2: Type, canConstrain: Boolean = false, isSoft: Boolean = true): Type = /*>|>*/ trace(s"lub(${tp1.show}, ${tp2.show}, canConstrain=$canConstrain, isSoft=$isSoft)", subtyping, show = true) /*<|<*/ {
2144-
if tp1 eq tp2 then tp1
2144+
if (tp1 eq tp2) tp1
21452145
else if !tp1.exists || (tp2 eq WildcardType) then tp1
21462146
else if !tp2.exists || (tp1 eq WildcardType) then tp2
21472147
else if tp1.isAny && !tp2.isLambdaSub || tp1.isAnyKind || isBottom(tp2) then tp1
@@ -2157,19 +2157,16 @@ class TypeComparer(@constructorOnly initctx: Context) extends ConstraintHandling
21572157
if (hi1 & hi2).isEmpty then return orType(tp1, tp2)
21582158
case none =>
21592159
case none =>
2160-
2161-
// Simplifying the super type is important to avoid
2162-
// inconsistant result in union type.
21632160
val t1 = mergeIfSuper(tp1, tp2, canConstrain)
2164-
if t1.exists then return t1.simplified
2161+
if (t1.exists) return t1
21652162

21662163
val t2 = mergeIfSuper(tp2, tp1, canConstrain)
2167-
if t2.exists then return t2.simplified
2164+
if (t2.exists) return t2
21682165

2169-
def widen(tp: Type) = if widenInUnions then tp.widen else tp.widenIfUnstable
2166+
def widen(tp: Type) = if (widenInUnions) tp.widen else tp.widenIfUnstable
21702167
val tp1w = widen(tp1)
21712168
val tp2w = widen(tp2)
2172-
if (tp1 ne tp1w) || (tp2 ne tp2w) then lub(tp1w, tp2w, canConstrain = canConstrain, isSoft = isSoft)
2169+
if ((tp1 ne tp1w) || (tp2 ne tp2w)) lub(tp1w, tp2w, canConstrain = canConstrain, isSoft = isSoft)
21732170
else orType(tp1w, tp2w, isSoft = isSoft) // no need to check subtypes again
21742171
}
21752172
mergedLub(tp1.stripLazyRef, tp2.stripLazyRef)

compiler/src/dotty/tools/dotc/transform/Pickler.scala

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import Phases._
1212
import Symbols._
1313
import Flags.Module
1414
import reporting.{ThrowingReporter, Profile}
15+
import typer.Nullables
1516
import collection.mutable
1617
import scala.concurrent.{Future, Await, ExecutionContext}
1718
import scala.concurrent.duration.Duration
@@ -60,13 +61,15 @@ class Pickler extends Phase {
6061
val unit = ctx.compilationUnit
6162
pickling.println(i"unpickling in run ${ctx.runId}")
6263

64+
val typeSimplifier = new TypeSimplifyTransformer
65+
6366
for
6467
cls <- dropCompanionModuleClasses(topLevelClasses(unit.tpdTree))
6568
tree <- sliceTopLevel(unit.tpdTree, cls)
6669
do
6770
val pickler = new TastyPickler(cls)
6871
if ctx.settings.YtestPickler.value then
69-
beforePickling(cls) = tree.show
72+
beforePickling(cls) = typeSimplifier.transform(tree).show
7073
picklers(cls) = pickler
7174
val treePkl = new TreePickler(pickler)
7275
treePkl.pickle(tree :: Nil)
@@ -134,8 +137,11 @@ class Pickler extends Phase {
134137
cls -> unpickler
135138
}
136139
pickling.println("************* entered toplevel ***********")
140+
141+
val typeSimplifier = new TypeSimplifyTransformer
142+
137143
for ((cls, unpickler) <- unpicklers) {
138-
val unpickled = unpickler.rootTrees
144+
val unpickled = typeSimplifier.transform(unpickler.rootTrees)
139145
testSame(i"$unpickled%\n%", beforePickling(cls), cls)
140146
}
141147
}
@@ -151,4 +157,21 @@ class Pickler extends Phase {
151157
|
152158
| diff before-pickling.txt after-pickling.txt""".stripMargin)
153159
end testSame
160+
161+
// Overwrite types of If, Match, and Try nodes with simplified types
162+
// to avoid inconsistencies in unsafe nulls
163+
class TypeSimplifyTransformer extends TreeMapWithPreciseStatContexts:
164+
override def transform(tree: Tree)(using Context): Tree =
165+
try tree match
166+
case _: If | _: Match | _: Try if Nullables.unsafeNullsEnabled =>
167+
val newTree = super.transform(tree)
168+
newTree.overwriteType(newTree.tpe.simplified)
169+
newTree
170+
case _ =>
171+
super.transform(tree)
172+
catch
173+
case ex: TypeError =>
174+
report.error(ex, tree.srcPos)
175+
tree
176+
end TypeSimplifyTransformer
154177
}

0 commit comments

Comments
 (0)