Skip to content

Commit

Permalink
Add special handling for comparisons with Singleton types
Browse files Browse the repository at this point in the history
Fixes #15030

[Cherry-picked 1f9a61e][modified]
  • Loading branch information
WojciechMazur committed Jul 8, 2024
1 parent ebd1ee0 commit 7f4e19c
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 @@ -920,12 +920,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 @@ -326,6 +326,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 type of kind `AnyKind`? */
def hasAnyKind(using Context): Boolean = {
@tailrec def loop(tp: Type): Boolean = tp match {
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 7f4e19c

Please sign in to comment.