aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/dotty/tools/dotc/typer/RefChecks.scala16
-rw-r--r--test/dotc/tests.scala2
-rw-r--r--tests/neg/i705-inner-value-class.scala7
-rw-r--r--tests/pos/extmethods.scala1
4 files changed, 22 insertions, 4 deletions
diff --git a/src/dotty/tools/dotc/typer/RefChecks.scala b/src/dotty/tools/dotc/typer/RefChecks.scala
index 6a31b66aa..bb22e2045 100644
--- a/src/dotty/tools/dotc/typer/RefChecks.scala
+++ b/src/dotty/tools/dotc/typer/RefChecks.scala
@@ -655,7 +655,17 @@ object RefChecks {
}
/** Verify classes extending AnyVal meet the requirements */
- private def checkDerivedValueClass(clazz: Symbol)(implicit ctx: Context) =
+ private def checkDerivedValueClass(clazz: Symbol, stats: List[Tree])(implicit ctx: Context) = {
+ def checkValueClassMember(stat: Tree) = stat match {
+ case _: ValDef if !stat.symbol.is(ParamAccessor) =>
+ ctx.error(s"value class may not define non-parameter field", stat.pos)
+ case _: DefDef if stat.symbol.isConstructor =>
+ ctx.error(s"value class may not define secondary constructor", stat.pos)
+ case _: MemberDef | _: Import | EmptyTree =>
+ // ok
+ case _ =>
+ ctx.error(s"value class may not contain initialization statements", stat.pos)
+ }
if (isDerivedValueClass(clazz)) {
if (clazz.is(Trait))
ctx.error("Only classes (not traits) are allowed to extend AnyVal", clazz.pos)
@@ -663,7 +673,9 @@ object RefChecks {
ctx.error("`abstract' modifier cannot be used with value classes", clazz.pos)
if (!clazz.isStatic)
ctx.error("value class cannot be an inner class", clazz.pos)
+ stats.foreach(checkValueClassMember)
}
+ }
type LevelAndIndex = immutable.Map[Symbol, (LevelInfo, Int)]
@@ -780,7 +792,7 @@ class RefChecks extends MiniPhase { thisTransformer =>
checkParents(cls)
checkCompanionNameClashes(cls)
checkAllOverrides(cls)
- checkDerivedValueClass(cls)
+ checkDerivedValueClass(cls, tree.body)
tree
}
diff --git a/test/dotc/tests.scala b/test/dotc/tests.scala
index 1cdd9f38a..9b5748a07 100644
--- a/test/dotc/tests.scala
+++ b/test/dotc/tests.scala
@@ -134,7 +134,7 @@ class tests extends CompilerTest {
@Test def neg_i0281 = compileFile(negDir, "i0281-null-primitive-conforms", xerrors = 3)
@Test def neg_i583 = compileFile(negDir, "i0583-skolemize", xerrors = 2)
@Test def neg_finalSealed = compileFile(negDir, "final-sealed", xerrors = 2)
- @Test def neg_i705 = compileFile(negDir, "i705-inner-value-class", xerrors = 3)
+ @Test def neg_i705 = compileFile(negDir, "i705-inner-value-class", xerrors = 7)
@Test def neg_moduleSubtyping = compileFile(negDir, "moduleSubtyping", xerrors = 4)
@Test def neg_escapingRefs = compileFile(negDir, "escapingRefs", xerrors = 2)
@Test def neg_instantiateAbstract = compileFile(negDir, "instantiateAbstract", xerrors = 8)
diff --git a/tests/neg/i705-inner-value-class.scala b/tests/neg/i705-inner-value-class.scala
index 6dec7b0f9..f638b0670 100644
--- a/tests/neg/i705-inner-value-class.scala
+++ b/tests/neg/i705-inner-value-class.scala
@@ -2,6 +2,13 @@ class Foo {
class B(val a: Int) extends AnyVal // error
}
+class VCwithBadMembers(val a: Int) extends AnyVal {
+ def this() = this(1) // error
+ var x = 0 // error
+ val y = 2 // error
+ println("hi") // error
+}
+
object Test {
class B(val a: Int) extends AnyVal // ok
def f = {
diff --git a/tests/pos/extmethods.scala b/tests/pos/extmethods.scala
index 3edfa2d75..cac1c4ec1 100644
--- a/tests/pos/extmethods.scala
+++ b/tests/pos/extmethods.scala
@@ -1,7 +1,6 @@
trait That1[A]
class T[A, This <: That1[A]](val x: Int) extends AnyVal {
self: This =>
- var next: This = _
final def loop(x: This, cnt: Int): Int = loop(x, cnt + 1)
def const[B](): Boolean = return true
}