Skip to content

Disallow phantom type parameter/member in classes #2442

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions compiler/src/dotty/tools/dotc/typer/Checking.scala
Original file line number Diff line number Diff line change
Expand Up @@ -473,6 +473,16 @@ object Checking {
stats.foreach(checkValueClassMember)
}
}

/** Verify type definitions meet the requirements */
def checkTypeDef(tdef: tpd.TypeDef)(implicit ctx: Context): Unit = {
val isParam = tdef.tpe.typeSymbol.is(Param)
val isPhantom = tdef.tpe.isPhantom
if (isParam && isPhantom && tdef.symbol.owner.isPrimaryConstructor)
ctx.error("Classes cannot have phantom type parameters", tdef.pos)
else if (!isParam && isPhantom && !tdef.symbol.owner.isStaticOwner)
ctx.error("Non static classes cannot have phantom type members", tdef.pos)
}
}

trait Checking {
Expand Down
4 changes: 3 additions & 1 deletion compiler/src/dotty/tools/dotc/typer/Typer.scala
Original file line number Diff line number Diff line change
Expand Up @@ -1261,7 +1261,9 @@ class Typer extends Namer with TypeAssigner with Applications with Implicits wit
case rhs =>
typedType(rhs)
}
assignType(cpy.TypeDef(tdef)(name, rhs1), sym)
val tdef1 = assignType(cpy.TypeDef(tdef)(name, rhs1), sym)
Checking.checkTypeDef(tdef1)
tdef1
}

def typedClassDef(cdef: untpd.TypeDef, cls: ClassSymbol)(implicit ctx: Context) = track("typedClassDef") {
Expand Down
2 changes: 1 addition & 1 deletion tests/neg/phantom-bottom.scala
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ class BooFunDef1 {
}

class Foo {
type Y <: Boo.BooAny
type Y <: Boo.BooAny // error
}

object Boo extends Phantom {
Expand Down
37 changes: 37 additions & 0 deletions tests/neg/phantom-class-type-members.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import Boo._

object Test {
def main(args: Array[String]): Unit = {
val a = new Bar()
foo(a.asInstanceOf[Foo{type T = BooNothing}].y) // error

val b = new Baz
b.asInstanceOf[Foo{type T = BooAny}].z(any) // error
}

def foo(x: BooNothing) = println("foo")

}

abstract class Foo {
type T <: BooAny // error
def y: T
def z(z: T) = ()
}

class Bar {
type T = BooAny // error
def y: T = any
def z(z: T) = ()
}

class Baz {
type T = BooNothing // error
def z(z: T) = ()
}

object Boo extends Phantom {
type BooAny = this.Any
type BooNothing = this.Nothing
def any: BooAny = assume
}
26 changes: 26 additions & 0 deletions tests/neg/phantom-class-type-parameters.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import Boo._

object Test {
def main(args: Array[String]): Unit = {
val a = new Foo[BooAny](any)
foo(a.asInstanceOf[Foo[BooNothing]].x) // should not be possible
foo(a.asInstanceOf[Foo[BooNothing]].y) // should not be possible

val b = new Foo[BooNothing](a.asInstanceOf[Foo[BooNothing]].x)
b.asInstanceOf[Foo[BooAny]].z(any) // should not be possible
}

def foo(x: BooNothing) = println("foo")

}

class Foo[T <: BooAny](val x: T) { // error
def y: T = x
def z(z: T) = ()
}

object Boo extends Phantom {
type BooAny = this.Any
type BooNothing = this.Nothing
def any: BooAny = assume
}
6 changes: 2 additions & 4 deletions tests/neg/phantom-classOf-2.scala
Original file line number Diff line number Diff line change
@@ -1,10 +1,8 @@

class phantomClassOf {
type Blinky <: Boo.BooAny

classOf[Blinky] // error
classOf[Boo.Blinky] // error
}

object Boo extends Phantom {
type BooAny = this.Any
type Blinky = this.Any
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ object Test {

def fun(top: BooAny): Unit = ()

class Boo1[P <: BooAny] {
class Boo1[P <: BooAny] { // error
println("Boo1")
def polyfun1(p1: P): Unit = {
println("Boo1.polyfun1")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ object Test {
new Boo5[Pinky](boo[Pinky])
}

class Boo5[P <: Blinky](p5: P) {
class Boo5[P <: Blinky](p5: P) { // error
println("Boo5")
}
}
Expand Down
5 changes: 2 additions & 3 deletions tests/neg/phantom-expr.scala
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,6 @@ class Foo {
import Boo._
import Boo1._

type Blinky <: BooAny
type Inky <: BooAny

val blinky = Boo.boo[Blinky]
val inky = Boo.boo[Inky]

Expand Down Expand Up @@ -40,6 +37,8 @@ class Foo {

object Boo extends Phantom {
type BooAny = this.Any
type Blinky <: BooAny
type Inky <: BooAny
def boo[B <: BooAny]: B = assume
}

Expand Down
4 changes: 0 additions & 4 deletions tests/run/phantom-decls-1.check

This file was deleted.

3 changes: 2 additions & 1 deletion tests/run/phantom-decls-2.scala
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,10 @@ object Test {
new Boo2().polyfun1(boo[Pinky])
}

type Boo3 = BooAny

class Boo2 {
println("Boo2")
type Boo3 = BooAny
def polyfun1(p2: Boo3): Unit = {
println("Boo2.polyfun1")
}
Expand Down
14 changes: 4 additions & 10 deletions tests/run/phantom-decls-3.scala
Original file line number Diff line number Diff line change
Expand Up @@ -7,20 +7,14 @@ object Test {
import Boo._

def main(args: Array[String]): Unit = {

new Boo3(){
type Boo1 = BooAny
}.polyfun1(boo[Pinky])

new Boo3(){
type Boo1 = Blinky
}.polyfun1(boo[Blinky])

new Boo3(){ }.polyfun1(boo[Pinky])
new Boo3(){ }.polyfun1(boo[Blinky])
}

type Boo1 = BooAny

trait Boo3 {
println("Boo3")
type Boo1 <: BooAny
def polyfun1(p3: Boo1): Unit = {
println("Boo3.polyfun1")
}
Expand Down
2 changes: 0 additions & 2 deletions tests/run/phantom-decls-5.check

This file was deleted.