Skip to content

Commit 3be5349

Browse files
committed
WIP
1 parent 11f64e1 commit 3be5349

File tree

6 files changed

+115
-45
lines changed

6 files changed

+115
-45
lines changed

src/dotty/tools/dotc/typer/Typer.scala

+16-1
Original file line numberDiff line numberDiff line change
@@ -386,7 +386,10 @@ class Typer extends Namer with TypeAssigner with Applications with Implicits wit
386386
import untpd._
387387
val x = tpnme.ANON_CLASS
388388
val clsDef = TypeDef(x, templ).withFlags(Final)
389-
typed(cpy.Block(tree)(clsDef :: Nil, New(Ident(x), Nil)), pt)
389+
val typedBlock = typed(cpy.Block(tree)(clsDef :: Nil, New(Ident(x), Nil)), pt)
390+
if (typedBlock.tpe.derivesFrom(defn.PhantomAnyClass))
391+
ctx.error("Cannot instantiate anonymous phantom classes.", tree.pos)
392+
typedBlock
390393
case _ =>
391394
var tpt1 = typedType(tree.tpt)
392395
tpt1.tpe.dealias match {
@@ -576,6 +579,8 @@ class Typer extends Namer with TypeAssigner with Applications with Implicits wit
576579
val cond1 = typed(tree.cond, defn.BooleanType)
577580
val thenp1 = typed(tree.thenp, pt)
578581
val elsep1 = typed(tree.elsep orElse (untpd.unitLiteral withPos tree.pos), pt)
582+
checkNotPhantomExpr("Cannot yield a phantom type in one of the if branches", thenp1)
583+
checkNotPhantomExpr("Cannot yield a phantom type in one of the if branches", elsep1)
579584
val thenp2 :: elsep2 :: Nil = harmonize(thenp1 :: elsep1 :: Nil)
580585
assignType(cpy.If(tree)(cond1, thenp2, elsep2), thenp2, elsep2)
581586
}
@@ -744,6 +749,7 @@ class Typer extends Namer with TypeAssigner with Applications with Implicits wit
744749
typed(desugar.makeCaseLambda(tree.cases, protoFormals.length) withPos tree.pos, pt)
745750
case _ =>
746751
val sel1 = typedExpr(tree.selector)
752+
checkNotPhantomExpr("Cannot pattern match on phantom objects", sel1)
747753
val selType = widenForMatchSelector(
748754
fullyDefinedType(sel1.tpe, "pattern selector", tree.pos))
749755

@@ -814,6 +820,7 @@ class Typer extends Namer with TypeAssigner with Applications with Implicits wit
814820
val guard1 = typedExpr(tree.guard, defn.BooleanType)
815821
val body1 = ensureNoLocalRefs(typedExpr(tree.body, pt), pt, ctx.scope.toList)
816822
.ensureConforms(pt)(originalCtx) // insert a cast if body does not conform to expected type if we disregard gadt bounds
823+
checkNotPhantomExpr("Pattern matches cannot return phantom objects", body1)
817824
assignType(cpy.CaseDef(tree)(pat1, guard1, body1), body1)
818825
}
819826

@@ -870,6 +877,7 @@ class Typer extends Namer with TypeAssigner with Applications with Implicits wit
870877
(from, proto)
871878
}
872879
val expr1 = typedExpr(tree.expr orElse untpd.unitLiteral.withPos(tree.pos), proto)
880+
checkNotPhantomExpr("Cannot use 'return' with phantom objects", expr1)
873881
assignType(cpy.Return(tree)(expr1, from))
874882
}
875883

@@ -879,6 +887,7 @@ class Typer extends Namer with TypeAssigner with Applications with Implicits wit
879887
val finalizer1 = typed(tree.finalizer, defn.UnitType)
880888
val expr2 :: cases2x = harmonize(expr1 :: cases1)
881889
val cases2 = cases2x.asInstanceOf[List[CaseDef]]
890+
checkNotPhantomExpr("Cannot return a phantom object in a try", expr2)
882891
assignType(cpy.Try(tree)(expr2, cases2, finalizer1), expr2, cases2)
883892
}
884893

@@ -1855,4 +1864,10 @@ class Typer extends Namer with TypeAssigner with Applications with Implicits wit
18551864
}
18561865
}
18571866
}
1867+
1868+
private def checkNotPhantomExpr(msg: => String, expr: Tree)(implicit ctx: Context): Unit = {
1869+
if (expr.tpe.derivesFrom(defn.PhantomAnyClass))
1870+
ctx.error(msg, expr.pos)
1871+
}
1872+
18581873
}

tests/neg/phantomClass4.scala

