Skip to content

Commit 9b5ab2e

Browse files
authored
Add special handling for comparisons with Singleton types (#20474)
2 parents d3df8ca + 1f9a61e commit 9b5ab2e

File tree

3 files changed

+34
-5
lines changed

3 files changed

+34
-5
lines changed

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

+8-5
Original file line numberDiff line numberDiff line change
@@ -970,12 +970,15 @@ class TypeComparer(@constructorOnly initctx: Context) extends ConstraintHandling
970970
compareAppliedType1(tp1, tycon1, args1)
971971
case tp1: SingletonType =>
972972
def comparePaths = tp2 match
973-
case tp2: TermRef =>
973+
case tp2: (TermRef | ThisType) =>
974974
compareAtoms(tp1, tp2, knownSingletons = true).getOrElse(false)
975-
|| { // needed to make from-tasty work. test cases: pos/i1753.scala, pos/t839.scala
976-
tp2.info.widenExpr.dealias match
977-
case tp2i: SingletonType => recur(tp1, tp2i)
978-
case _ => false
975+
|| {
976+
// If tp2's underlying type tp2super is also effectively a singleton, compare
977+
// against that. The idea is that if tp1 <: tp2super and tp2 <: tp2super and
978+
// tp2super is also singleton, then tp1 and tp2 must be the same singleton.
979+
// Needed to make from-tasty work. test cases: pos/i1753.scala, pos/t839.scala
980+
val tp2super = tp2.superType.widenExpr
981+
tp2super.isEffectivelySingleton && recur(tp1, tp2super)
979982
}
980983
case _ => false
981984

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

+10
Original file line numberDiff line numberDiff line change
@@ -328,6 +328,16 @@ object Types extends TypeUtils {
328328
/** Is this type a (possibly aliased) singleton type? */
329329
def isSingleton(using Context): Boolean = dealias.isInstanceOf[SingletonType]
330330

331+
/** Is this type a (possibly aliased) singleton type or a type proxy
332+
* or Or/And type known to be a singleton type?
333+
*/
334+
def isEffectivelySingleton(using Context): Boolean = dealias match
335+
case tp: SingletonType => true
336+
case tp: TypeProxy => tp.superType.isEffectivelySingleton
337+
case AndType(tpL, tpR) => tpL.isEffectivelySingleton || tpR.isEffectivelySingleton
338+
case OrType(tpL, tpR) => tpL.isEffectivelySingleton && tpR.isEffectivelySingleton
339+
case _ => false
340+
331341
/** Is this upper-bounded by a (possibly aliased) singleton type?
332342
* Overridden in TypeVar
333343
*/

tests/pos/i15030.scala

+16
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
sealed trait Schema[A]
2+
3+
object Schema extends RecordInstances:
4+
case class Field[A]()
5+
6+
sealed trait RecordInstances:
7+
self: Schema.type =>
8+
9+
case class Record[A](field: Field[A]) extends Schema[A]
10+
11+
import Schema._
12+
13+
val field: Field[Int] = Field()
14+
15+
// Uh oh Found Playground.Schema.Field[Int] but Requried RecordInstances.this.Field[Int]
16+
val record = Record[Int](field)

0 commit comments

Comments
 (0)