Skip to content

Commit 0dc8272

Browse files
committed
Tweak condition when to drop super traits
Drop supertraits only if they are a mixin to something else (which is not a supertype of the supertrait itself).
1 parent 6400e2a commit 0dc8272

File tree

3 files changed

+20
-14
lines changed

3 files changed

+20
-14
lines changed

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

Lines changed: 15 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -300,9 +300,12 @@ trait ConstraintHandling[AbstractContext] {
300300
* (i.e. `inst.widenSingletons <:< bound` succeeds with satisfiable constraint)
301301
* 2. If `inst` is a union type, approximate the union type from above by an intersection
302302
* of all common base types, provided the result is a subtype of `bound`.
303-
* 3. If `inst` a super trait instance or an intersection with some super trait
304-
* parents, replace all super trait instances with AnyRef (or Any, if the trait
305-
* is a universal trait) as long as the result is a subtype of `bound`.
303+
* 3. If `inst` an intersection such that some operands are super trait instances
304+
* and others are not, replace as many super trait instances as possible with Any
305+
* as long as the result is still a subtype of `bound`. But fall back to the
306+
* original type if the resulting widened type is a supertype of all dropped
307+
* types (since in this case the type was not a true intersection of super traits
308+
* and other types to start with).
306309
*
307310
* Don't do these widenings if `bound` is a subtype of `scala.Singleton`.
308311
* Also, if the result of these widenings is a TypeRef to a module class,
@@ -315,14 +318,14 @@ trait ConstraintHandling[AbstractContext] {
315318
def widenInferred(inst: Type, bound: Type)(implicit actx: AbstractContext): Type =
316319

317320
def dropSuperTraits(tp: Type): Type =
318-
var keep: Set[Type] = Set() // types to keep since otherwise bound would not fit
319-
var lastDropped: Type = NoType // the last type dropped in dropOneSuperTrait
321+
var kept: Set[Type] = Set() // types to keep since otherwise bound would not fit
322+
var dropped: List[Type] = List() // the types dropped so far, last one on top
320323

321324
def dropOneSuperTrait(tp: Type): Type =
322325
val tpd = tp.dealias
323-
if tpd.typeSymbol.isSuperTrait && !tpd.isLambdaSub && !keep.contains(tpd) then
324-
lastDropped = tpd
325-
if tpd.derivesFrom(defn.ObjectClass) then defn.ObjectType else defn.AnyType
326+
if tpd.typeSymbol.isSuperTrait && !tpd.isLambdaSub && !kept.contains(tpd) then
327+
dropped = tpd :: dropped
328+
defn.AnyType
326329
else tpd match
327330
case AndType(tp1, tp2) =>
328331
val tp1w = dropOneSuperTrait(tp1)
@@ -339,10 +342,12 @@ trait ConstraintHandling[AbstractContext] {
339342
if tpw eq tp then tp
340343
else if tpw <:< bound then recur(tpw)
341344
else
342-
keep += lastDropped
345+
kept += dropped.head
346+
dropped = dropped.tail
343347
recur(tp)
344348

345-
recur(tp)
349+
val tpw = recur(tp)
350+
if (tpw eq tp) || dropped.forall(_ frozen_<:< tpw) then tp else tpw
346351
end dropSuperTraits
347352

348353
def widenOr(tp: Type) =

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1304,7 +1304,7 @@ class Definitions {
13041304
(sym eq Object_eq) || (sym eq Object_ne)
13051305

13061306
@tu lazy val assumedSuperTraits =
1307-
Set(ComparableClass, JavaSerializableClass, ProductClass, SerializableClass)
1307+
Set(ComparableClass, ProductClass, SerializableClass)
13081308

13091309
// ----- primitive value class machinery ------------------------------------------
13101310

tests/neg-custom-args/fatal-warnings/supertraits.scala

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
sealed super trait TA
22
sealed super trait TB
3-
case object a extends TA, TB
4-
case object b extends TA, TB
3+
trait S
4+
case object a extends S, TA, TB
5+
case object b extends S, TA, TB
56

67
object Test:
78

@@ -13,7 +14,7 @@ object Test:
1314

1415
choose0(a, b) match
1516
case _: TA => ???
16-
case _: TB => ???
17+
case _: TB => ??? // error: unreachable
1718

1819
choose1(a, b) match
1920
case _: TA => ???

0 commit comments

Comments
 (0)