Skip to content
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

Keep softness when widening unions #14399

Merged
merged 1 commit into from
Feb 2, 2022
Merged
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
6 changes: 3 additions & 3 deletions compiler/src/dotty/tools/dotc/core/Types.scala
Original file line number Diff line number Diff line change
Expand Up @@ -3263,10 +3263,10 @@ object Types {
if myUnionPeriod != ctx.period then
myUnion =
if isSoft then
TypeComparer.lub(tp1.widenUnionWithoutNull, tp2.widenUnionWithoutNull, canConstrain = true) match
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)
else derivedOrType(tp1.widenUnionWithoutNull, tp2.widenUnionWithoutNull, soft = isSoft)
if !isProvisional then myUnionPeriod = ctx.period
myUnion

Expand All @@ -3282,7 +3282,7 @@ object Types {
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
myWidened = if ((tp1 eq tp1w) && (tp2 eq tp2w)) this else TypeComparer.lub(tp1w, tp2w, isSoft = isSoft)
atomsRunId = ctx.runId

override def atoms(using Context): Atoms =
Expand Down
7 changes: 6 additions & 1 deletion tests/pos/widen-union.scala
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,19 @@ object Test1:
val z: Int | String = y

object Test2:
val x: 3 | "a" = 3
val y = x
val z: Int | String = y

object Test3:
type Sig = Int | String
def consistent(x: Sig, y: Sig): Boolean = ???// x == y

def consistentLists(xs: List[Sig], ys: List[Sig]): Boolean =
xs.corresponds(ys)(consistent) // OK
|| xs.corresponds(ys)(consistent(_, _)) // error, found: Any, required: Int | String

object Test3:
object Test4:

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