Skip to content

Commit

Permalink
Re-lub also hard union types in simplify
Browse files Browse the repository at this point in the history
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
  • Loading branch information
odersky committed Mar 27, 2024
1 parent 43ed9fd commit 01e715d
Show file tree
Hide file tree
Showing 3 changed files with 12 additions and 10 deletions.
11 changes: 2 additions & 9 deletions compiler/src/dotty/tools/dotc/core/TypeOps.scala
Expand Up @@ -157,15 +157,8 @@ object TypeOps:
tp.derivedAlias(simplify(tp.alias, theMap))
case AndType(l, r) if !ctx.mode.is(Mode.Type) =>
simplify(l, theMap) & simplify(r, theMap)
case tp @ OrType(l, r)
if !ctx.mode.is(Mode.Type)
&& (tp.isSoft || l.isBottomType || r.isBottomType) =>
// Normalize A | Null and Null | A to A even if the union is hard (i.e.
// explicitly declared), but not if -Yexplicit-nulls is set. The reason is
// that in this case the normal asSeenFrom machinery is not prepared to deal
// with Nulls (which have no base classes). Under -Yexplicit-nulls, we take
// corrective steps, so no widening is wanted.
simplify(l, theMap) | simplify(r, theMap)
case tp @ OrType(l, r) if !ctx.mode.is(Mode.Type) =>
TypeComparer.lub(simplify(l, theMap), simplify(r, theMap), isSoft = tp.isSoft)
case tp @ CapturingType(parent, refs) =>
if !ctx.mode.is(Mode.Type)
&& refs.subCaptures(parent.captureSet, frozen = true).isOK
Expand Down
3 changes: 2 additions & 1 deletion compiler/src/dotty/tools/dotc/typer/Namer.scala
Expand Up @@ -1961,7 +1961,8 @@ class Namer { typer: Typer =>
else
// don't strip @uncheckedVariance annot for default getters
TypeOps.simplify(tp.widenTermRefExpr,
if defaultTp.exists then TypeOps.SimplifyKeepUnchecked() else null) match
if defaultTp.exists then TypeOps.SimplifyKeepUnchecked() else null)
match
case ctp: ConstantType if sym.isInlineVal => ctp
case tp => TypeComparer.widenInferred(tp, pt, widenUnions = true)

Expand Down
8 changes: 8 additions & 0 deletions tests/pos/i10693.scala
@@ -0,0 +1,8 @@
def test[A, B](a: A, b: B): A | B = a
val v0 = test("string", 1)
val v1 = test(1, "string")
val v2 = test(v0, v1)
val v3 = test(v1, v0)
val v4 = test(v2, v3)
val v5 = test(v3, v2)
val v6 = test(v4, v5)

0 comments on commit 01e715d

Please sign in to comment.