summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/compiler/scala/reflect/internal/Symbols.scala2
-rw-r--r--src/compiler/scala/tools/nsc/Global.scala15
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/SuperAccessors.scala3
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Typers.scala18
-rw-r--r--test/files/neg/valueclasses.check46
-rw-r--r--test/files/neg/valueclasses.scala36
-rw-r--r--test/files/run/GenericValueClass.scala12
-rw-r--r--test/files/run/Meter.check13
-rw-r--r--test/files/run/Meter.scala55
-rw-r--r--test/files/run/programmatic-main.check4
10 files changed, 156 insertions, 48 deletions
diff --git a/src/compiler/scala/reflect/internal/Symbols.scala b/src/compiler/scala/reflect/internal/Symbols.scala
index 89af10283b..d3641c1ee8 100644
--- a/src/compiler/scala/reflect/internal/Symbols.scala
+++ b/src/compiler/scala/reflect/internal/Symbols.scala
@@ -504,7 +504,7 @@ trait Symbols extends api.Symbols { self: SymbolTable =>
!isPrimitiveValueClass
final def isMethodWithExtension =
- isMethod && owner.isInlineClass && !isParamAccessor && !isConstructor
+ isMethod && owner.isInlineClass && !isParamAccessor && !isConstructor && !hasFlag(SUPERACCESSOR)
final def isAnonymousClass = isClass && (name containsName tpnme.ANON_CLASS_NAME)
final def isAnonymousFunction = isSynthetic && (name containsName tpnme.ANON_FUN_NAME)
diff --git a/src/compiler/scala/tools/nsc/Global.scala b/src/compiler/scala/tools/nsc/Global.scala
index 3f6a0f8f73..a3529020d4 100644
--- a/src/compiler/scala/tools/nsc/Global.scala
+++ b/src/compiler/scala/tools/nsc/Global.scala
@@ -438,12 +438,6 @@ class Global(var currentSettings: Settings, var reporter: Reporter) extends Symb
val global: Global.this.type = Global.this
} with Analyzer
- object extensionMethods extends {
- val global: Global.this.type = Global.this
- val runsAfter = List("typer")
- val runsRightAfter = None
- } with ExtensionMethods
-
// phaseName = "superaccessors"
object superAccessors extends {
val global: Global.this.type = Global.this
@@ -451,10 +445,17 @@ class Global(var currentSettings: Settings, var reporter: Reporter) extends Symb
val runsRightAfter = None
} with SuperAccessors
+ // phaseName = "extmethods"
+ object extensionMethods extends {
+ val global: Global.this.type = Global.this
+ val runsAfter = List("superaccessors")
+ val runsRightAfter = None
+ } with ExtensionMethods
+
// phaseName = "pickler"
object pickler extends {
val global: Global.this.type = Global.this
- val runsAfter = List("superaccessors")
+ val runsAfter = List("extmethods")
val runsRightAfter = None
} with Pickler
diff --git a/src/compiler/scala/tools/nsc/typechecker/SuperAccessors.scala b/src/compiler/scala/tools/nsc/typechecker/SuperAccessors.scala
index 0ab09b4fec..d294cc86bc 100644
--- a/src/compiler/scala/tools/nsc/typechecker/SuperAccessors.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/SuperAccessors.scala
@@ -237,6 +237,9 @@ abstract class SuperAccessors extends transform.Transform with transform.TypingT
}
transformSuperSelect(tree)
+ case DefDef(mods, name, tparams, vparamss, tpt, rhs) if tree.symbol.isMethodWithExtension =>
+ treeCopy.DefDef(tree, mods, name, tparams, vparamss, tpt, withInvalidOwner(transform(rhs)))
+
case TypeApply(sel @ Select(qual, name), args) =>
mayNeedProtectedAccessor(sel, args, true)
diff --git a/src/compiler/scala/tools/nsc/typechecker/Typers.scala b/src/compiler/scala/tools/nsc/typechecker/Typers.scala
index 008a2e1764..fde9b6f551 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Typers.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Typers.scala
@@ -1205,13 +1205,19 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser {
sym == acc || acc.hasAccessorFlag && sym == acc.accessed
if (acc.accessBoundary(clazz) != RootClass)
unit.error(acc.pos, "Value class needs to have a publicly accessible val parameter")
- else
- for (stat <- body)
- if (!treeInfo.isAllowedInUniversalTrait(stat) && !isUnderlyingAcc(stat.symbol))
- unit.error(stat.pos, "This statement is not allowed in value class: "+stat)
+ if (acc.tpe.resultType.typeSymbol.isTypeParameter)
+ unit.error(acc.pos, "Type of parameter of value class may not be a type variable")
+ for (stat <- body)
+ if (!treeInfo.isAllowedInUniversalTrait(stat) && !isUnderlyingAcc(stat.symbol))
+ unit.error(stat.pos,
+ if (stat.symbol hasFlag PARAMACCESSOR) "Illegal parameter for value class"
+ else "This statement is not allowed in value class: "+stat)
case x =>
unit.error(clazz.pos, "Value class needs to have exactly one public val parameter")
}
+ for (tparam <- clazz.typeParams)
+ if (tparam hasAnnotation definitions.SpecializedClass)
+ unit.error(tparam.pos, "type parameter of value class may not be specialized")
}
def parentTypes(templ: Template): List[Tree] =
@@ -1437,10 +1443,10 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser {
_.typedTemplate(cdef.impl, parentTypes(cdef.impl))
}
val impl2 = finishMethodSynthesis(impl1, clazz, context)
- if (clazz.isTrait && clazz.info.parents.nonEmpty && clazz.info.firstParent.typeSymbol == AnyClass)
+ if (clazz.isTrait && clazz.info.parents.nonEmpty && clazz.info.firstParent.normalize.typeSymbol == AnyClass)
for (stat <- impl2.body)
if (!treeInfo.isAllowedInUniversalTrait(stat))
- unit.error(stat.pos, "this statement is not allowed in trait extending from class Any: "+stat)
+ unit.error(stat.pos, "this statement is not allowed in universal trait extending from class Any: "+stat)
if ((clazz != ClassfileAnnotationClass) &&
(clazz isNonBottomSubClass ClassfileAnnotationClass))
restrictionWarning(cdef.pos, unit,
diff --git a/test/files/neg/valueclasses.check b/test/files/neg/valueclasses.check
new file mode 100644
index 0000000000..c4430c8e1a
--- /dev/null
+++ b/test/files/neg/valueclasses.check
@@ -0,0 +1,46 @@
+valueclasses.scala:3: error: Only classes (not traits) are allowed to extend AnyVal
+trait T extends AnyVal // fail
+ ^
+valueclasses.scala:6: error: Value class may not be a member of another class
+ class Bar(x: Int) extends AnyVal // fail
+ ^
+valueclasses.scala:8: error: Value class may not be a local class
+ class Baz(x: Int) extends AnyVal // fail
+ ^
+valueclasses.scala:12: error: Value class needs to have exactly one public val parameter
+class V1 extends AnyVal // fail
+ ^
+valueclasses.scala:14: error: Value class needs to have a publicly accessible val parameter
+class V2(private[test] val x: Int) extends AnyVal // fail
+ ^
+valueclasses.scala:15: error: Value class needs to have a publicly accessible val parameter
+class V3(protected[test] val x: Int) extends AnyVal // fail
+ ^
+valueclasses.scala:16: error: Value class needs to have a publicly accessible val parameter
+class V4(protected val x: Int) extends AnyVal // fail
+ ^
+valueclasses.scala:17: error: Value class needs to have a publicly accessible val parameter
+class V5(private val x: Int) extends AnyVal // fail
+ ^
+valueclasses.scala:19: error: Value class needs to have exactly one public val parameter
+class V6(val x: Int, val y: String) extends AnyVal // fail
+ ^
+valueclasses.scala:20: error: Illegal parameter for value class
+class V7(val x: Int, private[this] val y: String) extends AnyVal // fail
+ ^
+valueclasses.scala:21: error: Value class needs to have exactly one public val parameter
+class V8(var x: Int) extends AnyVal // fail
+ ^
+valueclasses.scala:24: error: This statement is not allowed in value class: private[this] val y: Int = V9.this.x
+ val y = x // fail
+ ^
+valueclasses.scala:27: error: Type of parameter of value class may not be a type variable
+class V10[T](val x: T) extends AnyVal // fail
+ ^
+valueclasses.scala:29: error: type parameter of value class may not be specialized
+class V12[@specialized T, U](val x: (T, U)) extends AnyVal // fail
+ ^
+valueclasses.scala:31: error: Value class needs to have exactly one public val parameter
+class V13(x: Int) extends AnyVal // fail
+ ^
+15 errors found
diff --git a/test/files/neg/valueclasses.scala b/test/files/neg/valueclasses.scala
new file mode 100644
index 0000000000..2794a852ee
--- /dev/null
+++ b/test/files/neg/valueclasses.scala
@@ -0,0 +1,36 @@
+package test
+
+trait T extends AnyVal // fail
+
+class Foo {
+ class Bar(x: Int) extends AnyVal // fail
+ def foo() {
+ class Baz(x: Int) extends AnyVal // fail
+ }
+}
+
+class V1 extends AnyVal // fail
+
+class V2(private[test] val x: Int) extends AnyVal // fail
+class V3(protected[test] val x: Int) extends AnyVal // fail
+class V4(protected val x: Int) extends AnyVal // fail
+class V5(private val x: Int) extends AnyVal // fail
+
+class V6(val x: Int, val y: String) extends AnyVal // fail
+class V7(val x: Int, private[this] val y: String) extends AnyVal // fail
+class V8(var x: Int) extends AnyVal // fail
+
+class V9(val x: Int) extends AnyVal {
+ val y = x // fail
+}
+
+class V10[T](val x: T) extends AnyVal // fail
+class V11[T](val x: List[T]) extends AnyVal // ok
+class V12[@specialized T, U](val x: (T, U)) extends AnyVal // fail
+
+class V13(x: Int) extends AnyVal // fail
+
+
+
+
+
diff --git a/test/files/run/GenericValueClass.scala b/test/files/run/GenericValueClass.scala
deleted file mode 100644
index 10068d6cae..0000000000
--- a/test/files/run/GenericValueClass.scala
+++ /dev/null
@@ -1,12 +0,0 @@
-class Box[T](val x: T) extends AnyVal {
- def get: T = x
-}
-
-object Test extends App {
- val b = new Box(1)
- println(b.get)
-
- val c = new Box("abc")
- println(c.get)
-
-}
diff --git a/test/files/run/Meter.check b/test/files/run/Meter.check
index d5073b3c31..7562f9a1bf 100644
--- a/test/files/run/Meter.check
+++ b/test/files/run/Meter.check
@@ -9,10 +9,13 @@ a == b: true
testing native arrays
Array(1.0m, 2.0m)
1.0m
-1.0m 1.0m
-2.0m 2.0m
+>>>1.0m<<< 1.0m
+>>>2.0m<<< 2.0m
testing wrapped arrays
-RowFactory(1.0m, 2.0m)
+FlatArray(1.0m, 2.0m)
1.0m
-1.0m 1.0m
-2.0m 2.0m
+>>>1.0m<<< 1.0m
+>>>2.0m<<< 2.0m
+FlatArray(2.0m, 3.0m)
+ArrayBuffer(1.0, 2.0)
+FlatArray(0.3048ft, 0.6096ft)
diff --git a/test/files/run/Meter.scala b/test/files/run/Meter.scala
index 936b8d98b7..42a3aac5f8 100644
--- a/test/files/run/Meter.scala
+++ b/test/files/run/Meter.scala
@@ -1,23 +1,46 @@
-class Meter(val underlying: Double) extends AnyVal with Printable {
- def + (other: Meter): Meter =
- new Meter(this.underlying + other.underlying)
- def / (other: Meter): Double = this.underlying / other.underlying
- def / (factor: Double): Meter = new Meter(this.underlying / factor)
- def < (other: Meter): Boolean = this.underlying < other.underlying
- override def toString: String = underlying.toString+"m"
-}
-object Meter extends (Double => Meter) {
+package a {
+ class Meter(val underlying: Double) extends AnyVal with _root_.b.Printable {
+ def + (other: Meter): Meter =
+ new Meter(this.underlying + other.underlying)
+ def / (other: Meter): Double = this.underlying / other.underlying
+ def / (factor: Double): Meter = new Meter(this.underlying / factor)
+ def < (other: Meter): Boolean = this.underlying < other.underlying
+ def toFoot: Foot = new Foot(this.underlying * 0.3048)
+ override def print = { Console.print(">>>"); super.print; proprint }
+ override def toString: String = underlying.toString+"m"
+ }
- def apply(x: Double): Meter = new Meter(x)
+ object Meter extends (Double => Meter) {
+
+ def apply(x: Double): Meter = new Meter(x)
- implicit val boxings = new BoxingConversions[Meter, Double] {
- def box(x: Double) = new Meter(x)
- def unbox(m: Meter) = m.underlying
+ implicit val boxings = new BoxingConversions[Meter, Double] {
+ def box(x: Double) = new Meter(x)
+ def unbox(m: Meter) = m.underlying
+ }
}
-}
-trait Printable extends Any { def print: Unit = Console.print(this) }
+ class Foot(val unbox: Double) extends AnyVal {
+ def + (other: Foot): Foot =
+ new Foot(this.unbox + other.unbox)
+ override def toString = unbox.toString+"ft"
+ }
+ object Foot {
+ implicit val boxings = new BoxingConversions[Foot, Double] {
+ def box(x: Double) = new Foot(x)
+ def unbox(m: Foot) = m.unbox
+ }
+ }
+}
+package b {
+ trait Printable extends Any {
+ def print: Unit = Console.print(this)
+ protected def proprint = Console.print("<<<")
+ }
+}
+import a._
+import _root_.b._
object Test extends App {
{
@@ -72,6 +95,8 @@ object Test extends App {
println(ys)
val zs = arr map (_ / Meter(1))
println(zs)
+ val fs = arr map (_.toFoot)
+ println(fs)
}
}
diff --git a/test/files/run/programmatic-main.check b/test/files/run/programmatic-main.check
index 9ddd4a6e14..d16e2c5178 100644
--- a/test/files/run/programmatic-main.check
+++ b/test/files/run/programmatic-main.check
@@ -4,8 +4,8 @@
namer 2 resolve names, attach symbols to named trees
packageobjects 3 load package objects
typer 4 the meat and potatoes: type the trees
- extmethods 5 add extension methods for inline classes
- superaccessors 6 add super accessors in traits and nested classes
+ superaccessors 5 add super accessors in traits and nested classes
+ extmethods 6 add extension methods for inline classes
pickler 7 serialize symbol tables
refchecks 8 reference/override checking, translate nested objects
uncurry 9 uncurry, translate function values to anonymous classes