Skip to content

Commit a1d6c96

Browse files
committed
Avoid early widening enum val symbols in provablyDisjointClasses
1 parent 3cd94b4 commit a1d6c96

File tree

2 files changed

+29
-23
lines changed

2 files changed

+29
-23
lines changed

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

+7-23
Original file line numberDiff line numberDiff line change
@@ -3201,35 +3201,21 @@ class TypeComparer(@constructorOnly initctx: Context) extends ConstraintHandling
32013201
result
32023202
end existsCommonBaseTypeWithDisjointArguments
32033203

3204-
provablyDisjointClasses(cls1, cls2, seen = null)
3204+
provablyDisjointClasses(cls1, cls2)
32053205
|| existsCommonBaseTypeWithDisjointArguments
32063206
end match
32073207
}
32083208

3209-
private def provablyDisjointClasses(cls1: Symbol, cls2: Symbol, seen: util.HashSet[Symbol] | Null)(using Context): Boolean =
3209+
private def provablyDisjointClasses(cls1: Symbol, cls2: Symbol)(using Context): Boolean =
32103210
def isDecomposable(cls: Symbol): Boolean =
3211-
if seen != null && seen.contains(cls) then false
3212-
else cls.is(Sealed) && !cls.hasAnonymousChild
3213-
3214-
def decompose(cls: Symbol): List[Symbol] =
3215-
cls.children.flatMap { child =>
3216-
if child.isTerm then
3217-
child.info.classSymbols // allow enum vals to be decomposed to their enum class (then filtered out) and any mixins
3218-
else child :: Nil
3219-
}.filter(child => child.exists && child != cls)
3220-
3221-
inline def seeing(inline cls: Symbol)(inline thunk: util.HashSet[Symbol] => Boolean) =
3222-
val seen1 = if seen == null then new util.HashSet[Symbol] else seen
3223-
try
3224-
seen1 += cls
3225-
thunk(seen1)
3226-
finally seen1 -= cls
3211+
cls.is(Sealed) && !cls.hasAnonymousChild
32273212

32283213
def eitherDerivesFromOther(cls1: Symbol, cls2: Symbol): Boolean =
32293214
cls1.derivesFrom(cls2) || cls2.derivesFrom(cls1)
32303215

32313216
def smallestNonTraitBase(cls: Symbol): Symbol =
3232-
cls.asClass.baseClasses.find(!_.is(Trait)).get
3217+
val classes = if cls.isClass then cls.asClass.baseClasses else cls.info.classSymbols
3218+
classes.find(!_.is(Trait)).get
32333219

32343220
if (eitherDerivesFromOther(cls1, cls2))
32353221
false
@@ -3247,11 +3233,9 @@ class TypeComparer(@constructorOnly initctx: Context) extends ConstraintHandling
32473233
// instantiations of `cls1` (terms of the form `new cls1`) are not
32483234
// of type `tp2`. Therefore, we can safely decompose `cls1` using
32493235
// `.children`, even if `cls1` is non abstract.
3250-
seeing(cls1): seen1 =>
3251-
decompose(cls1).forall(x => provablyDisjointClasses(x, cls2, seen1))
3236+
cls1.children.forall(x => provablyDisjointClasses(x, cls2))
32523237
else if (isDecomposable(cls2))
3253-
seeing(cls2): seen1 =>
3254-
decompose(cls2).forall(x => provablyDisjointClasses(cls1, x, seen1))
3238+
cls2.children.forall(x => provablyDisjointClasses(cls1, x))
32553239
else
32563240
false
32573241
end provablyDisjointClasses

tests/pos/i22266.unenum.scala

+22
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
sealed trait NonPolygon
2+
sealed trait Polygon
3+
4+
sealed trait SymmetryAspect
5+
sealed trait RotationalSymmetry extends SymmetryAspect
6+
sealed trait MaybeRotationalSymmetry extends SymmetryAspect
7+
8+
sealed abstract class Shape
9+
10+
object Shape:
11+
case object Circle extends Shape with NonPolygon with RotationalSymmetry
12+
case object Triangle extends Shape with Polygon with MaybeRotationalSymmetry
13+
case object Square extends Shape with Polygon with RotationalSymmetry
14+
15+
def hasPolygon(
16+
rotationalSyms: Vector[Shape & RotationalSymmetry],
17+
maybeSyms: Vector[Shape & MaybeRotationalSymmetry]
18+
): Boolean =
19+
val all = rotationalSyms.concat(maybeSyms)
20+
all.exists:
21+
case _: Polygon => true
22+
case _ => false

0 commit comments

Comments
 (0)