File tree Expand file tree Collapse file tree 4 files changed +30
-3
lines changed
compiler/src/dotty/tools/dotc/core Expand file tree Collapse file tree 4 files changed +30
-3
lines changed Original file line number Diff line number Diff line change @@ -1179,12 +1179,21 @@ object Types {
1179
1179
*
1180
1180
* is approximated by constraining `A` to be =:= to `Int` and returning `ArrayBuffer[Int]`
1181
1181
* instead of `ArrayBuffer[_ >: Int | A <: Int & A]`
1182
+ *
1183
+ * Exception (if `-YexplicitNulls` is set): if this type is a nullable union (i.e. of the form `T | Null`),
1184
+ * then the top-level union isn't widened. This is needed so that type inference can infer nullable types.
1182
1185
*/
1183
1186
def widenUnion (implicit ctx : Context ): Type = this match {
1184
1187
case OrType (tp1, tp2) =>
1185
- ctx.typeComparer.lub(tp1.widenUnion, tp2.widenUnion, canConstrain = true ) match {
1186
- case union : OrType => union.join
1187
- case res => res
1188
+ if (ctx.settings.YexplicitNulls .value && isNullableUnion) {
1189
+ // Don't widen `T|Null`, since otherwise we wouldn't be able to infer nullable unions.
1190
+ val OrType (leftTpe, nullTpe) = normNullableUnion
1191
+ OrType (leftTpe.widenUnion, nullTpe)
1192
+ } else {
1193
+ ctx.typeComparer.lub(tp1.widenUnion, tp2.widenUnion, canConstrain = true ) match {
1194
+ case union : OrType => union.join
1195
+ case res => res
1196
+ }
1188
1197
}
1189
1198
case tp @ AndType (tp1, tp2) =>
1190
1199
tp derived_& (tp1.widenUnion, tp2.widenUnion)
Original file line number Diff line number Diff line change
1
+ class J {
2
+ String foo () { return "hello" ; }
3
+ }
Original file line number Diff line number Diff line change
1
+ class S {
2
+ val j = new J ()
3
+ val x = j.foo()
4
+ // Check that the type of `x` is inferred to be `String|Null`.
5
+ // i.e. the union isn't collapsed.
6
+ val y : String | Null = x
7
+ }
Original file line number Diff line number Diff line change
1
+
2
+ class S {
3
+ def foo [T ](x : T ): T = x
4
+ // Check that the type argument to `foo` is inferred to be
5
+ // `String|Null`: i.e. it isn't collapsed.
6
+ val x = foo(if (1 == 2 ) " hello" else null )
7
+ val y : String | Null = x
8
+ }
You can’t perform that action at this time.
0 commit comments