Skip to content

Don't widen components of a hard union #19908

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
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
14 changes: 7 additions & 7 deletions compiler/src/dotty/tools/dotc/core/Types.scala
Original file line number Diff line number Diff line change
Expand Up @@ -3597,15 +3597,15 @@ object Types extends TypeUtils {
private var myUnionPeriod: Period = Nowhere

override def widenUnionWithoutNull(using Context): Type =
if myUnionPeriod != ctx.period then
if !isSoft then this
else if myUnionPeriod != ctx.period then
myUnion =
if isSoft then
TypeComparer.lub(tp1.widenUnionWithoutNull, tp2.widenUnionWithoutNull, canConstrain = true, isSoft = isSoft) match
case union: OrType => union.join
case res => res
else derivedOrType(tp1.widenUnionWithoutNull, tp2.widenUnionWithoutNull, soft = isSoft)
TypeComparer.lub(tp1.widenUnionWithoutNull, tp2.widenUnionWithoutNull, canConstrain = true, isSoft = isSoft) match
case union: OrType => union.join
case res => res
if !isProvisional then myUnionPeriod = ctx.period
myUnion
myUnion
else myUnion

private var atomsRunId: RunId = NoRunId
private var myAtoms: Atoms = uninitialized
Expand Down
37 changes: 37 additions & 0 deletions tests/pos/i19823.4a.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
enum A:
case B
case C
case D

object A:
type B_type = B.type
type C_type = C.type
type D_type = D.type

type Matcher[T] = T match
case A.C.type | A.D.type => Int
case A.B.type => Float

class Test:
def fn[U <: A](u: U)(value: Matcher[U]): Matcher[U] = value

def t1: Unit =
val a: A.C_type | A.D_type = A.C
val x = fn(a)(5)

def t2: Unit =
val a: A.C.type | A.D.type = A.C
val x = fn(a)(5) // was:
// ^
// Found: (5 : Int)
// Required: Matcher[A]
//
// Note: a match type could not be fully reduced:
//
// trying to reduce Matcher[A]
// failed since selector A
// does not match case (A.C : A) | (A.D : A) => Int
// and cannot be shown to be disjoint from it either.
// Therefore, reduction cannot advance to the remaining case
//
// case (A.B : A) => Float
25 changes: 25 additions & 0 deletions tests/pos/i19823.4b.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
sealed abstract class A

object A:
case object B extends A
case object C extends A
case object D extends A

type B_type = B.type
type C_type = C.type
type D_type = D.type

type Matcher[T] = T match
case A.C.type | A.D.type => Int
case A.B.type => Float

class Test:
def fn[U <: A](u: U)(value: Matcher[U]): Matcher[U] = value

def t1: Unit =
val a: A.C_type | A.D_type = A.C
val x = fn(a)(5)

def t2: Unit =
val a: A.C.type | A.D.type = A.C
val x = fn(a)(5)