Skip to content

Commit 01e715d

Browse files
committed
Re-lub also hard union types in simplify
Simplify had some elaborate condition that prevented hard union types to be recomputed with a lub. I am not sure why that was. In the concrete scenario of i10693.scala, we had an explicitly union result type `B | A` where `A` and `B` are type parameters. So that is a hard union type. Then `A` was instantiated by `Int | String` and `B` was instantiated by `String | Int`. Re-forming the lub of that union would have eliminated one pair, but since the union type was hard tyat was not done. On the other hand I see no reason why hard unions should not be re-lubbed. Hard unions are about preventing the widening of or types with a join. I don't see a connection with avoiding re-lubbing. Fixes #10693
1 parent 43ed9fd commit 01e715d

File tree

3 files changed

+12
-10
lines changed

3 files changed

+12
-10
lines changed

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

Lines changed: 2 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -157,15 +157,8 @@ object TypeOps:
157157
tp.derivedAlias(simplify(tp.alias, theMap))
158158
case AndType(l, r) if !ctx.mode.is(Mode.Type) =>
159159
simplify(l, theMap) & simplify(r, theMap)
160-
case tp @ OrType(l, r)
161-
if !ctx.mode.is(Mode.Type)
162-
&& (tp.isSoft || l.isBottomType || r.isBottomType) =>
163-
// Normalize A | Null and Null | A to A even if the union is hard (i.e.
164-
// explicitly declared), but not if -Yexplicit-nulls is set. The reason is
165-
// that in this case the normal asSeenFrom machinery is not prepared to deal
166-
// with Nulls (which have no base classes). Under -Yexplicit-nulls, we take
167-
// corrective steps, so no widening is wanted.
168-
simplify(l, theMap) | simplify(r, theMap)
160+
case tp @ OrType(l, r) if !ctx.mode.is(Mode.Type) =>
161+
TypeComparer.lub(simplify(l, theMap), simplify(r, theMap), isSoft = tp.isSoft)
169162
case tp @ CapturingType(parent, refs) =>
170163
if !ctx.mode.is(Mode.Type)
171164
&& refs.subCaptures(parent.captureSet, frozen = true).isOK

compiler/src/dotty/tools/dotc/typer/Namer.scala

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1961,7 +1961,8 @@ class Namer { typer: Typer =>
19611961
else
19621962
// don't strip @uncheckedVariance annot for default getters
19631963
TypeOps.simplify(tp.widenTermRefExpr,
1964-
if defaultTp.exists then TypeOps.SimplifyKeepUnchecked() else null) match
1964+
if defaultTp.exists then TypeOps.SimplifyKeepUnchecked() else null)
1965+
match
19651966
case ctp: ConstantType if sym.isInlineVal => ctp
19661967
case tp => TypeComparer.widenInferred(tp, pt, widenUnions = true)
19671968

tests/pos/i10693.scala

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
def test[A, B](a: A, b: B): A | B = a
2+
val v0 = test("string", 1)
3+
val v1 = test(1, "string")
4+
val v2 = test(v0, v1)
5+
val v3 = test(v1, v0)
6+
val v4 = test(v2, v3)
7+
val v5 = test(v3, v2)
8+
val v6 = test(v4, v5)

0 commit comments

Comments
 (0)