+11
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
import dotty.phantom.PhantomAny
2+
3+
class Blinky extends PhantomAny {
4+
def boo1 = new PhantomAny {} // error
5+
def boo2 = new Inky {} // error
6+
def boo3 = new Pinky {} // error
7+
}
8+
9+
abstract class Inky extends PhantomAny
10+
11+
trait Pinky extends PhantomAny

tests/neg/phantomExpr.scala

+22
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
import dotty.phantom.PhantomAny
2+
3+
object Blinky extends PhantomAny
4+
object Inky extends PhantomAny
5+
6+
class Foo {
7+
val b = true
8+
def fooIf1 = if (b) { Blinky } else { Inky } // error // error
9+
// def fooIf2 = if (b) { Blinky } else { "" } // FIXME: emmits error but than crashes
10+
// def fooIf3 = if (b) { "" } else { Blinky } // FIXME: emmits error but than crashes
11+
12+
def fooMatch1 = Blinky match { case Blinky => () } // error
13+
def fooMatch2 = 1 match { case _ => Blinky } // error
14+
def fooMatch3 = 1 match { case Blinky => () } // error
15+
16+
// def fooTry1 = try { Blinky } catch { case e: Throwable => } // FIXME: emmits error but than crashes
17+
// def fooTry2 = try { } catch { case e: Throwable => Blinky } // FIXME: emmits error but than crashes
18+
19+
def fooReturn1: PhantomAny = return Blinky // error // error
20+
def fooReturn2 = return Blinky // error // error
21+
22+
}

tests/neg/phantomExpr2.scala

+8
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
import dotty.phantom.PhantomAny
2+
3+
object Blinky extends PhantomAny
4+
object Inky extends PhantomAny
5+
6+
class Foo {
7+
def fooTry1 = try { } finally { Blinky } // error
8+
}

tests/run/phantom.check

+4
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
fun1
22
fun1
33
fun1
4+
fun1
45
fun2
56
fun2
67
fun2
@@ -18,20 +19,23 @@ polyfun2
1819
polyfun2
1920
polyfun2
2021
polyfun2
22+
polyfun2
2123
Boo6
2224
polyfun3
2325
Boo6
2426
polyfun3
2527
polyfun3
2628
polyfun3
2729
polyfun3
30+
polyfun3
2831
Boo6
2932
polyfun4
3033
Boo6
3134
polyfun4
3235
polyfun4
3336
polyfun4
3437
polyfun4
38+
polyfun4
3539
Boo1
3640
Boo1.polyfun1
3741
Boo1

tests/run/phantom.scala

