File tree Expand file tree Collapse file tree 4 files changed +101
-0
lines changed
compiler/src/dotty/tools/dotc Expand file tree Collapse file tree 4 files changed +101
-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 .tpd
11
+
12
+
13
+ /** A no-op transform that checks whether the compiled sources have no Phantom types in casts */
14
+ class CheckPhantomCast extends MiniPhaseTransform { thisTransformer =>
15
+
16
+ override def phaseName = " checkPhantomCast"
17
+
18
+ override def transformTypeApply (tree : tpd.TypeApply )(implicit ctx : Context , info : TransformerInfo ): tpd.Tree = {
19
+ if (tree.fun.symbol eq defn.Any_asInstanceOf )
20
+ checkNoPhantoms(tree.args.head)
21
+ tree
22
+ }
23
+
24
+ private def checkNoPhantoms (tpTree : tpd.Tree )(implicit ctx : Context ): Unit = {
25
+ val checker = new TypeMap {
26
+ override def apply (tp : Type ): Type = {
27
+ if (tp.isPhantom) {
28
+ ctx.error(" Cannot cast type containing a phantom type" , tpTree.pos)
29
+ tp
30
+ } else mapOver(tp)
31
+ }
32
+ }
33
+
34
+ checker(tpTree.tpe)
35
+ }
36
+
37
+ }
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
+ val b = new Baz
9
+ b.asInstanceOf [Foo {type T = BooAny }].z(any) // error
10
+ }
11
+
12
+ def foo (x : BooNothing ) = println(" foo" )
13
+
14
+ }
15
+
16
+ abstract class Foo {
17
+ type T <: BooAny
18
+ def y : T
19
+ def z (z : T ) = ()
20
+ }
21
+
22
+ class Bar {
23
+ type T = BooAny
24
+ def y : T = any
25
+ def z (z : T ) = ()
26
+ }
27
+
28
+ class Baz {
29
+ type T = BooNothing
30
+ def z (z : T ) = ()
31
+ }
32
+
33
+ object Boo extends Phantom {
34
+ type BooAny = this .Any
35
+ type BooNothing = this .Nothing
36
+ def any : BooAny = assume
37
+ }
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
+ val b = new Foo [BooNothing ](a.asInstanceOf [Foo [BooNothing ]].x) // error
10
+ b.asInstanceOf [Foo [BooAny ]].z(any) // error
11
+ }
12
+
13
+ def foo (x : BooNothing ) = println(" foo" )
14
+
15
+ }
16
+
17
+ class Foo [T <: BooAny ](val x : T ) {
18
+ def y : T = x
19
+ def z (z : T ) = ()
20
+ }
21
+
22
+ object Boo extends Phantom {
23
+ type BooAny = this .Any
24
+ type BooNothing = this .Nothing
25
+ def any : BooAny = assume
26
+ }
You can’t perform that action at this time.
0 commit comments