summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/compiler/scala/tools/nsc/ast/TreeInfo.scala7
-rw-r--r--src/compiler/scala/tools/nsc/transform/Constructors.scala3
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Typers.scala87
-rw-r--r--src/reflect/scala/reflect/runtime/SynchronizedTypes.scala3
-rw-r--r--test/files/neg/anytrait.check4
-rw-r--r--test/files/neg/t5799.check2
-rw-r--r--test/files/neg/t5882.check18
-rw-r--r--test/files/neg/t5882.scala5
-rw-r--r--test/files/neg/t6359.check6
-rw-r--r--test/files/neg/t6436.check10
-rw-r--r--test/files/neg/t6436.scala9
-rw-r--r--test/files/neg/t6436b.check10
-rw-r--r--test/files/neg/t6436b.scala9
-rw-r--r--test/files/neg/unchecked-abstract.check32
-rw-r--r--test/files/neg/unchecked-abstract.scala96
-rw-r--r--test/files/neg/valueclasses-impl-restrictions.check21
-rw-r--r--test/files/neg/valueclasses-impl-restrictions.scala28
-rw-r--r--test/files/neg/valueclasses.check4
-rw-r--r--test/pending/run/t5882.scala14
-rw-r--r--test/pending/run/t6408.scala11
20 files changed, 266 insertions, 113 deletions
diff --git a/src/compiler/scala/tools/nsc/ast/TreeInfo.scala b/src/compiler/scala/tools/nsc/ast/TreeInfo.scala
index 9e46155d14..3e1d606877 100644
--- a/src/compiler/scala/tools/nsc/ast/TreeInfo.scala
+++ b/src/compiler/scala/tools/nsc/ast/TreeInfo.scala
@@ -45,11 +45,4 @@ abstract class TreeInfo extends scala.reflect.internal.TreeInfo {
def isInterface(mods: HasFlags, body: List[Tree]) =
mods.isTrait && (body forall isInterfaceMember)
-
- def isAllowedInUniversalTrait(stat: Tree): Boolean = stat match {
- case _: ValDef => false
- case Import(_, _) | EmptyTree => true
- case _: DefTree => true
- case _ => false
- }
}
diff --git a/src/compiler/scala/tools/nsc/transform/Constructors.scala b/src/compiler/scala/tools/nsc/transform/Constructors.scala
index 23b15a9033..4b9585bb93 100644
--- a/src/compiler/scala/tools/nsc/transform/Constructors.scala
+++ b/src/compiler/scala/tools/nsc/transform/Constructors.scala
@@ -127,7 +127,8 @@ abstract class Constructors extends Transform with ast.TreeDSL {
import CODE._
val result = mkAssign(to, Ident(from))
- if (from.name != nme.OUTER) result
+ if (from.name != nme.OUTER ||
+ from.tpe.typeSymbol.isPrimitiveValueClass) result
else localTyper.typedPos(to.pos) {
IF (from OBJ_EQ NULL) THEN Throw(NullPointerExceptionClass.tpe) ELSE result
}
diff --git a/src/compiler/scala/tools/nsc/typechecker/Typers.scala b/src/compiler/scala/tools/nsc/typechecker/Typers.scala
index c25b6c3726..5a9920c9e3 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Typers.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Typers.scala
@@ -1388,6 +1388,70 @@ 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
+ 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)
+ }
+ }
+ 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. 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 =>
+ //see https://issues.scala-lang.org/browse/SI-6359
+ implRestriction(stat, "nested object")
+ case _ =>
+ notAllowed("this statement")
+ }
+ }
+ }
+
private def validateDerivedValueClass(clazz: Symbol, body: List[Tree]) = {
if (clazz.isTrait)
unit.error(clazz.pos, "only classes (not traits) are allowed to extend AnyVal")
@@ -1395,7 +1459,7 @@ trait Typers extends Modes with Adaptations with Tags {
unit.error(clazz.pos, "value class may not be a "+
(if (clazz.owner.isTerm) "local class" else "member of another class"))
if (!clazz.isPrimitiveValueClass) {
- clazz.info.decls.toList.filter(acc => acc.isMethod && (acc hasFlag PARAMACCESSOR)) match {
+ clazz.info.decls.toList.filter(acc => acc.isMethod && acc.isParamAccessor) match {
case List(acc) =>
def isUnderlyingAcc(sym: Symbol) =
sym == acc || acc.hasAccessorFlag && sym == acc.accessed
@@ -1403,25 +1467,12 @@ trait Typers extends Modes with Adaptations with Tags {
unit.error(acc.pos, "value class needs to have a publicly accessible val parameter")
else if (acc.tpe.typeSymbol.isDerivedValueClass)
unit.error(acc.pos, "value class may not wrap another user-defined value class")
- for (stat <- body)
- if (!treeInfo.isAllowedInUniversalTrait(stat) && !isUnderlyingAcc(stat.symbol))
- unit.error(stat.pos,
- if (stat.symbol != null && (stat.symbol hasFlag PARAMACCESSOR)) "illegal parameter for value class"
- else "this statement is not allowed in value class: " + stat)
+ checkEphemeral(clazz, body filterNot (stat => isUnderlyingAcc(stat.symbol)))
case x =>
unit.error(clazz.pos, "value class needs to have exactly one public val parameter")
}
}
- def valueClassMayNotHave(at: Tree, what: String) = unit.error(at.pos, s"value class may not have $what")
- body.foreach {
- case dd: DefDef if dd.symbol.isAuxiliaryConstructor => valueClassMayNotHave(dd, "secondary constructors")
- case t => t.foreach {
- case md: ModuleDef => valueClassMayNotHave(md, "nested module definitions")
- case cd: ClassDef => valueClassMayNotHave(cd, "nested class definitions")
- case _ =>
- }
- }
for (tparam <- clazz.typeParams)
if (tparam hasAnnotation definitions.SpecializedClass)
unit.error(tparam.pos, "type parameter of value class may not be specialized")
@@ -1668,9 +1719,7 @@ trait Typers extends Modes with Adaptations with Tags {
}
val impl2 = finishMethodSynthesis(impl1, clazz, context)
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 universal trait extending from class Any: "+stat)
+ checkEphemeral(clazz, impl2.body)
if ((clazz != ClassfileAnnotationClass) &&
(clazz isNonBottomSubClass ClassfileAnnotationClass))
restrictionWarning(cdef.pos, unit,
@@ -4578,7 +4627,7 @@ trait Typers extends Modes with Adaptations with Tags {
// xml member to StringContext, which in turn has an unapply[Seq] method)
if (name != nme.CONSTRUCTOR && inExprModeOr(mode, PATTERNmode)) {
val qual1 = adaptToMemberWithArgs(tree, qual, name, mode, true, true)
- if (qual1 ne qual)
+ if ((qual1 ne qual) && !qual1.isErrorTyped)
return typed(treeCopy.Select(tree, qual1, name), mode, pt)
}
NoSymbol
diff --git a/src/reflect/scala/reflect/runtime/SynchronizedTypes.scala b/src/reflect/scala/reflect/runtime/SynchronizedTypes.scala
index b9b140a2fd..9b4d8d1d48 100644
--- a/src/reflect/scala/reflect/runtime/SynchronizedTypes.scala
+++ b/src/reflect/scala/reflect/runtime/SynchronizedTypes.scala
@@ -24,7 +24,8 @@ trait SynchronizedTypes extends internal.Types { self: SymbolTable =>
// i.e. they have their caches cleaned up automatically on per-run basis,
// therefore they should use vanilla uniques, which are faster
if (!isCompilerUniverse) {
- val result = if (uniques contains tp) uniques(tp).get else null
+ val inCache = uniques get tp
+ val result = if (inCache.isDefined) inCache.get.get else null
if (result ne null) result.asInstanceOf[T]
else {
uniques(tp) = new WeakReference(tp)
diff --git a/test/files/neg/anytrait.check b/test/files/neg/anytrait.check
index 9dd970b58c..fabe74d379 100644
--- a/test/files/neg/anytrait.check
+++ b/test/files/neg/anytrait.check
@@ -1,7 +1,7 @@
-anytrait.scala:3: error: this statement is not allowed in universal trait extending from class Any: private[this] var x: Int = 1
+anytrait.scala:3: error: field definition is not allowed in universal trait extending from class Any
var x = 1
^
-anytrait.scala:5: error: this statement is not allowed in universal trait extending from class Any: T.this.x_=(T.this.x.+(1))
+anytrait.scala:5: error: this statement is not allowed in universal trait extending from class Any
{ x += 1 }
^
two errors found
diff --git a/test/files/neg/t5799.check b/test/files/neg/t5799.check
index 10e2658d56..3b43d06a94 100644
--- a/test/files/neg/t5799.check
+++ b/test/files/neg/t5799.check
@@ -1,4 +1,4 @@
-t5799.scala:2: error: value class may not have secondary constructors
+t5799.scala:2: error: secondary constructor is not allowed in value class
def this(s: String) = this(s.toDouble)
^
one error found
diff --git a/test/files/neg/t5882.check b/test/files/neg/t5882.check
index df01c7bc0a..e0958e19d9 100644
--- a/test/files/neg/t5882.check
+++ b/test/files/neg/t5882.check
@@ -1,15 +1,9 @@
-t5882.scala:2: warning: case classes without a parameter list have been deprecated;
-use either case objects or case classes with `()' as parameter list.
- case class Scope
- ^
-t5882.scala:2: error: value class may not have nested class definitions
- case class Scope
+t5882.scala:4: error: implementation restriction: nested class is not allowed in value class
+This restriction is planned to be removed in subsequent releases.
+ case class Scope()
^
-t5882.scala:3: error: value class may not have nested class definitions
- class Foo
- ^
-t5882.scala:4: error: value class may not have nested module definitions
+t5882.scala:5: error: implementation restriction: nested object is not allowed in value class
+This restriction is planned to be removed in subsequent releases.
object Bar
^
-one warning found
-three errors found
+two errors found
diff --git a/test/files/neg/t5882.scala b/test/files/neg/t5882.scala
index 1233eb636f..3a55abdc9a 100644
--- a/test/files/neg/t5882.scala
+++ b/test/files/neg/t5882.scala
@@ -1,5 +1,6 @@
+// SIP-15 was changed to allow nested classes. See run/t5882.scala
+
class NodeOps(val n: Any) extends AnyVal {
- case class Scope
- class Foo
+ case class Scope()
object Bar
}
diff --git a/test/files/neg/t6359.check b/test/files/neg/t6359.check
index 2aa1ac5035..5bcdc57331 100644
--- a/test/files/neg/t6359.check
+++ b/test/files/neg/t6359.check
@@ -1,7 +1,9 @@
-t6359.scala:3: error: value class may not have nested module definitions
+t6359.scala:3: error: implementation restriction: nested object is not allowed in value class
+This restriction is planned to be removed in subsequent releases.
object X
^
-t6359.scala:4: error: value class may not have nested class definitions
+t6359.scala:4: error: implementation restriction: nested class is not allowed in value class
+This restriction is planned to be removed in subsequent releases.
class Y
^
two errors found
diff --git a/test/files/neg/t6436.check b/test/files/neg/t6436.check
new file mode 100644
index 0000000000..ecb28f9100
--- /dev/null
+++ b/test/files/neg/t6436.check
@@ -0,0 +1,10 @@
+t6436.scala:8: error: type mismatch;
+ found : StringContext
+ required: ?{def q: ?}
+Note that implicit conversions are not applicable because they are ambiguous:
+ both method foo1 in object quasiquotes of type (ctx: StringContext)Object{def q: Nothing}
+ and method foo2 in object quasiquotes of type (ctx: StringContext)Object{def q: Nothing}
+ are possible conversion functions from StringContext to ?{def q: ?}
+ println(q"a")
+ ^
+one error found
diff --git a/test/files/neg/t6436.scala b/test/files/neg/t6436.scala
new file mode 100644
index 0000000000..2c40502538
--- /dev/null
+++ b/test/files/neg/t6436.scala
@@ -0,0 +1,9 @@
+object quasiquotes {
+ implicit def foo1(ctx: StringContext) = new { def q = ??? }
+ implicit def foo2(ctx: StringContext) = new { def q = ??? }
+}
+
+object Test extends App {
+ import quasiquotes._
+ println(q"a")
+}
diff --git a/test/files/neg/t6436b.check b/test/files/neg/t6436b.check
new file mode 100644
index 0000000000..b3c2d73739
--- /dev/null
+++ b/test/files/neg/t6436b.check
@@ -0,0 +1,10 @@
+t6436b.scala:8: error: type mismatch;
+ found : StringContext
+ required: ?{def q: ?}
+Note that implicit conversions are not applicable because they are ambiguous:
+ both method foo1 in object quasiquotes of type (ctx: StringContext)Object{def q: Nothing}
+ and method foo2 in object quasiquotes of type (ctx: StringContext)Object{def q: Nothing}
+ are possible conversion functions from StringContext to ?{def q: ?}
+ println(StringContext("a").q())
+ ^
+one error found
diff --git a/test/files/neg/t6436b.scala b/test/files/neg/t6436b.scala
new file mode 100644
index 0000000000..8023329e90
--- /dev/null
+++ b/test/files/neg/t6436b.scala
@@ -0,0 +1,9 @@
+object quasiquotes {
+ implicit def foo1(ctx: StringContext) = new { def q = ??? }
+ implicit def foo2(ctx: StringContext) = new { def q = ??? }
+}
+
+object Test extends App {
+ import quasiquotes._
+ println(StringContext("a").q())
+}
diff --git a/test/files/neg/unchecked-abstract.check b/test/files/neg/unchecked-abstract.check
index dc7a8d93d0..6e811dc156 100644
--- a/test/files/neg/unchecked-abstract.check
+++ b/test/files/neg/unchecked-abstract.check
@@ -1,25 +1,25 @@
-unchecked-abstract.scala:16: error: abstract type H in type Con[M.this.H] is unchecked since it is eliminated by erasure
- /* warn */ println(x.isInstanceOf[Con[H]])
+unchecked-abstract.scala:16: error: abstract type H in type Contravariant[M.this.H] is unchecked since it is eliminated by erasure
+ /* warn */ println(x.isInstanceOf[Contravariant[H]])
^
-unchecked-abstract.scala:21: error: abstract type H in type Con[M.this.H] is unchecked since it is eliminated by erasure
- /* warn */ println(x.isInstanceOf[Con[H]])
+unchecked-abstract.scala:21: error: abstract type H in type Contravariant[M.this.H] is unchecked since it is eliminated by erasure
+ /* warn */ println(x.isInstanceOf[Contravariant[H]])
^
-unchecked-abstract.scala:27: error: abstract type T in type Inv[M.this.T] is unchecked since it is eliminated by erasure
- /* warn */ println(x.isInstanceOf[Inv[T]])
+unchecked-abstract.scala:27: error: abstract type T in type Invariant[M.this.T] is unchecked since it is eliminated by erasure
+ /* warn */ println(x.isInstanceOf[Invariant[T]])
^
-unchecked-abstract.scala:28: error: abstract type L in type Inv[M.this.L] is unchecked since it is eliminated by erasure
- /* warn */ println(x.isInstanceOf[Inv[L]])
+unchecked-abstract.scala:28: error: abstract type L in type Invariant[M.this.L] is unchecked since it is eliminated by erasure
+ /* warn */ println(x.isInstanceOf[Invariant[L]])
^
-unchecked-abstract.scala:31: error: abstract type H in type Inv[M.this.H] is unchecked since it is eliminated by erasure
- /* warn */ println(x.isInstanceOf[Inv[H]])
+unchecked-abstract.scala:31: error: abstract type H in type Invariant[M.this.H] is unchecked since it is eliminated by erasure
+ /* warn */ println(x.isInstanceOf[Invariant[H]])
^
-unchecked-abstract.scala:33: error: abstract type L in type Inv[M.this.L] is unchecked since it is eliminated by erasure
- /* warn */ println(x.isInstanceOf[Inv[L]])
+unchecked-abstract.scala:33: error: abstract type L in type Invariant[M.this.L] is unchecked since it is eliminated by erasure
+ /* warn */ println(x.isInstanceOf[Invariant[L]])
^
-unchecked-abstract.scala:36: error: abstract type H in type Inv[M.this.H] is unchecked since it is eliminated by erasure
- /* warn */ println(x.isInstanceOf[Inv[H]])
+unchecked-abstract.scala:36: error: abstract type H in type Invariant[M.this.H] is unchecked since it is eliminated by erasure
+ /* warn */ println(x.isInstanceOf[Invariant[H]])
^
-unchecked-abstract.scala:37: error: abstract type T in type Inv[M.this.T] is unchecked since it is eliminated by erasure
- /* warn */ println(x.isInstanceOf[Inv[T]])
+unchecked-abstract.scala:37: error: abstract type T in type Invariant[M.this.T] is unchecked since it is eliminated by erasure
+ /* warn */ println(x.isInstanceOf[Invariant[T]])
^
8 errors found
diff --git a/test/files/neg/unchecked-abstract.scala b/test/files/neg/unchecked-abstract.scala
index 5b915755f4..23c8281ca8 100644
--- a/test/files/neg/unchecked-abstract.scala
+++ b/test/files/neg/unchecked-abstract.scala
@@ -1,56 +1,56 @@
-trait Con[-X]
-trait Inv[X]
-trait Cov[+X]
+trait Contravariant[-X]
+trait Invariant[X]
+trait Covariant[+X]
abstract class M {
type H
type L <: H
type T >: L <: H
- def h1(x: Con[H]) = {
- /* nowarn */ println(x.isInstanceOf[Con[H]])
- /* nowarn */ println(x.isInstanceOf[Con[T]])
- /* nowarn */ println(x.isInstanceOf[Con[L]])
+ def h1(x: Contravariant[H]) = {
+ /* nowarn */ println(x.isInstanceOf[Contravariant[H]])
+ /* nowarn */ println(x.isInstanceOf[Contravariant[T]])
+ /* nowarn */ println(x.isInstanceOf[Contravariant[L]])
}
- def h2(x: Con[T]) = {
- /* warn */ println(x.isInstanceOf[Con[H]])
- /* nowarn */ println(x.isInstanceOf[Con[T]])
- /* nowarn */ println(x.isInstanceOf[Con[L]])
+ def h2(x: Contravariant[T]) = {
+ /* warn */ println(x.isInstanceOf[Contravariant[H]])
+ /* nowarn */ println(x.isInstanceOf[Contravariant[T]])
+ /* nowarn */ println(x.isInstanceOf[Contravariant[L]])
}
- def h3(x: Con[L]) = {
- /* warn */ println(x.isInstanceOf[Con[H]])
- /* warn */ println(x.isInstanceOf[Con[T]])
- /* nowarn */ println(x.isInstanceOf[Con[L]])
+ def h3(x: Contravariant[L]) = {
+ /* warn */ println(x.isInstanceOf[Contravariant[H]])
+ /* warn */ println(x.isInstanceOf[Contravariant[T]])
+ /* nowarn */ println(x.isInstanceOf[Contravariant[L]])
}
- def h4(x: Inv[H]) = {
- /* nowarn */ println(x.isInstanceOf[Inv[H]])
- /* warn */ println(x.isInstanceOf[Inv[T]])
- /* warn */ println(x.isInstanceOf[Inv[L]])
+ def h4(x: Invariant[H]) = {
+ /* nowarn */ println(x.isInstanceOf[Invariant[H]])
+ /* warn */ println(x.isInstanceOf[Invariant[T]])
+ /* warn */ println(x.isInstanceOf[Invariant[L]])
}
- def h5(x: Inv[T]) = {
- /* warn */ println(x.isInstanceOf[Inv[H]])
- /* nowarn */ println(x.isInstanceOf[Inv[T]])
- /* warn */ println(x.isInstanceOf[Inv[L]])
+ def h5(x: Invariant[T]) = {
+ /* warn */ println(x.isInstanceOf[Invariant[H]])
+ /* nowarn */ println(x.isInstanceOf[Invariant[T]])
+ /* warn */ println(x.isInstanceOf[Invariant[L]])
}
- def h6(x: Inv[L]) = {
- /* warn */ println(x.isInstanceOf[Inv[H]])
- /* warn */ println(x.isInstanceOf[Inv[T]])
- /* nowarn */ println(x.isInstanceOf[Inv[L]])
+ def h6(x: Invariant[L]) = {
+ /* warn */ println(x.isInstanceOf[Invariant[H]])
+ /* warn */ println(x.isInstanceOf[Invariant[T]])
+ /* nowarn */ println(x.isInstanceOf[Invariant[L]])
}
- def h7(x: Cov[H]) = {
- /* nowarn */ println(x.isInstanceOf[Cov[H]])
- /* warn */ println(x.isInstanceOf[Cov[T]])
- /* warn */ println(x.isInstanceOf[Cov[L]])
+ def h7(x: Covariant[H]) = {
+ /* nowarn */ println(x.isInstanceOf[Covariant[H]])
+ /* warn */ println(x.isInstanceOf[Covariant[T]])
+ /* warn */ println(x.isInstanceOf[Covariant[L]])
}
- def h8(x: Cov[T]) = {
- /* nowarn */ println(x.isInstanceOf[Cov[H]])
- /* nowarn */ println(x.isInstanceOf[Cov[T]])
- /* warn */ println(x.isInstanceOf[Cov[L]])
+ def h8(x: Covariant[T]) = {
+ /* nowarn */ println(x.isInstanceOf[Covariant[H]])
+ /* nowarn */ println(x.isInstanceOf[Covariant[T]])
+ /* warn */ println(x.isInstanceOf[Covariant[L]])
}
- def h9(x: Cov[L]) = {
- /* nowarn */ println(x.isInstanceOf[Cov[H]])
- /* nowarn */ println(x.isInstanceOf[Cov[T]])
- /* nowarn */ println(x.isInstanceOf[Cov[L]])
+ def h9(x: Covariant[L]) = {
+ /* nowarn */ println(x.isInstanceOf[Covariant[H]])
+ /* nowarn */ println(x.isInstanceOf[Covariant[T]])
+ /* nowarn */ println(x.isInstanceOf[Covariant[L]])
}
}
@@ -59,17 +59,17 @@ object Test extends M {
type T = Int
type L = Nothing
- val conh = new Con[H] { }
- val cont = new Con[T] { }
- val conl = new Con[L] { }
+ val conh = new Contravariant[H] { }
+ val cont = new Contravariant[T] { }
+ val conl = new Contravariant[L] { }
- val invh = new Inv[H] { }
- val invt = new Inv[T] { }
- val invl = new Inv[L] { }
+ val invh = new Invariant[H] { }
+ val invt = new Invariant[T] { }
+ val invl = new Invariant[L] { }
- val covh = new Cov[H] { }
- val covt = new Cov[T] { }
- val covl = new Cov[L] { }
+ val covh = new Covariant[H] { }
+ val covt = new Covariant[T] { }
+ val covl = new Covariant[L] { }
def main(args: Array[String]): Unit = {
h1(conh)
diff --git a/test/files/neg/valueclasses-impl-restrictions.check b/test/files/neg/valueclasses-impl-restrictions.check
new file mode 100644
index 0000000000..17d07ba960
--- /dev/null
+++ b/test/files/neg/valueclasses-impl-restrictions.check
@@ -0,0 +1,21 @@
+valueclasses-impl-restrictions.scala:3: error: implementation restriction: nested object is not allowed in value class
+This restriction is planned to be removed in subsequent releases.
+ object X
+ ^
+valueclasses-impl-restrictions.scala:4: error: implementation restriction: lazy val is not allowed in value class
+This restriction is planned to be removed in subsequent releases.
+ lazy val y = 1
+ ^
+valueclasses-impl-restrictions.scala:10: error: implementation restriction: nested trait is not allowed in value class
+This restriction is planned to be removed in subsequent releases.
+ trait I2 {
+ ^
+valueclasses-impl-restrictions.scala:16: error: implementation restriction: nested class is not allowed in value class
+This restriction is planned to be removed in subsequent releases.
+ val i2 = new I2 { val q = x.s }
+ ^
+valueclasses-impl-restrictions.scala:22: error: implementation restriction: nested class is not allowed in value class
+This restriction is planned to be removed in subsequent releases.
+ private[this] class I2(val q: String)
+ ^
+5 errors found
diff --git a/test/files/neg/valueclasses-impl-restrictions.scala b/test/files/neg/valueclasses-impl-restrictions.scala
new file mode 100644
index 0000000000..53396db958
--- /dev/null
+++ b/test/files/neg/valueclasses-impl-restrictions.scala
@@ -0,0 +1,28 @@
+class M(val t: Int) extends AnyVal {
+ def lazyString = {
+ object X
+ lazy val y = 1
+ () => X
+ }
+}
+
+class X1(val s: String) extends AnyVal {
+ trait I2 {
+ val q: String
+ def z = s + q
+ }
+
+ def y(x: X1) = {
+ val i2 = new I2 { val q = x.s }
+ i2.z
+ }
+}
+
+class X2(val s: String) extends AnyVal {
+ private[this] class I2(val q: String)
+
+ def y(i: Int) = {
+ val i2 = new I2(i.toString)
+ i2.q + s
+ }
+}
diff --git a/test/files/neg/valueclasses.check b/test/files/neg/valueclasses.check
index 4f042faded..3b82a8358c 100644
--- a/test/files/neg/valueclasses.check
+++ b/test/files/neg/valueclasses.check
@@ -25,13 +25,13 @@ 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
+valueclasses.scala:20: error: field definition is not allowed in 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
+valueclasses.scala:24: error: field definition is not allowed in value class
val y = x // fail
^
valueclasses.scala:29: error: type parameter of value class may not be specialized
diff --git a/test/pending/run/t5882.scala b/test/pending/run/t5882.scala
new file mode 100644
index 0000000000..47996d3068
--- /dev/null
+++ b/test/pending/run/t5882.scala
@@ -0,0 +1,14 @@
+// SIP-15 was revised to allow nested classes in value classes.
+// This test checks that their basic functionality.
+
+class NodeOps(val n: Any) extends AnyVal { self =>
+ class Foo() { def show = self.show(n) }
+ def show(x: Any) = x.toString
+}
+
+
+object Test extends App {
+
+ val n = new NodeOps("abc")
+ assert(new n.Foo().show == "abc")
+}
diff --git a/test/pending/run/t6408.scala b/test/pending/run/t6408.scala
new file mode 100644
index 0000000000..ff17480b35
--- /dev/null
+++ b/test/pending/run/t6408.scala
@@ -0,0 +1,11 @@
+class X(val i: Int) extends AnyVal {
+ class Inner(val q: Int) {
+ def plus = i + q
+ }
+}
+
+object Test extends App {
+ val x = new X(11)
+ val i = new x.Inner(22)
+ assert(i.plus == 33)
+}