diff options
-rw-r--r-- | src/dotty/tools/dotc/typer/RefChecks.scala | 16 | ||||
-rw-r--r-- | test/dotc/tests.scala | 2 | ||||
-rw-r--r-- | tests/neg/i705-inner-value-class.scala | 7 | ||||
-rw-r--r-- | tests/pos/extmethods.scala | 1 |
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 } |