File tree Expand file tree Collapse file tree 9 files changed +186
-2
lines changed
compiler/src/dotty/tools/dotc/typer Expand file tree Collapse file tree 9 files changed +186
-2
lines changed Original file line number Diff line number Diff line change @@ -250,8 +250,7 @@ object Inferencing {
250250 * approx, see gadt-approximation-interaction.scala).
251251 */
252252 def apply (tp : Type ): Type = tp.dealias match {
253- case tp @ TypeRef (qual, nme) if (qual eq NoPrefix )
254- && variance != 0
253+ case tp @ TypeRef (qual, nme) if variance != 0
255254 && ctx.gadt.contains(tp.symbol)
256255 =>
257256 val sym = tp.symbol
Original file line number Diff line number Diff line change @@ -2030,6 +2030,15 @@ class Typer extends Namer
20302030 val tparamss = paramss1.collect {
20312031 case untpd.TypeDefs (tparams) => tparams
20322032 }
2033+
2034+ // Register GADT constraint for class type parameters from outer to inner class definition. (Useful when nested classes exist.) But do not cross a function definition.
2035+ if sym.flags.is(Method ) then
2036+ rhsCtx.setFreshGADTBounds
2037+ ctx.outer.outersIterator.takeWhile(! _.owner.is(Method ))
2038+ .filter(ctx => ctx.owner.isClass && ctx.owner.typeParams.nonEmpty)
2039+ .toList.reverse
2040+ .foreach(ctx => rhsCtx.gadt.addToConstraint(ctx.owner.typeParams))
2041+
20332042 if tparamss.nonEmpty then
20342043 rhsCtx.setFreshGADTBounds
20352044 val tparamSyms = tparamss.flatten.map(_.symbol)
Original file line number Diff line number Diff line change 1+ object basic {
2+ enum Expr [A ] {
3+ case IntExpr (value : Int ) extends Expr [Int ]
4+ case Other [T ](value : T ) extends Expr [T ]
5+ }
6+
7+ class C [A ] {
8+ def eval (e : Expr [A ]): A =
9+ e match {
10+ case Expr .IntExpr (i) => i + 2
11+ case Expr .Other (v) => v
12+ }
13+ }
14+ }
Original file line number Diff line number Diff line change 1+ object inheritance {
2+ enum SUB [- A , + B ]:
3+ case Refl [S ]() extends SUB [S , S ]
4+
5+ class A [T ](val v : T ) {
6+ val foo1 : T = v
7+ }
8+
9+ class C [T ](val v1 : T ) extends A [T ](v1) {
10+ def eval1 (t : T , e : SUB [T , Int ]): Int =
11+ e match {
12+ case SUB .Refl () => foo1
13+ }
14+ }
15+ }
Original file line number Diff line number Diff line change 1+ object member {
2+ enum SUB [- A , + B ]:
3+ case Refl [S ]() extends SUB [S , S ]
4+
5+ class C [T ] {
6+ def eval1 (t : T , e : SUB [T , Int ]): Int =
7+ e match {
8+ case SUB .Refl () => t + 2
9+ }
10+ }
11+ }
Original file line number Diff line number Diff line change 1+ // Nested class for GADT constraining
2+ object nestedClass {
3+ enum Expr [A ] {
4+ case IntExpr (value : Int ) extends Expr [Int ]
5+ case Other [T ](value : T ) extends Expr [T ]
6+ }
7+
8+ class Outer1 [C ] {
9+ class Inner1 {
10+ def eval (e : Expr [C ]): C =
11+ e match {
12+ case Expr .IntExpr (i) => i + 2
13+ case Expr .Other (v) => v
14+ }
15+ }
16+ }
17+
18+ def foo2 [C ](): Unit =
19+ class Outer2 {
20+ class Inner2 {
21+ def eval (e : Expr [C ]): C =
22+ e match {
23+ case Expr .IntExpr (i) => i + 2
24+ case Expr .Other (v) => v
25+ }
26+ }
27+ }
28+
29+ class Outer3 [C ] {
30+ def foo3 (): Unit =
31+ class Inner3 {
32+ def eval (e : Expr [C ]): C =
33+ e match {
34+ case Expr .IntExpr (i) => i + 2
35+ case Expr .Other (v) => v
36+ }
37+ }
38+ }
39+
40+ trait Outer4 [C ] {
41+ class Inner4 {
42+ def eval (e : Expr [C ]): C =
43+ e match {
44+ case Expr .IntExpr (i) => i + 2
45+ case Expr .Other (v) => v
46+ }
47+ }
48+ }
49+
50+ class Outer5 [C ] {
51+ object Inner5 {
52+ def eval (e : Expr [C ]): C =
53+ e match {
54+ case Expr .IntExpr (i) => i + 2
55+ case Expr .Other (v) => v
56+ }
57+ }
58+ }
59+ }
Original file line number Diff line number Diff line change 1+ object variance {
2+ enum SUB [- A , + B ]:
3+ case Refl [S ]() extends SUB [S , S ]
4+ // Covariant
5+ class C1 [+ T ](v : T ){
6+ def foo (ev : T SUB Int ): Int =
7+ ev match {
8+ case SUB .Refl () => v
9+ }
10+ }
11+
12+ // Contravariant
13+ class B2 [- T ](v : T ){}
14+
15+ class C2 [- T ](v : T ){
16+ def foo (ev : Int SUB T ): B2 [T ] =
17+ ev match {
18+ case SUB .Refl () => new B2 (v)
19+ }
20+ }
21+
22+ // Variance with inheritance
23+
24+ // superclass covariant and subclass covariant
25+
26+ class A3 [+ T ](v : T ) {
27+ val value = v
28+ }
29+
30+ class C3 [+ T ](v : T ) extends A3 [T ](v){
31+ def foo (ev : T SUB Int ): Int =
32+ ev match {
33+ case SUB .Refl () => value
34+ }
35+ }
36+
37+
38+ // superclass covariant and subclass invariant
39+ class A4 [+ T ](v : T ) {
40+ val value = v
41+ }
42+
43+ class C4 [T ](v : T ) extends A4 [T ](v){
44+ def foo (ev : T SUB Int ): Int =
45+ ev match {
46+ case SUB .Refl () => value
47+ }
48+ }
49+
50+ // superclass contravariant and subclass contravariant
51+ class B5 [- T ](v : T ){}
52+
53+ class A5 [- T ](v : T ) {
54+ val value = new B5 (v)
55+ }
56+
57+ class C5 [- T ](v : T ) extends A5 [T ](v){
58+ def foo (ev : Int SUB T ): B5 [T ] =
59+ ev match {
60+ case SUB .Refl () => value
61+ }
62+ }
63+
64+ // superclass contravariant and subclass invariant
65+ class B6 [- T ](v : T ){}
66+
67+ class A6 [- T ](v : T ) {
68+ val value = new B6 (v)
69+ }
70+
71+ class C6 [- T ](v : T ) extends A6 [T ](v){
72+ def foo (ev : Int SUB T ): B6 [T ] =
73+ ev match {
74+ case SUB .Refl () => value
75+ }
76+ }
77+ }
File renamed without changes.
File renamed without changes.
You can’t perform that action at this time.
0 commit comments