File tree Expand file tree Collapse file tree 4 files changed +125
-0
lines changed
compiler/src/dotty/tools/dotc Expand file tree Collapse file tree 4 files changed +125
-0
lines changed Original file line number Diff line number Diff line change @@ -49,6 +49,7 @@ class Compiler {
49
49
List (new FirstTransform , // Some transformations to put trees into a canonical form
50
50
new CheckReentrant ), // Internal use only: Check that compiled program has no data races involving global vars
51
51
List (new CheckStatic , // Check restrictions that apply to @static members
52
+ new CheckPhantomCast , // Checks that no Phantom types in are in casts
52
53
new ElimRepeated , // Rewrite vararg parameters and arguments
53
54
new RefChecks , // Various checks mostly related to abstract members and overriding
54
55
new NormalizeFlags , // Rewrite some definition flags
Original file line number Diff line number Diff line change
1
+ package dotty .tools .dotc
2
+ package transform
3
+
4
+ import core ._
5
+ import dotty .tools .dotc .transform .TreeTransforms .{MiniPhaseTransform , TransformerInfo }
6
+ import Types ._
7
+ import Contexts .Context
8
+ import Symbols ._
9
+ import Decorators ._
10
+ import dotty .tools .dotc .ast .Trees ._
11
+ import dotty .tools .dotc .ast .tpd
12
+
13
+
14
+ /** A no-op transform to ensure that the compiled sources have no Phantom types in casts */
15
+ class CheckPhantomCast extends MiniPhaseTransform { thisTransformer =>
16
+
17
+ override def phaseName = " checkPhantomCast"
18
+
19
+ override def transformTypeApply (tree : tpd.TypeApply )(implicit ctx : Context , info : TransformerInfo ): tpd.Tree = {
20
+ if (tree.fun.symbol eq defn.Any_asInstanceOf )
21
+ checkNoPhantoms(tree.args.head)
22
+ tree
23
+ }
24
+
25
+ override def transformBind (tree : tpd.Bind )(implicit ctx : Context , info : TransformerInfo ): tpd.Tree = {
26
+ tree.body match {
27
+ case Typed (_, tpt) => checkNoPhantoms(tpt)
28
+ case _ =>
29
+ }
30
+ tree
31
+ }
32
+
33
+ private def checkNoPhantoms (tpTree : tpd.Tree )(implicit ctx : Context ): Unit = {
34
+ val checker = new TypeTraverser () {
35
+ override def traverse (tp : Type ): Unit = {
36
+ if (tp.isPhantom) ctx.error(" Cannot cast type containing a phantom type" , tpTree.pos)
37
+ else traverseChildren(tp)
38
+ }
39
+ }
40
+ checker.traverse(tpTree.tpe)
41
+ }
42
+
43
+ }
Original file line number Diff line number Diff line change
1
+ import Boo ._
2
+
3
+ object Test {
4
+ def main (args : Array [String ]): Unit = {
5
+ val a = new Bar ()
6
+ foo(a.asInstanceOf [Foo {type T = BooNothing }].y) // error
7
+
8
+ a match {
9
+ case a : Foo {type T = BooNothing } => a.y // error
10
+ }
11
+
12
+ val b = new Baz
13
+ b.asInstanceOf [Foo {type T = BooAny }].z(any) // error
14
+
15
+ b match {
16
+ case b : Foo {type T = BooAny } => a.z(any) // error
17
+ }
18
+ }
19
+
20
+ def foo (x : BooNothing ) = println(" foo" )
21
+
22
+ }
23
+
24
+ abstract class Foo {
25
+ type T <: BooAny
26
+ def y : T
27
+ def z (z : T ): Unit
28
+ }
29
+
30
+ class Bar extends Foo {
31
+ type T = BooAny
32
+ def y : T = any
33
+ def z (z : T ) = ()
34
+ }
35
+
36
+ class Baz extends Foo {
37
+ type T = BooNothing
38
+ def y : T = nothing
39
+ def z (z : T ) = ()
40
+ }
41
+
42
+ object Boo extends Phantom {
43
+ type BooAny = this .Any
44
+ type BooNothing = this .Nothing
45
+ def any : BooAny = assume
46
+ def nothing : BooNothing = assume
47
+ }
Original file line number Diff line number Diff line change
1
+ import Boo ._
2
+
3
+ object Test {
4
+ def main (args : Array [String ]): Unit = {
5
+ val a = new Foo [BooAny ](any)
6
+ foo(a.asInstanceOf [Foo [BooNothing ]].x) // error
7
+ foo(a.asInstanceOf [Foo [BooNothing ]].y) // error
8
+
9
+ a match {
10
+ case a : Foo [BooNothing ] => a.x // error
11
+ }
12
+
13
+ val b = new Foo [BooNothing ](a.asInstanceOf [Foo [BooNothing ]].x) // error
14
+ b.asInstanceOf [Foo [BooAny ]].z(any) // error
15
+
16
+ b match {
17
+ case b : Foo [BooAny ] => b.z(any) // error
18
+ }
19
+ }
20
+
21
+ def foo (x : BooNothing ) = println(" foo" )
22
+
23
+ }
24
+
25
+ class Foo [T <: BooAny ](val x : T ) {
26
+ def y : T = x
27
+ def z (z : T ) = ()
28
+ }
29
+
30
+ object Boo extends Phantom {
31
+ type BooAny = this .Any
32
+ type BooNothing = this .Nothing
33
+ def any : BooAny = assume
34
+ }
You can’t perform that action at this time.
0 commit comments