+54-44
Original file line numberDiff line numberDiff line change
@@ -8,104 +8,114 @@ object Test {
88
import dotty.phantom.PhantomNothing
99
import Phantoms._
1010

11+
trait Phantoms {
12+
type Clyde >: Pinky <: Inky
13+
}
14+
15+
object Phantoms extends Phantoms {
16+
trait Blinky extends PhantomAny
17+
abstract class Inky extends Blinky
18+
class Pinky extends Inky
19+
object Moroi extends Pinky
20+
}
21+
1122
def main(args: Array[String]): Unit = {
12-
fun1(new Blinky {})
13-
fun1(new Inky {})
23+
class BlinkyImpl extends Blinky
24+
class InkyImpl extends Inky
25+
26+
fun1(new BlinkyImpl)
27+
fun1(new InkyImpl)
1428
fun1(new Pinky)
29+
fun1(Moroi)
1530

16-
fun3(new Blinky {}, new Pinky)
17-
fun3(new Inky {}, new Pinky)
18-
fun3(new Pinky, new Pinky)
31+
fun3(new BlinkyImpl, new Pinky)
32+
fun3(new InkyImpl, new Pinky)
33+
fun3(new Pinky, Moroi)
1934

20-
fun4(3, 4)(new Blinky {}, new Pinky)
21-
fun4(5, 6)(new Inky {}, new Pinky)
22-
fun4(7, 8)(new Pinky, new Pinky)
35+
fun4(3, 4)(new BlinkyImpl, new Pinky)
36+
fun4(5, 6)(new InkyImpl, new Pinky)
37+
fun4(7, 8)(new Pinky, Moroi)
2338

24-
fun5(new Blinky {}, new Pinky)(15, 16)
25-
fun5(new Inky {}, new Pinky)(17, 18)
26-
fun5(new Pinky, new Pinky)(19, 20)
39+
fun5(new BlinkyImpl, new Pinky)(15, 16)
40+
fun5(new InkyImpl, new Pinky)(17, 18)
41+
fun5(new Pinky, Moroi)(19, 20)
2742

2843
polyfun1()
2944

3045
polyfun2(new Boo6().boo1)
3146
polyfun2(new Boo6().boo2)
32-
println("polyfun2") // polyfun2(new Blinky {}) // FIXME: error: Type argument (Object & Test.Phantoms.Blinky)' does not conform to lower bound PhantomNothing
33-
polyfun2(new Inky {})
47+
polyfun2(new BlinkyImpl)
48+
polyfun2(new InkyImpl)
3449
polyfun2(new Pinky)
50+
polyfun2(Moroi)
3551

3652
polyfun3(new Boo6().boo1)
3753
polyfun3(new Boo6().boo2)
38-
println("polyfun3") // polyfun3(new Blinky {}) FIXME
39-
polyfun3(new Inky {})
54+
polyfun3(new BlinkyImpl)
55+
polyfun3(new InkyImpl)
4056
polyfun3(new Pinky)
57+
polyfun3(Moroi)
4158

4259
polyfun4(new Boo6().boo1)
4360
polyfun4(new Boo6().boo2)
44-
println("polyfun4") // polyfun4(new Blinky {}) FIXME
45-
polyfun4(new Inky {})
61+
polyfun4(new BlinkyImpl)
62+
polyfun4(new InkyImpl)
4663
polyfun4(new Pinky)
64+
polyfun4(Moroi)
4765

48-
new Boo1[PhantomAny]().polyfun1(new Blinky {})
49-
new Boo1[PhantomAny]().polyfun1(new Inky {})
66+
new Boo1[PhantomAny]().polyfun1(new BlinkyImpl)
67+
new Boo1[PhantomAny]().polyfun1(new InkyImpl)
5068

51-
new Boo2().polyfun1(new Blinky {})
52-
new Boo2().polyfun1(new Inky {})
69+
new Boo2().polyfun1(new BlinkyImpl)
70+
new Boo2().polyfun1(new InkyImpl)
5371
new Boo2().polyfun1(new Pinky)
5472

5573
new Boo3(){
5674
type Boo = PhantomAny
5775
}.polyfun1(new Pinky)
5876
new Boo3(){
5977
type Boo = Blinky
60-
}.polyfun1(new Blinky {})
78+
}.polyfun1(new BlinkyImpl)
6179

62-
new Boo4(new Blinky {})
63-
new Boo4(new Inky {})
80+
new Boo4(new BlinkyImpl)
81+
new Boo4(new InkyImpl)
6482
new Boo4(new Pinky)
6583

6684
new Boo5[PhantomAny](new Pinky)
6785
new Boo5[Pinky](new Pinky)
6886

6987
fun(phantomFun1())
7088

71-
fun(phantomFun2(new Blinky {}))
72-
fun(phantomFun2(new Inky {}))
89+
fun(phantomFun2(new BlinkyImpl))
90+
fun(phantomFun2(new InkyImpl))
7391
fun(phantomFun2(new Pinky))
7492

75-
// fun(phantomFun3(new Blinky {})) FIXME
76-
fun(phantomFun3(new Inky {}))
93+
fun(phantomFun3(new BlinkyImpl))
94+
fun(phantomFun3(new InkyImpl))
7795
fun(phantomFun3(new Pinky))
7896

79-
// fun(phantomFun4(new Blinky {})) FIXME
80-
fun(phantomFun4(new Inky {}))
97+
fun(phantomFun4(new BlinkyImpl))
98+
fun(phantomFun4(new InkyImpl))
8199
fun(phantomFun4(new Pinky))
82100

83-
pacFun1(new Blinky {})
84-
pacFun1(new Inky {})
101+
pacFun1(new BlinkyImpl)
102+
pacFun1(new InkyImpl)
85103
pacFun1(new Pinky)
86104

87105
pacFun2(new Pinky)
88106

89107
pacFun3(new Pinky)
90108

91-
println("hkFun1") // hkFun1(new Blinky {}) // FIXME
92-
hkFun1(new Inky {})
109+
hkFun1(new BlinkyImpl)
110+
hkFun1(new InkyImpl)
93111
hkFun1(new Pinky)
94112

95-
// fun(hkFun2(new Blinky {})) FIXME
96-
fun(hkFun2(new Inky {}))
113+
fun(hkFun2(new BlinkyImpl))
114+
fun(hkFun2(new InkyImpl))
97115
fun(hkFun2(new Pinky))
98116
}
99117

100-
trait Phantoms {
101-
type Clyde >: Pinky <: Inky
102-
}
103118

104-
object Phantoms extends Phantoms {
105-
trait Blinky extends PhantomAny
106-
abstract class Inky extends Blinky
107-
class Pinky extends Inky
108-
}
109119

110120
def fun(top: PhantomAny): Unit = ()
111121

0 commit comments

Comments
 (0)