Skip to content
Closed
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions compiler/src/dotty/tools/dotc/core/ConstraintHandling.scala
Original file line number Diff line number Diff line change
Expand Up @@ -557,8 +557,8 @@ trait ConstraintHandling {
// Widening can add extra constraints, in particular the widened type might
// be a type variable which is now instantiated to `param`, and therefore
// cannot be used as an instantiation of `param` without creating a loop.
// If that happens, we run `instanceType` again to find a new instantation.
// (we do not check for non-toplevel occurences: those should never occur
// If that happens, we run `instanceType` again to find a new instantiation.
// (we do not check for non-toplevel occurrences: those should never occur
// since `addOneBound` disallows recursive lower bounds).
if constraint.occursAtToplevel(param, widened) then
instanceType(param, fromBelow)
Expand Down
13 changes: 9 additions & 4 deletions compiler/src/dotty/tools/dotc/core/Types.scala
Original file line number Diff line number Diff line change
Expand Up @@ -3266,7 +3266,7 @@ object Types {
TypeComparer.lub(tp1.widenUnionWithoutNull, tp2.widenUnionWithoutNull, canConstrain = true) match
case union: OrType => union.join
case res => res
else derivedOrType(tp1.widenUnionWithoutNull, tp2.widenUnionWithoutNull)
else this
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Might be worth flipping the order with your change:

if isSoft then
  if myUnionPeriod != ctx.period then
    ...
  myUnion
else this

if !isProvisional then myUnionPeriod = ctx.period
myUnion

Expand All @@ -3280,11 +3280,16 @@ object Types {
if tp1.hasClassSymbol(defn.NothingClass) then tp2.atoms
else if tp2.hasClassSymbol(defn.NothingClass) then tp1.atoms
else tp1.atoms | tp2.atoms
val tp1w = tp1.widenSingletons
val tp2w = tp2.widenSingletons
myWidened = if ((tp1 eq tp1w) && (tp2 eq tp2w)) this else tp1w | tp2w
atomsRunId = ctx.runId

myWidened =
if isSoft then
val tp1w = tp1.widenSingletons
val tp2w = tp2.widenSingletons
if ((tp1 eq tp1w) && (tp2 eq tp2w)) this else tp1w | tp2w
else
this

override def atoms(using Context): Atoms =
ensureAtomsComputed()
myAtoms
Expand Down
11 changes: 10 additions & 1 deletion tests/pos/widen-union.scala
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,21 @@ object Test2:
|| xs.corresponds(ys)(consistent(_, _)) // error, found: Any, required: Int | String

object Test3:

def g[X](x: X | String): Int = ???
def y: Boolean | String = ???
g[Boolean](y)
g(y)
g[Boolean](identity(y))
g(identity(y))

object Test4:
def f(a: 2 | 3) = a

def test() =
Copy link
Contributor

@odersky odersky Jan 26, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Consider adding a test where the union is the result type of a def.

val x: 2 | 3 = 2
val y = x
f(y)

def g: 2 | 3 = 2
val z = g
f(z)