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 {
4949 List (new FirstTransform , // Some transformations to put trees into a canonical form
5050 new CheckReentrant ), // Internal use only: Check that compiled program has no data races involving global vars
5151 List (new CheckStatic , // Check restrictions that apply to @static members
52+ new CheckPhantomCast , // Checks that no Phantom types in are in casts
5253 new ElimRepeated , // Rewrite vararg parameters and arguments
5354 new RefChecks , // Various checks mostly related to abstract members and overriding
5455 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