Skip to content

Commit b3ade17

Browse files
authored
Merge pull request #12925 from dotty-staging/fix-12909
Widen unions before finding members
2 parents cd626da + a0e4b8a commit b3ade17

File tree

3 files changed

+63
-7
lines changed

3 files changed

+63
-7
lines changed

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

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2049,7 +2049,10 @@ object SymDenotations {
20492049

20502050
override final def findMember(name: Name, pre: Type, required: FlagSet, excluded: FlagSet)(using Context): Denotation =
20512051
val raw = if excluded.is(Private) then nonPrivateMembersNamed(name) else membersNamed(name)
2052-
raw.filterWithFlags(required, excluded).asSeenFrom(pre).toDenot(pre)
2052+
val pre1 = pre match
2053+
case pre: OrType => pre.widenUnion
2054+
case _ => pre
2055+
raw.filterWithFlags(required, excluded).asSeenFrom(pre1).toDenot(pre1)
20532056

20542057
final def findMemberNoShadowingBasedOnFlags(name: Name, pre: Type,
20552058
required: FlagSet = EmptyFlags, excluded: FlagSet = EmptyFlags)(using Context): Denotation =

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

Lines changed: 17 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1282,13 +1282,10 @@ object Types {
12821282
case tp =>
12831283
tp.widenUnionWithoutNull
12841284

1285+
/** Overridden in OrType */
12851286
def widenUnionWithoutNull(using Context): Type = widen match
1286-
case tp @ OrType(lhs, rhs) if tp.isSoft =>
1287-
TypeComparer.lub(lhs.widenUnionWithoutNull, rhs.widenUnionWithoutNull, canConstrain = true) match
1288-
case union: OrType => union.join
1289-
case res => res
1290-
case tp: AndOrType =>
1291-
tp.derivedAndOrType(tp.tp1.widenUnionWithoutNull, tp.tp2.widenUnionWithoutNull)
1287+
case tp: AndType =>
1288+
tp.derivedAndType(tp.tp1.widenUnionWithoutNull, tp.tp2.widenUnionWithoutNull)
12921289
case tp: RefinedType =>
12931290
tp.derivedRefinedType(tp.parent.widenUnion, tp.refinedName, tp.refinedInfo)
12941291
case tp: RecType =>
@@ -3198,6 +3195,20 @@ object Types {
31983195
myJoin
31993196
}
32003197

3198+
private var myUnion: Type = _
3199+
private var myUnionPeriod: Period = Nowhere
3200+
3201+
override def widenUnionWithoutNull(using Context): Type =
3202+
if myUnionPeriod != ctx.period then
3203+
myUnion =
3204+
if isSoft then
3205+
TypeComparer.lub(tp1.widenUnionWithoutNull, tp2.widenUnionWithoutNull, canConstrain = true) match
3206+
case union: OrType => union.join
3207+
case res => res
3208+
else derivedOrType(tp1.widenUnionWithoutNull, tp2.widenUnionWithoutNull)
3209+
if !isProvisional then myUnionPeriod = ctx.period
3210+
myUnion
3211+
32013212
private var atomsRunId: RunId = NoRunId
32023213
private var myAtoms: Atoms = _
32033214
private var myWidened: Type = _

tests/pos/i12909.scala

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
package example
2+
3+
final case class Writer[W, A](run: (W, A)) {
4+
def map[B](f: A => B): Writer[W, B] = ???
5+
6+
def flatMap[B](f: A => Writer[W, B]): Writer[W, B] = ???
7+
}
8+
9+
object Main {
10+
implicit class WriterOps[A](a: A) {
11+
def set[W](w: W): Writer[W, A] = ???
12+
}
13+
14+
def x1[A]: Writer[Vector[String], Option[A]] = ???
15+
16+
val failure = for {
17+
a1 <- {
18+
Option(1) match {
19+
case Some(x) =>
20+
x1[Boolean]
21+
case _ =>
22+
Option.empty[Boolean].set(Vector.empty[String])
23+
}
24+
}
25+
a2 <- x1[String]
26+
} yield ()
27+
28+
val success = for {
29+
a1 <- {
30+
val temp = Option(1) match {
31+
case Some(x) =>
32+
x1[Boolean]
33+
case _ =>
34+
Option.empty[Boolean].set(Vector.empty[String])
35+
}
36+
// why ???
37+
temp
38+
}
39+
a2 <- x1[String]
40+
} yield ()
41+
42+
}

0 commit comments

Comments
 (0)