Skip to content

Commit

Permalink
Add special handling for comparisons with Singleton types (#20474)
Browse files Browse the repository at this point in the history
  • Loading branch information
smarter authored May 28, 2024
2 parents d3df8ca + 1f9a61e commit 9b5ab2e
Show file tree
Hide file tree
Showing 3 changed files with 34 additions and 5 deletions.
13 changes: 8 additions & 5 deletions compiler/src/dotty/tools/dotc/core/TypeComparer.scala
Original file line number Diff line number Diff line change
Expand Up @@ -970,12 +970,15 @@ class TypeComparer(@constructorOnly initctx: Context) extends ConstraintHandling
compareAppliedType1(tp1, tycon1, args1)
case tp1: SingletonType =>
def comparePaths = tp2 match
case tp2: TermRef =>
case tp2: (TermRef | ThisType) =>
compareAtoms(tp1, tp2, knownSingletons = true).getOrElse(false)
|| { // needed to make from-tasty work. test cases: pos/i1753.scala, pos/t839.scala
tp2.info.widenExpr.dealias match
case tp2i: SingletonType => recur(tp1, tp2i)
case _ => false
|| {
// If tp2's underlying type tp2super is also effectively a singleton, compare
// against that. The idea is that if tp1 <: tp2super and tp2 <: tp2super and
// tp2super is also singleton, then tp1 and tp2 must be the same singleton.
// Needed to make from-tasty work. test cases: pos/i1753.scala, pos/t839.scala
val tp2super = tp2.superType.widenExpr
tp2super.isEffectivelySingleton && recur(tp1, tp2super)
}
case _ => false

Expand Down
10 changes: 10 additions & 0 deletions compiler/src/dotty/tools/dotc/core/Types.scala
Original file line number Diff line number Diff line change
Expand Up @@ -328,6 +328,16 @@ object Types extends TypeUtils {
/** Is this type a (possibly aliased) singleton type? */
def isSingleton(using Context): Boolean = dealias.isInstanceOf[SingletonType]

/** Is this type a (possibly aliased) singleton type or a type proxy
* or Or/And type known to be a singleton type?
*/
def isEffectivelySingleton(using Context): Boolean = dealias match
case tp: SingletonType => true
case tp: TypeProxy => tp.superType.isEffectivelySingleton
case AndType(tpL, tpR) => tpL.isEffectivelySingleton || tpR.isEffectivelySingleton
case OrType(tpL, tpR) => tpL.isEffectivelySingleton && tpR.isEffectivelySingleton
case _ => false

/** Is this upper-bounded by a (possibly aliased) singleton type?
* Overridden in TypeVar
*/
Expand Down
16 changes: 16 additions & 0 deletions tests/pos/i15030.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
sealed trait Schema[A]

object Schema extends RecordInstances:
case class Field[A]()

sealed trait RecordInstances:
self: Schema.type =>

case class Record[A](field: Field[A]) extends Schema[A]

import Schema._

val field: Field[Int] = Field()

// Uh oh Found Playground.Schema.Field[Int] but Requried RecordInstances.this.Field[Int]
val record = Record[Int](field)

0 comments on commit 9b5ab2e

Please sign in to comment.