File tree 9 files changed +186
-2
lines changed
compiler/src/dotty/tools/dotc/typer
9 files changed +186
-2
lines changed Original file line number Diff line number Diff line change @@ -250,8 +250,7 @@ object Inferencing {
250
250
* approx, see gadt-approximation-interaction.scala).
251
251
*/
252
252
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
255
254
&& ctx.gadt.contains(tp.symbol)
256
255
=>
257
256
val sym = tp.symbol
Original file line number Diff line number Diff line change @@ -2030,6 +2030,15 @@ class Typer extends Namer
2030
2030
val tparamss = paramss1.collect {
2031
2031
case untpd.TypeDefs (tparams) => tparams
2032
2032
}
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
+ .map(ctx => rhsCtx.gadt.addToConstraint(ctx.owner.typeParams))
2041
+
2033
2042
if tparamss.nonEmpty then
2034
2043
rhsCtx.setFreshGADTBounds
2035
2044
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