summaryrefslogtreecommitdiff
path: root/src/compiler/scala/tools/nsc/typechecker/Typers.scala
diff options
context:
space:
mode:
authorGrzegorz Kossakowski <grzegorz.kossakowski@gmail.com>2012-10-03 14:43:30 +0200
committerGrzegorz Kossakowski <grzegorz.kossakowski@gmail.com>2012-10-03 14:43:30 +0200
commit5d9cde105e804d14e2c15c3e15c147a56cb67ff1 (patch)
tree7d1ea64620c7e782a302ee7108a21fc6e4388853 /src/compiler/scala/tools/nsc/typechecker/Typers.scala
parentea9e4ec55ebb5dd6aaf22862622add7608e3f7a0 (diff)
downloadscala-5d9cde105e804d14e2c15c3e15c147a56cb67ff1.tar.gz
scala-5d9cde105e804d14e2c15c3e15c147a56cb67ff1.tar.bz2
scala-5d9cde105e804d14e2c15c3e15c147a56cb67ff1.zip
Put more implementation restrictions on value classes.
Nested objects, classes and lazy vals are disallowed at any nesting level in value classes; e.g. lazy vals local to a method defined in a value class. There are still allowed in universal traits. This is a temporary, implementation restriction that is planned to be addressed in future releases of Scala. Error messages has been updated to communicate that intent. Moved tests for SI-5582 and SI-6408 to pending folder. They have to stay there until implementation restrictions are addressed. Closes SI-6408 and SI-6432. Review by @odersky, @harrah and @adriaanm.
Diffstat (limited to 'src/compiler/scala/tools/nsc/typechecker/Typers.scala')
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Typers.scala58
1 files changed, 48 insertions, 10 deletions
diff --git a/src/compiler/scala/tools/nsc/typechecker/Typers.scala b/src/compiler/scala/tools/nsc/typechecker/Typers.scala
index c73263a101..d3e74f75b4 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Typers.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Typers.scala
@@ -1389,25 +1389,63 @@ trait Typers extends Modes with Adaptations with Tags {
}
private def checkEphemeral(clazz: Symbol, body: List[Tree]) = {
+ // NOTE: Code appears to be messy in this method for good reason: it clearly
+ // communicates the fact that it implements rather ad-hoc, arbitrary and
+ // non-regular set of rules that identify features that interact badly with
+ // value classes. This code can be cleaned up a lot once implementation
+ // restrictions are addressed.
val isValueClass = !clazz.isTrait
- for (stat <- body) {
- def notAllowed(what: String) = {
- val where = if (clazz.isTrait) "universal trait extending from class Any" else "value class"
- unit.error(stat.pos, s"$what is not allowed in $where")
+ def where = if (isValueClass) "value class" else "universal trait extending from class Any"
+ def implRestriction(tree: Tree, what: String) =
+ unit.error(tree.pos, s"implementation restriction: $what is not allowed in $where" +
+ "\nThis restriction is planned to be removed in subsequent releases.")
+ /**
+ * Deeply traverses the tree in search of constructs that are not allowed
+ * in value classes (at any nesting level).
+ *
+ * All restrictions this object imposes are probably not fundamental but require
+ * fair amount of work and testing. We are conservative for now when it comes
+ * to allowing language features to interact with value classes.
+ * */
+ object checkEphemeralDeep extends Traverser {
+ override def traverse(tree: Tree): Unit = if (isValueClass) {
+ tree match {
+ case _: ModuleDef =>
+ //see https://issues.scala-lang.org/browse/SI-6359
+ implRestriction(tree, "nested object")
+ //see https://issues.scala-lang.org/browse/SI-6444
+ //see https://issues.scala-lang.org/browse/SI-6463
+ case _: ClassDef =>
+ implRestriction(tree, "nested class")
+ case x: ValDef if x.mods.isLazy =>
+ //see https://issues.scala-lang.org/browse/SI-6358
+ implRestriction(tree, "lazy val")
+ case _ =>
+ }
+ super.traverse(tree)
}
- stat match {
- case _: Import | _: TypeDef | _: ClassDef | EmptyTree => // OK
- case DefDef(_, name, _, _, _, _) =>
+ }
+ for (stat <- body) {
+ def notAllowed(what: String) = unit.error(stat.pos, s"$what is not allowed in $where")
+ stat match {
+ // see https://issues.scala-lang.org/browse/SI-6444
+ // see https://issues.scala-lang.org/browse/SI-6463
+ case ClassDef(mods, _, _, _) if isValueClass =>
+ implRestriction(stat, s"nested ${ if (mods.isTrait) "trait" else "class" }")
+ case _: Import | _: ClassDef | _: TypeDef | EmptyTree => // OK
+ case DefDef(_, name, _, _, _, rhs) =>
if (stat.symbol.isAuxiliaryConstructor)
notAllowed("secondary constructor")
else if (isValueClass && (name == nme.equals_ || name == nme.hashCode_))
- notAllowed(s"redefinition of $name method")
- else if (stat.symbol != null && (stat.symbol hasFlag PARAMACCESSOR))
+ notAllowed(s"redefinition of $name method. See SIP-15, criterion 4.")
+ else if (stat.symbol != null && stat.symbol.isParamAccessor)
notAllowed("additional parameter")
+ checkEphemeralDeep.traverse(rhs)
case _: ValDef =>
notAllowed("field definition")
case _: ModuleDef =>
- notAllowed("nested object")
+ //see https://issues.scala-lang.org/browse/SI-6359
+ implRestriction(stat, "nested object")
case _ =>
notAllowed("this statement")
}