File tree Expand file tree Collapse file tree 2 files changed +41
-1
lines changed
compiler/src/dotty/tools/dotc/core Expand file tree Collapse file tree 2 files changed +41
-1
lines changed Original file line number Diff line number Diff line change @@ -872,7 +872,14 @@ class TypeComparer(initctx: Context) extends ConstraintHandling[AbsentContext] w
872872 || byGadtBounds(tycon1sym, tycon2, fromAbove = true )
873873 || byGadtBounds(tycon2sym, tycon1, fromAbove = false )
874874 ) && {
875- // check both tycons to deal with the case when they are equal b/c of GADT constraint
875+ // There are two cases in which we can assume injectivity.
876+ // First we check if either sym is a class.
877+ // Then:
878+ // 1) if we didn't touch GADTs, then both symbols are the same
879+ // (b/c of an earlier condition) and both are the same class
880+ // 2) if we touched GADTs, then the _other_ symbol (class syms
881+ // cannot have GADT constraints), the one w/ GADT cstrs,
882+ // must be instantiated, making the two tycons equal
876883 val tyconIsInjective =
877884 (tycon1sym.isClass || tycon2sym.isClass)
878885 && (if touchedGADTs then gadtIsInstantiated else true )
Original file line number Diff line number Diff line change 1+ object test {
2+
3+ enum SUB [- F , + G ] {
4+ case Refl [S ]() extends SUB [S , S ]
5+ }
6+
7+ enum KSUB [- F [_], + G [_]] {
8+ case Refl [S [_]]() extends KSUB [S , S ]
9+ }
10+
11+ def foo [F [_], G [_], A ](
12+ keq : (F KSUB Option , Option KSUB F ),
13+ ksub : Option KSUB G ,
14+ sub : F [A ] SUB G [Int ],
15+ a : A
16+ ) =
17+ keq._1 match { case KSUB .Refl () =>
18+ keq._2 match { case KSUB .Refl () =>
19+ ksub match { case KSUB .Refl () =>
20+ sub match { case SUB .Refl () =>
21+ // f = Option
22+ // & g >: Option
23+ // & f[a] <: g[I]
24+ // =X=>
25+ // a <: I
26+ // counterexample: g = [t] => Any
27+ val i : Int = a // error
28+ ()
29+ }
30+ }
31+ }
32+ }
33+ }
You can’t perform that action at this time.
0 commit comments