@@ -1137,7 +1137,8 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer
1137
1137
1138
1138
def gadtAdaptBranch (tree : Tree , branchPt : Type ): Tree =
1139
1139
TypeComparer .testSubType(tree.tpe.widenExpr, branchPt) match {
1140
- case CompareResult .OKwithGADTUsed => tree.cast(branchPt)
1140
+ case CompareResult .OKwithGADTUsed =>
1141
+ insertGadtCast(tree, tree.tpe.widen, branchPt)
1141
1142
case _ => tree
1142
1143
}
1143
1144
@@ -1157,8 +1158,10 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer
1157
1158
1158
1159
val resType = thenp1.tpe | elsep1.tpe
1159
1160
1160
- val thenp2 = gadtAdaptBranch(thenp1, resType)
1161
- val elsep2 = gadtAdaptBranch(elsep1, resType)
1161
+ val thenp2 :: elsep2 :: Nil =
1162
+ (thenp1 :: elsep1 :: Nil ) map { t =>
1163
+ gadtAdaptBranch(t, resType)
1164
+ }: @ unchecked
1162
1165
1163
1166
cpy.If (tree)(cond1, thenp2, elsep2).withType(resType)
1164
1167
@@ -3775,26 +3778,7 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer
3775
3778
gadts.println(i " unnecessary GADTused for $tree: ${tree.tpe.widenExpr} vs $pt in ${ctx.source}" )
3776
3779
res
3777
3780
} =>
3778
- // Insert an explicit cast, so that -Ycheck in later phases succeeds.
3779
- // The check "safeToInstantiate" in `maximizeType` works to prevent unsound GADT casts.
3780
- val target =
3781
- if tree.tpe.isSingleton then
3782
- // In the target type, when the singleton type is intersected, we also intersect
3783
- // the GADT-approximated type of the singleton to avoid the loss of
3784
- // information. See #14776.
3785
- val gadtApprox = Inferencing .approximateGADT(tree.tpe.widen)
3786
- gadts.println(i " gadt approx $wtp ~~~ $gadtApprox" )
3787
- val conj =
3788
- AndType (AndType (tree.tpe, gadtApprox), pt)
3789
- if tree.tpe.isStable && ! conj.isStable then
3790
- // this is needed for -Ycheck. Without the annotation Ycheck will
3791
- // skolemize the result type which will lead to different types before
3792
- // and after checking. See i11955.scala.
3793
- AnnotatedType (conj, Annotation (defn.UncheckedStableAnnot ))
3794
- else conj
3795
- else pt
3796
- gadts.println(i " insert GADT cast from $tree to $target" )
3797
- tree.cast(target)
3781
+ insertGadtCast(tree, wtp, pt)
3798
3782
case _ =>
3799
3783
// typr.println(i"OK ${tree.tpe}\n${TypeComparer.explained(_.isSubType(tree.tpe, pt))}") // uncomment for unexpected successes
3800
3784
tree
@@ -4225,4 +4209,36 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer
4225
4209
EmptyTree
4226
4210
else typedExpr(call, defn.AnyType )
4227
4211
4212
+ /** Insert GADT cast to target type `pt` on the `tree`
4213
+ * so that -Ycheck in later phases succeeds.
4214
+ * The check "safeToInstantiate" in `maximizeType` works to prevent unsound GADT casts.
4215
+ */
4216
+ private def insertGadtCast (tree : Tree , wtp : Type , pt : Type )(using Context ): Tree =
4217
+ val target =
4218
+ if tree.tpe.isSingleton then
4219
+ // In the target type, when the singleton type is intersected, we also intersect
4220
+ // the GADT-approximated type of the singleton to avoid the loss of
4221
+ // information. See #14776.
4222
+ val gadtApprox = Inferencing .approximateGADT(wtp)
4223
+ gadts.println(i " gadt approx $wtp ~~~ $gadtApprox" )
4224
+ val conj =
4225
+ TypeComparer .testSubType(gadtApprox, pt) match {
4226
+ case CompareResult .OK =>
4227
+ // GADT approximation of the tree type is a subtype of expected type under empty GADT
4228
+ // constraints, so it is enough to only have the GADT approximation.
4229
+ AndType (tree.tpe, gadtApprox)
4230
+ case _ =>
4231
+ // In other cases, we intersect both the approximated type and the expected type.
4232
+ AndType (AndType (tree.tpe, gadtApprox), pt)
4233
+ }
4234
+ if tree.tpe.isStable && ! conj.isStable then
4235
+ // this is needed for -Ycheck. Without the annotation Ycheck will
4236
+ // skolemize the result type which will lead to different types before
4237
+ // and after checking. See i11955.scala.
4238
+ AnnotatedType (conj, Annotation (defn.UncheckedStableAnnot ))
4239
+ else conj
4240
+ else pt
4241
+ gadts.println(i " insert GADT cast from $tree to $target" )
4242
+ tree.cast(target)
4243
+ end insertGadtCast
4228
4244
}
0 commit comments