@@ -123,7 +123,7 @@ class TypeComparer(initctx: Context) extends DotClass with ConstraintHandling {
123
123
pendingSubTypes = new mutable.HashSet [(Type , Type )]
124
124
ctx.log(s " !!! deep subtype recursion involving ${tp1.show} <:< ${tp2.show}, constraint = ${state.constraint.show}" )
125
125
ctx.log(s " !!! constraint = ${constraint.show}" )
126
- assert( ! ctx.settings.YnoDeepSubtypes .value)
126
+ if ( ctx.settings.YnoDeepSubtypes .value) throw new Error ( " deep subtype " )
127
127
if (Config .traceDeepSubTypeRecursions && ! this .isInstanceOf [ExplainingTypeComparer ])
128
128
ctx.log(TypeComparer .explained(implicit ctx => ctx.typeComparer.isSubType(tp1, tp2)))
129
129
}
@@ -779,8 +779,24 @@ class TypeComparer(initctx: Context) extends DotClass with ConstraintHandling {
779
779
else {
780
780
val t2 = mergeIfSub(tp2, tp1)
781
781
if (t2.exists) t2
782
- else andType(tp1, tp2)
783
- }
782
+ else tp1 match {
783
+ case tp1 : ConstantType =>
784
+ tp2 match {
785
+ case tp2 : ConstantType =>
786
+ // Make use of the fact that the intersection of two constant types
787
+ // types which are not subtypes of each other is known to be empty.
788
+ // Note: The same does not apply to singleton types in general.
789
+ // E.g. we could have a pattern match against `x.type & y.type`
790
+ // which might succeed if `x` and `y` happen to be the same ref
791
+ // at run time. It would not work to replace that with `Nothing`.
792
+ // However, maybe we can still apply the replacement to
793
+ // types which are not explicitly written.
794
+ defn.NothingType
795
+ case _ => andType(tp1, tp2)
796
+ }
797
+ case _ => andType(tp1, tp2)
798
+ }
799
+ }
784
800
}
785
801
}
786
802
}
0 commit comments