diff options
author | Grzegorz Kossakowski <grzegorz.kossakowski@gmail.com> | 2012-10-04 13:38:11 +0200 |
---|---|---|
committer | Grzegorz Kossakowski <grzegorz.kossakowski@gmail.com> | 2012-10-04 13:38:11 +0200 |
commit | 1393baf83bc284e0e2360f2fdc79cc7e400d2320 (patch) | |
tree | 7b7708ec1fe7ce6374972c1bec47b31476cd6a85 | |
parent | 5b9af1b9ff327e8efa2c8b6e8b9ed8d3cdf2598e (diff) | |
parent | d924ef9bce3fb47b590474d04aa3f8aee570958d (diff) | |
download | scala-1393baf83bc284e0e2360f2fdc79cc7e400d2320.tar.gz scala-1393baf83bc284e0e2360f2fdc79cc7e400d2320.tar.bz2 scala-1393baf83bc284e0e2360f2fdc79cc7e400d2320.zip |
Merge remote-tracking branch 'scala/2.10.0-wip' into 2.10.x
-rw-r--r-- | src/compiler/scala/tools/nsc/ast/TreeInfo.scala | 7 | ||||
-rw-r--r-- | src/compiler/scala/tools/nsc/transform/Constructors.scala | 3 | ||||
-rw-r--r-- | src/compiler/scala/tools/nsc/typechecker/Typers.scala | 87 | ||||
-rw-r--r-- | src/reflect/scala/reflect/runtime/SynchronizedTypes.scala | 3 | ||||
-rw-r--r-- | test/files/neg/anytrait.check | 4 | ||||
-rw-r--r-- | test/files/neg/t5799.check | 2 | ||||
-rw-r--r-- | test/files/neg/t5882.check | 18 | ||||
-rw-r--r-- | test/files/neg/t5882.scala | 5 | ||||
-rw-r--r-- | test/files/neg/t6359.check | 6 | ||||
-rw-r--r-- | test/files/neg/t6436.check | 10 | ||||
-rw-r--r-- | test/files/neg/t6436.scala | 9 | ||||
-rw-r--r-- | test/files/neg/t6436b.check | 10 | ||||
-rw-r--r-- | test/files/neg/t6436b.scala | 9 | ||||
-rw-r--r-- | test/files/neg/unchecked-abstract.check | 32 | ||||
-rw-r--r-- | test/files/neg/unchecked-abstract.scala | 96 | ||||
-rw-r--r-- | test/files/neg/valueclasses-impl-restrictions.check | 21 | ||||
-rw-r--r-- | test/files/neg/valueclasses-impl-restrictions.scala | 28 | ||||
-rw-r--r-- | test/files/neg/valueclasses.check | 4 | ||||
-rw-r--r-- | test/pending/run/t5882.scala | 14 | ||||
-rw-r--r-- | test/pending/run/t6408.scala | 11 |
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) +} |