summaryrefslogtreecommitdiff
path: root/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala
diff options
context:
space:
mode:
authorPaul Phillips <paulp@improving.org>2012-01-30 12:42:26 -0800
committerPaul Phillips <paulp@improving.org>2012-01-30 22:18:25 -0800
commita9eb9c5b69071a944d2a5225aa320babdf33ad42 (patch)
tree52c6353685c24c2101f8a963a66068a703405584 /src/compiler/scala/tools/nsc/typechecker/RefChecks.scala
parent74a252e668959dd2cf4808132473d8b15bb606af (diff)
downloadscala-a9eb9c5b69071a944d2a5225aa320babdf33ad42.tar.gz
scala-a9eb9c5b69071a944d2a5225aa320babdf33ad42.tar.bz2
scala-a9eb9c5b69071a944d2a5225aa320babdf33ad42.zip
More work on inline classes.
Fail compile if AnyVal is inherited by a trait, a non-@inline class, or a class with an AnyRef parent somewhere. Added tests. Added logging, like [log extmethods] Inline class class Bippy spawns extension method. Old: def getClass: Class[_ <: Bippy] New: final def extension$getClass($this: Bippy): Class[_ <: Bippy] Fixed what I hope was a bug in ExtensionMethods where the original method params were dropped. Since adding a NonNull parent was also inflicting an AnyRef on AnyVal subclasses, suppressed that for those. Had the bright idea that AnyVal could extend NotNull. It doesn't seem to accomplish much, but then, I don't think NotNull accomplishes much. Still, maybe it's time to restrict the ways one can use AnyVal so one can't do this: scala> var x: AnyVal = _ x: AnyVal = null
Diffstat (limited to 'src/compiler/scala/tools/nsc/typechecker/RefChecks.scala')
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/RefChecks.scala23
1 files changed, 19 insertions, 4 deletions
diff --git a/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala b/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala
index 4449116fd1..f7a6815905 100644
--- a/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala
@@ -683,16 +683,16 @@ abstract class RefChecks extends InfoTransform with reflect.internal.transform.R
if (abstractErrors.nonEmpty)
unit.error(clazz.pos, abstractErrorMessage)
- } else if (clazz.isTrait) {
- // prevent abstract methods in interfaces that override final members in Object; see #4431
- if (!(clazz isSubClass AnyValClass)) {
+ }
+ else if (clazz.isTrait && !(clazz isSubClass AnyValClass)) {
+ // For non-AnyVal classes, prevent abstract methods in interfaces that override
+ // final members in Object; see #4431
for (decl <- clazz.info.decls.iterator) {
val overridden = decl.overriddenSymbol(ObjectClass)
if (overridden.isFinal)
unit.error(decl.pos, "trait cannot redefine final method from class AnyRef")
}
}
- }
/** Returns whether there is a symbol declared in class `inclazz`
* (which must be different from `clazz`) whose name and type
@@ -1527,6 +1527,19 @@ abstract class RefChecks extends InfoTransform with reflect.internal.transform.R
)
case _ => ()
}
+
+ // verify classes extending AnyVal meet the requirements
+ // (whatever those are to be, but at least: @inline annotation)
+ private def checkAnyValSubclass(clazz: Symbol) = {
+ if ((clazz isSubClass AnyValClass) && (clazz ne AnyValClass) && !isPrimitiveValueClass(clazz)) {
+ if (!clazz.hasAnnotation(ScalaInlineClass))
+ unit.error(clazz.pos, "Only @inline classes are allowed to extend AnyVal")
+ if (clazz.isTrait)
+ unit.error(clazz.pos, "Only @inline classes (not traits) are allowed to extend AnyVal")
+ if (clazz.tpe <:< AnyRefClass.tpe)
+ unit.error(clazz.pos, "Classes which extend AnyVal may not have an ancestor which inherits AnyRef")
+ }
+ }
override def transform(tree: Tree): Tree = {
val savedLocalTyper = localTyper
@@ -1562,6 +1575,8 @@ abstract class RefChecks extends InfoTransform with reflect.internal.transform.R
checkOverloadedRestrictions(currentOwner)
val bridges = addVarargBridges(currentOwner)
checkAllOverrides(currentOwner)
+ checkAnyValSubclass(currentOwner)
+
if (bridges.nonEmpty) treeCopy.Template(tree, parents, self, body ::: bridges)
else tree