From 6a6cd3ac2986c6036e64cb38b9e22f9416409f48 Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Mon, 6 Feb 2012 14:31:45 +0100 Subject: Removing AnyVal as a source class. Removing automatic addition of ScalaObject. Undoing wrong fix in ExtensionMethods. --- test/files/buildmanager/t2556_3/t2556_3.check | 4 ++-- test/files/neg/anyval-children.check | 17 +++++++---------- test/files/neg/t2641.check | 6 +----- test/files/neg/t464-neg.check | 4 ++-- test/files/neg/t5060.check | 4 ++-- test/files/neg/t664.check | 4 ++-- test/files/neg/variances.check | 2 +- test/files/presentation/callcc-interpreter.check | 4 ++-- test/files/run/primitive-sigs-2.check | 2 +- test/files/run/repl-parens.check | 2 +- test/files/run/t4172.check | 2 +- test/files/run/t4891.check | 1 - 12 files changed, 22 insertions(+), 30 deletions(-) (limited to 'test/files') diff --git a/test/files/buildmanager/t2556_3/t2556_3.check b/test/files/buildmanager/t2556_3/t2556_3.check index bf26602494..37808d2b31 100644 --- a/test/files/buildmanager/t2556_3/t2556_3.check +++ b/test/files/buildmanager/t2556_3/t2556_3.check @@ -3,8 +3,8 @@ compiling Set(A.scala, B.scala, C.scala) Changes: Map() builder > A.scala compiling Set(A.scala) -Changes: Map(class A -> List(), class B -> List(Changed(Class(B))[List((A,Object), (ScalaObject,ScalaObject))])) -invalidate C.scala because parents have changed [Changed(Class(B))[List((A,Object), (ScalaObject,ScalaObject))]] +Changes: Map(class A -> List(), class B -> List(Changed(Class(B))[List((A,Object))])) +invalidate C.scala because parents have changed [Changed(Class(B))[List((A,Object))]] invalidate B.scala because it references invalid (no longer inherited) definition [ParentChanged(Class(C))] compiling Set(B.scala, C.scala) B.scala:3: error: type mismatch; diff --git a/test/files/neg/anyval-children.check b/test/files/neg/anyval-children.check index cbb5a2b1d1..769f990210 100644 --- a/test/files/neg/anyval-children.check +++ b/test/files/neg/anyval-children.check @@ -1,6 +1,7 @@ -anyval-children.scala:7: error: illegal inheritance; superclass Bippy - is not a subclass of the superclass Object - of the mixin trait ScalaObject +anyval-children.scala:3: error: class AnyVal needs to be a trait to be mixed in +@inline class NotOkDingus2 extends Immutable with AnyVal // fail + ^ +anyval-children.scala:7: error: Bippy does not have a constructor class NotOkBippy1 extends Bippy // fail ^ anyval-children.scala:9: error: illegal inheritance; superclass Bippy @@ -8,9 +9,7 @@ anyval-children.scala:9: error: illegal inheritance; superclass Bippy of the mixin trait Immutable class NotOkBippy2 extends Bippy with Immutable //fail ^ -anyval-children.scala:9: error: illegal inheritance; superclass Bippy - is not a subclass of the superclass Object - of the mixin trait ScalaObject +anyval-children.scala:9: error: Bippy does not have a constructor class NotOkBippy2 extends Bippy with Immutable //fail ^ anyval-children.scala:11: error: illegal inheritance; superclass Bippy @@ -18,9 +17,7 @@ anyval-children.scala:11: error: illegal inheritance; superclass Bippy of the mixin trait Immutable @inline class NotOkBippy3 extends Bippy with Immutable //fail ^ -anyval-children.scala:11: error: illegal inheritance; superclass Bippy - is not a subclass of the superclass Object - of the mixin trait ScalaObject +anyval-children.scala:11: error: Bippy does not have a constructor @inline class NotOkBippy3 extends Bippy with Immutable //fail ^ -5 errors found +6 errors found diff --git a/test/files/neg/t2641.check b/test/files/neg/t2641.check index 9e2f02ac47..909f4f0cf3 100644 --- a/test/files/neg/t2641.check +++ b/test/files/neg/t2641.check @@ -9,11 +9,7 @@ t2641.scala:17: error: illegal inheritance; self-type ManagedSeq does not conform to scala.collection.TraversableView[A,ManagedSeqStrict[A]]'s selftype scala.collection.TraversableView[A,ManagedSeqStrict[A]] with TraversableView[A, ManagedSeqStrict[A]] ^ -t2641.scala:16: error: illegal inheritance; - self-type ManagedSeq does not conform to ScalaObject's selftype ScalaObject - extends ManagedSeqStrict[A] - ^ t2641.scala:27: error: value managedIterator is not a member of ManagedSeq override def managedIterator = self.managedIterator slice (from, until) ^ -5 errors found +four errors found diff --git a/test/files/neg/t464-neg.check b/test/files/neg/t464-neg.check index aea1987b2e..e822e7fb6b 100644 --- a/test/files/neg/t464-neg.check +++ b/test/files/neg/t464-neg.check @@ -1,7 +1,7 @@ t464-neg.scala:7: error: not found: value f1 f1() ^ -t464-neg.scala:8: error: method f1 in class A cannot be accessed in A with ScalaObject +t464-neg.scala:8: error: method f1 in class A cannot be accessed in A super.f1() ^ t464-neg.scala:9: error: value f2 is not a member of B @@ -10,7 +10,7 @@ t464-neg.scala:9: error: value f2 is not a member of B t464-neg.scala:10: error: method f3 in class A cannot be accessed in B f3() ^ -t464-neg.scala:11: error: method f3 in class A cannot be accessed in A with ScalaObject +t464-neg.scala:11: error: method f3 in class A cannot be accessed in A super.f3() ^ 5 errors found diff --git a/test/files/neg/t5060.check b/test/files/neg/t5060.check index ab860c9d5b..e71f30ccdb 100644 --- a/test/files/neg/t5060.check +++ b/test/files/neg/t5060.check @@ -1,7 +1,7 @@ -t5060.scala:2: error: covariant type T occurs in contravariant position in type => Object with ScalaObject{def contains(x: T): Unit} of value foo0 +t5060.scala:2: error: covariant type T occurs in contravariant position in type => Object{def contains(x: T): Unit} of value foo0 val foo0 = { ^ -t5060.scala:6: error: covariant type T occurs in contravariant position in type => Object with ScalaObject{def contains(x: T): Unit} of method foo1 +t5060.scala:6: error: covariant type T occurs in contravariant position in type => Object{def contains(x: T): Unit} of method foo1 def foo1 = { ^ two errors found diff --git a/test/files/neg/t664.check b/test/files/neg/t664.check index 43a6bea074..cbdf53daea 100644 --- a/test/files/neg/t664.check +++ b/test/files/neg/t664.check @@ -1,7 +1,7 @@ -t664.scala:4: error: type Foo is not a member of test.Test with ScalaObject +t664.scala:4: error: type Foo is not a member of test.Test trait Foo extends super.Foo { ^ -t664.scala:5: error: type Bar is not a member of AnyRef with ScalaObject +t664.scala:5: error: type Bar is not a member of AnyRef trait Bar extends super.Bar; ^ two errors found diff --git a/test/files/neg/variances.check b/test/files/neg/variances.check index 4eaab56cef..dc72b05e1e 100644 --- a/test/files/neg/variances.check +++ b/test/files/neg/variances.check @@ -4,7 +4,7 @@ variances.scala:4: error: covariant type A occurs in contravariant position in t variances.scala:14: error: covariant type A occurs in contravariant position in type A of value a private[this] def setA(a : A) = this.a = a ^ -variances.scala:16: error: covariant type A occurs in invariant position in supertype test.C[A] with ScalaObject of object Baz +variances.scala:16: error: covariant type A occurs in invariant position in supertype test.C[A] of object Baz object Baz extends C[A] ^ variances.scala:63: error: covariant type A occurs in contravariant position in type => test.Covariant.T[A]{val m: A => A} of value x diff --git a/test/files/presentation/callcc-interpreter.check b/test/files/presentation/callcc-interpreter.check index 3385ef12b7..41b07b07dc 100644 --- a/test/files/presentation/callcc-interpreter.check +++ b/test/files/presentation/callcc-interpreter.check @@ -20,7 +20,7 @@ retrieved 64 members `method ->[B](y: B)(callccInterpreter.type, B)` `method ==(x$1: Any)Boolean` `method ==(x$1: AnyRef)Boolean` -`method add(a: callccInterpreter.Value, b: callccInterpreter.Value)callccInterpreter.M[_ >: callccInterpreter.Num with callccInterpreter.Wrong.type <: Product with Serializable with callccInterpreter.Value]` +`method add(a: callccInterpreter.Value, b: callccInterpreter.Value)callccInterpreter.M[_ >: callccInterpreter.Num with callccInterpreter.Wrong.type <: Serializable with Product with callccInterpreter.Value]` `method apply(a: callccInterpreter.Value, b: callccInterpreter.Value)callccInterpreter.M[callccInterpreter.Value]` `method asInstanceOf[T0]=> T0` `method callCC[A](h: (A => callccInterpreter.M[A]) => callccInterpreter.M[A])callccInterpreter.M[A]` @@ -87,7 +87,7 @@ def showM(m: callccInterpreter.M[callccInterpreter.Value]): String = m.in.apply( askType at CallccInterpreter.scala(50,30) ================================================================================ [response] askTypeAt at (50,30) -def add(a: callccInterpreter.Value, b: callccInterpreter.Value): callccInterpreter.M[_ >: callccInterpreter.Num with callccInterpreter.Wrong.type <: Product with Serializable with callccInterpreter.Value] = scala.this.Predef.Pair.apply[callccInterpreter.Value, callccInterpreter.Value](a, b) match { +def add(a: callccInterpreter.Value, b: callccInterpreter.Value): callccInterpreter.M[_ >: callccInterpreter.Num with callccInterpreter.Wrong.type <: Serializable with Product with callccInterpreter.Value] = scala.this.Predef.Pair.apply[callccInterpreter.Value, callccInterpreter.Value](a, b) match { case scala.this.Predef.Pair.unapply[callccInterpreter.Value, callccInterpreter.Value]() ((n: Int)callccInterpreter.Num((m @ _)), (n: Int)callccInterpreter.Num((n @ _))) => this.unitM[callccInterpreter.Num](callccInterpreter.this.Num.apply(m.+(n))) case _ => callccInterpreter.this.unitM[callccInterpreter.Wrong.type](callccInterpreter.this.Wrong) } diff --git a/test/files/run/primitive-sigs-2.check b/test/files/run/primitive-sigs-2.check index c69d1b54a6..feb0619525 100644 --- a/test/files/run/primitive-sigs-2.check +++ b/test/files/run/primitive-sigs-2.check @@ -1,4 +1,4 @@ -T interface scala.ScalaObject +T List(A, char, class java.lang.Object) a public java.lang.Object Arr.arr4(java.lang.Object[],scala.reflect.Manifest) diff --git a/test/files/run/repl-parens.check b/test/files/run/repl-parens.check index 944846541f..69f0a9ce30 100644 --- a/test/files/run/repl-parens.check +++ b/test/files/run/repl-parens.check @@ -66,7 +66,7 @@ scala> 55 ; () => 5 res13: () => Int = scala> () => { class X ; new X } -res14: () => Object with ScalaObject = +res14: () => Object = scala> diff --git a/test/files/run/t4172.check b/test/files/run/t4172.check index 95e3eb950d..da467e27ea 100644 --- a/test/files/run/t4172.check +++ b/test/files/run/t4172.check @@ -4,7 +4,7 @@ Type :help for more information. scala> scala> val c = { class C { override def toString = "C" }; ((new C, new C { def f = 2 })) } -c: (C, C{def f: Int}) forSome { type C <: Object with ScalaObject } = (C,C) +c: (C, C{def f: Int}) forSome { type C <: Object } = (C,C) scala> diff --git a/test/files/run/t4891.check b/test/files/run/t4891.check index 072f8df8d4..79fd7f6fbb 100644 --- a/test/files/run/t4891.check +++ b/test/files/run/t4891.check @@ -5,4 +5,3 @@ test.generic.C1 test.generic.C2 (m) public void test.generic.C1.m1() null -interface scala.ScalaObject -- cgit v1.2.3 From 0559b62b2d3f528eefdcda505127a59358e75599 Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Mon, 6 Feb 2012 18:16:12 +0100 Subject: Fixed a bunch of scalap check files to account for absence of ScalaObject --- test/files/scalap/abstractClass/result.test | 2 +- test/files/scalap/abstractMethod/result.test | 2 +- test/files/scalap/caseClass/result.test | 2 +- test/files/scalap/caseObject/result.test | 2 +- test/files/scalap/cbnParam/result.test | 2 +- test/files/scalap/classPrivate/result.test | 6 +++--- test/files/scalap/classWithExistential/result.test | 4 ++-- test/files/scalap/classWithSelfAnnotation/result.test | 2 +- test/files/scalap/covariantParam/result.test | 2 +- test/files/scalap/implicitParam/result.test | 2 +- test/files/scalap/packageObject/result.test | 2 +- test/files/scalap/paramClauses/result.test | 2 +- test/files/scalap/paramNames/result.test | 2 +- test/files/scalap/sequenceParam/result.test | 2 +- test/files/scalap/simpleClass/result.test | 2 +- test/files/scalap/traitObject/result.test | 4 ++-- test/files/scalap/typeAnnotations/result.test | 4 ++-- test/files/scalap/valAndVar/result.test | 2 +- test/files/scalap/wildcardType/result.test | 2 +- 19 files changed, 24 insertions(+), 24 deletions(-) (limited to 'test/files') diff --git a/test/files/scalap/abstractClass/result.test b/test/files/scalap/abstractClass/result.test index 9b8fc4dd95..9163346fc6 100644 --- a/test/files/scalap/abstractClass/result.test +++ b/test/files/scalap/abstractClass/result.test @@ -1,4 +1,4 @@ -abstract class AbstractClass extends java.lang.Object with scala.ScalaObject { +abstract class AbstractClass extends java.lang.Object { def this() = { /* compiled code */ } def foo : scala.Predef.String } diff --git a/test/files/scalap/abstractMethod/result.test b/test/files/scalap/abstractMethod/result.test index a1bd378c87..90f572f258 100644 --- a/test/files/scalap/abstractMethod/result.test +++ b/test/files/scalap/abstractMethod/result.test @@ -1,4 +1,4 @@ -trait AbstractMethod extends java.lang.Object with scala.ScalaObject { +trait AbstractMethod extends java.lang.Object { def $init$() : scala.Unit = { /* compiled code */ } def arity : scala.Int def isCool : scala.Boolean = { /* compiled code */ } diff --git a/test/files/scalap/caseClass/result.test b/test/files/scalap/caseClass/result.test index a0dbc497fe..8e3255859f 100644 --- a/test/files/scalap/caseClass/result.test +++ b/test/files/scalap/caseClass/result.test @@ -1,4 +1,4 @@ -case class CaseClass[A <: scala.Seq[scala.Int]](i : A, s : scala.Predef.String) extends java.lang.Object with scala.ScalaObject with scala.Product with scala.Serializable { +case class CaseClass[A <: scala.Seq[scala.Int]](i : A, s : scala.Predef.String) extends java.lang.Object with scala.Product with scala.Serializable { val i : A = { /* compiled code */ } val s : scala.Predef.String = { /* compiled code */ } def foo : scala.Int = { /* compiled code */ } diff --git a/test/files/scalap/caseObject/result.test b/test/files/scalap/caseObject/result.test index 55e46eccd7..9c66c6ebb1 100644 --- a/test/files/scalap/caseObject/result.test +++ b/test/files/scalap/caseObject/result.test @@ -1,4 +1,4 @@ -case object CaseObject extends java.lang.Object with scala.ScalaObject with scala.Product with scala.Serializable { +case object CaseObject extends java.lang.Object with scala.Product with scala.Serializable { def bar : scala.Int = { /* compiled code */ } override def productPrefix : java.lang.String = { /* compiled code */ } def productArity : scala.Int = { /* compiled code */ } diff --git a/test/files/scalap/cbnParam/result.test b/test/files/scalap/cbnParam/result.test index c6b2f4caa8..fbe035d63c 100644 --- a/test/files/scalap/cbnParam/result.test +++ b/test/files/scalap/cbnParam/result.test @@ -1,3 +1,3 @@ -class CbnParam extends java.lang.Object with scala.ScalaObject { +class CbnParam extends java.lang.Object { def this(s : => scala.Predef.String) = { /* compiled code */ } } diff --git a/test/files/scalap/classPrivate/result.test b/test/files/scalap/classPrivate/result.test index 0d12b779c3..5f2e1cc00e 100644 --- a/test/files/scalap/classPrivate/result.test +++ b/test/files/scalap/classPrivate/result.test @@ -1,10 +1,10 @@ -class ClassPrivate extends java.lang.Object with scala.ScalaObject { +class ClassPrivate extends java.lang.Object { def this() = { /* compiled code */ } def baz : scala.Int = { /* compiled code */ } - class Outer extends java.lang.Object with scala.ScalaObject { + class Outer extends java.lang.Object { def this() = { /* compiled code */ } private[ClassPrivate] def qux : scala.Int = { /* compiled code */ } } protected def quux : scala.Int = { /* compiled code */ } private[ClassPrivate] def bar : scala.Int = { /* compiled code */ } -} \ No newline at end of file +} diff --git a/test/files/scalap/classWithExistential/result.test b/test/files/scalap/classWithExistential/result.test index 91afddaf0e..b8ce005da9 100644 --- a/test/files/scalap/classWithExistential/result.test +++ b/test/files/scalap/classWithExistential/result.test @@ -1,4 +1,4 @@ -class ClassWithExistential extends java.lang.Object with scala.ScalaObject { +class ClassWithExistential extends java.lang.Object { def this() = { /* compiled code */ } def foo[A, B] : scala.Function1[A, B forSome {type A <: scala.Seq[scala.Int]; type B >: scala.Predef.String}] = { /* compiled code */ } -} \ No newline at end of file +} diff --git a/test/files/scalap/classWithSelfAnnotation/result.test b/test/files/scalap/classWithSelfAnnotation/result.test index 326437c7be..df7bd86643 100644 --- a/test/files/scalap/classWithSelfAnnotation/result.test +++ b/test/files/scalap/classWithSelfAnnotation/result.test @@ -1,4 +1,4 @@ -class ClassWithSelfAnnotation extends java.lang.Object with scala.ScalaObject { +class ClassWithSelfAnnotation extends java.lang.Object { this : ClassWithSelfAnnotation with java.lang.CharSequence => def this() = { /* compiled code */ } def foo : scala.Int = { /* compiled code */ } diff --git a/test/files/scalap/covariantParam/result.test b/test/files/scalap/covariantParam/result.test index 8acd9b497a..2f52f1f28e 100644 --- a/test/files/scalap/covariantParam/result.test +++ b/test/files/scalap/covariantParam/result.test @@ -1,4 +1,4 @@ -class CovariantParam[+A] extends java.lang.Object with scala.ScalaObject { +class CovariantParam[+A] extends java.lang.Object { def this() = { /* compiled code */ } def foo[A](a : A) : scala.Int = { /* compiled code */ } } diff --git a/test/files/scalap/implicitParam/result.test b/test/files/scalap/implicitParam/result.test index 11d678df06..0ea212dda6 100644 --- a/test/files/scalap/implicitParam/result.test +++ b/test/files/scalap/implicitParam/result.test @@ -1,4 +1,4 @@ -class ImplicitParam extends java.lang.Object with scala.ScalaObject { +class ImplicitParam extends java.lang.Object { def this() = { /* compiled code */ } def foo(i : scala.Int)(implicit f : scala.Float, d : scala.Double) : scala.Int = { /* compiled code */ } } diff --git a/test/files/scalap/packageObject/result.test b/test/files/scalap/packageObject/result.test index 6a8d6ae1d5..94c6a01b08 100644 --- a/test/files/scalap/packageObject/result.test +++ b/test/files/scalap/packageObject/result.test @@ -1,4 +1,4 @@ -package object PackageObject extends java.lang.Object with scala.ScalaObject { +package object PackageObject extends java.lang.Object { def this() = { /* compiled code */ } type A = scala.Predef.String def foo(i : scala.Int) : scala.Int = { /* compiled code */ } diff --git a/test/files/scalap/paramClauses/result.test b/test/files/scalap/paramClauses/result.test index 9ef93d2e76..dc4397386c 100644 --- a/test/files/scalap/paramClauses/result.test +++ b/test/files/scalap/paramClauses/result.test @@ -1,4 +1,4 @@ -class ParamClauses extends java.lang.Object with scala.ScalaObject { +class ParamClauses extends java.lang.Object { def this() = { /* compiled code */ } def foo(i : scala.Int)(s : scala.Predef.String)(t : scala.Double) : scala.Int = { /* compiled code */ } } diff --git a/test/files/scalap/paramNames/result.test b/test/files/scalap/paramNames/result.test index f9d98d9647..4d3c7d0c1e 100644 --- a/test/files/scalap/paramNames/result.test +++ b/test/files/scalap/paramNames/result.test @@ -1,4 +1,4 @@ -class ParamNames extends java.lang.Object with scala.ScalaObject { +class ParamNames extends java.lang.Object { def this() = { /* compiled code */ } def foo(s : => scala.Seq[scala.Int], s2 : => scala.Seq[scala.Any]) : scala.Unit = { /* compiled code */ } } diff --git a/test/files/scalap/sequenceParam/result.test b/test/files/scalap/sequenceParam/result.test index 4b9d7844ab..ed47c094fe 100644 --- a/test/files/scalap/sequenceParam/result.test +++ b/test/files/scalap/sequenceParam/result.test @@ -1,3 +1,3 @@ -class SequenceParam extends java.lang.Object with scala.ScalaObject { +class SequenceParam extends java.lang.Object { def this(s : scala.Predef.String, i : scala.Int*) = { /* compiled code */ } } diff --git a/test/files/scalap/simpleClass/result.test b/test/files/scalap/simpleClass/result.test index d10b633bce..905046ce52 100644 --- a/test/files/scalap/simpleClass/result.test +++ b/test/files/scalap/simpleClass/result.test @@ -1,4 +1,4 @@ -class SimpleClass extends java.lang.Object with scala.ScalaObject { +class SimpleClass extends java.lang.Object { def this() = { /* compiled code */ } def foo : scala.Int = { /* compiled code */ } } diff --git a/test/files/scalap/traitObject/result.test b/test/files/scalap/traitObject/result.test index 0d7de1535d..d0521043c8 100644 --- a/test/files/scalap/traitObject/result.test +++ b/test/files/scalap/traitObject/result.test @@ -1,8 +1,8 @@ -trait TraitObject extends java.lang.Object with scala.ScalaObject { +trait TraitObject extends java.lang.Object { def $init$() : scala.Unit = { /* compiled code */ } def foo : scala.Int = { /* compiled code */ } } -object TraitObject extends java.lang.Object with scala.ScalaObject { +object TraitObject extends java.lang.Object { def this() = { /* compiled code */ } def bar : scala.Int = { /* compiled code */ } } diff --git a/test/files/scalap/typeAnnotations/result.test b/test/files/scalap/typeAnnotations/result.test index b565d6185b..d28712f12b 100644 --- a/test/files/scalap/typeAnnotations/result.test +++ b/test/files/scalap/typeAnnotations/result.test @@ -1,8 +1,8 @@ -abstract class TypeAnnotations[@scala.specialized R] extends java.lang.Object with scala.ScalaObject { +abstract class TypeAnnotations[@scala.specialized R] extends java.lang.Object { def this() = { /* compiled code */ } @scala.specialized val x : scala.Int = { /* compiled code */ } @scala.specialized type T def compose[@scala.specialized A](x : A, y : R) : A = { /* compiled code */ } -} \ No newline at end of file +} diff --git a/test/files/scalap/valAndVar/result.test b/test/files/scalap/valAndVar/result.test index 934ad0a086..90081acade 100644 --- a/test/files/scalap/valAndVar/result.test +++ b/test/files/scalap/valAndVar/result.test @@ -1,4 +1,4 @@ -class ValAndVar extends java.lang.Object with scala.ScalaObject { +class ValAndVar extends java.lang.Object { def this() = { /* compiled code */ } val foo : java.lang.String = { /* compiled code */ } var bar : scala.Int = { /* compiled code */ } diff --git a/test/files/scalap/wildcardType/result.test b/test/files/scalap/wildcardType/result.test index aa3d5d53bc..28147b6605 100644 --- a/test/files/scalap/wildcardType/result.test +++ b/test/files/scalap/wildcardType/result.test @@ -1,3 +1,3 @@ -class WildcardType extends java.lang.Object with scala.ScalaObject { +class WildcardType extends java.lang.Object { def this(f : scala.Function1[scala.Int, _]) = { /* compiled code */ } } -- cgit v1.2.3 From 7f9c2636cf560b066783e0745a08393ce17531cd Mon Sep 17 00:00:00 2001 From: Paul Phillips Date: Mon, 6 Feb 2012 13:11:30 -0800 Subject: Removing unnecessary AnyVal code. ...since it works from source. The parser must be forcibly restrained from adding a bogus constructor, but other than that it's pretty much smooth sailing. To give an idea how smooth, if I change scala.Short like so: trait Bippy extends Any final class Short extends AnyVal with Bippy Then it just works, at least until the fiction is revealed. scala> def f(x: Bippy) = x f: (x: Bippy)Bippy scala> f(5) :9: error: type mismatch; found : Int(5) required: Bippy f(5) ^ scala> f(5: Short) java.lang.ClassCastException: java.lang.Short cannot be cast to scala.Bippy at .(:9) at .() at .(:11) --- .../scala/tools/nsc/ast/parser/Parsers.scala | 55 +++++++--------------- .../scala/tools/nsc/transform/AddInterfaces.scala | 24 +++++----- .../scala/tools/nsc/typechecker/Typers.scala | 5 +- test/files/codelib/code.jar.desired.sha1 | 2 +- test/files/neg/anyval-anyref-parent.check | 12 ++++- test/files/neg/anyval-anyref-parent.scala | 4 ++ test/files/neg/anyval-children-2.check | 4 -- test/files/neg/anyval-children-2.scala | 1 - test/files/neg/anyval-children.check | 23 --------- test/files/neg/anyval-children.scala | 14 ------ test/files/scalap/caseClass/result.test | 2 +- test/files/scalap/caseObject/result.test | 2 +- 12 files changed, 48 insertions(+), 100 deletions(-) delete mode 100644 test/files/neg/anyval-children-2.check delete mode 100644 test/files/neg/anyval-children-2.scala delete mode 100644 test/files/neg/anyval-children.check delete mode 100644 test/files/neg/anyval-children.scala (limited to 'test/files') diff --git a/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala b/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala index c2b4dc32b6..20c35e952f 100644 --- a/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala +++ b/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala @@ -2722,23 +2722,6 @@ self => * }}} */ def templateOpt(mods: Modifiers, name: Name, constrMods: Modifiers, vparamss: List[List[ValDef]], tstart: Int): Template = { - /** Extra parents for case classes. */ - def caseParents() = ( - if (mods.isCase) { - val arity = if (vparamss.isEmpty || vparamss.head.isEmpty) 0 else vparamss.head.size - productConstr :: serializableConstr :: { - Nil - // if (arity == 0 || settings.YnoProductN.value) Nil - // else List( - // AppliedTypeTree( - // productConstrN(arity), - // vparamss.head map (vd => vd.tpt.duplicate setPos vd.tpt.pos.focus) - // ) - // ) - } - } - else Nil - ) val (parents0, argss, self, body) = ( if (in.token == EXTENDS || in.token == SUBTYPE && mods.hasTraitFlag) { in.nextToken() @@ -2750,29 +2733,25 @@ self => (List(), List(List()), self, body) } ) - + def anyrefParents() = { + val caseParents = if (mods.isCase) List(productConstr, serializableConstr) else Nil + parents0 ::: caseParents match { + case Nil => List(scalaAnyRefConstr) + case ps => ps + } + } + def anyvalConstructor() = ( + // Not a well-formed constructor, has to be finished later - see note + // regarding AnyVal constructor in AddInterfaces. + DefDef(NoMods, nme.CONSTRUCTOR, Nil, List(Nil), TypeTree(), Block(Nil, Literal(Constant()))) + ) val tstart0 = if (body.isEmpty && in.lastOffset < tstart) in.lastOffset else tstart + atPos(tstart0) { - if (inScalaPackage && name == tpnme.AnyVal) { - // Not a well-formed constructor, has to be finished later - see note - // regarding AnyVal constructor in AddInterfaces. - val constructor = DefDef(NoMods, nme.CONSTRUCTOR, Nil, List(Nil), TypeTree(), Block(Nil, Literal(Constant()))) - Template(parents0, self, constructor :: body) - } - else if (isPrimitiveType(name)) - Template(List(scalaAnyValConstr), self, body) - else if (parents0 exists isReferenceToAnyVal) { - // @inline and other restrictions enforced in refchecks - Template(parents0, self, body) - } - else { - val casePs = caseParents() - val parents = parents0 match { - case Nil if casePs.isEmpty => List(scalaAnyRefConstr) - case _ => parents0 ++ casePs - } - Template(parents, self, constrMods, vparamss, argss, body, o2p(tstart)) - } + if ((inScalaPackage && name == tpnme.AnyVal) || (parents0 exists isReferenceToAnyVal)) + Template(parents0, self, anyvalConstructor :: body) + else + Template(anyrefParents, self, constrMods, vparamss, argss, body, o2p(tstart)) } } diff --git a/src/compiler/scala/tools/nsc/transform/AddInterfaces.scala b/src/compiler/scala/tools/nsc/transform/AddInterfaces.scala index e7759f1d7e..531a475bc6 100644 --- a/src/compiler/scala/tools/nsc/transform/AddInterfaces.scala +++ b/src/compiler/scala/tools/nsc/transform/AddInterfaces.scala @@ -302,21 +302,19 @@ abstract class AddInterfaces extends InfoTransform { yield mixinConstructorCall(implClass(mc)) } tree match { + case Block(Nil, expr) => + // AnyVal constructor - have to provide a real body so the + // jvm doesn't throw a VerifyError. But we can't add the + // body until now, because the typer knows that Any has no + // constructor and won't accept a call to super.init. + assert((clazz isSubClass AnyValClass) || clazz.info.parents.isEmpty, clazz) + val superCall = Apply(Select(Super(This(tpnme.EMPTY), tpnme.EMPTY), nme.CONSTRUCTOR), Nil) + Block(List(superCall), expr) + case Block(stats, expr) => // needs `hasSymbol` check because `supercall` could be a block (named / default args) - stats span (t => t.hasSymbolWhich(_ hasFlag PRESUPER)) match { - case (presuper, supercall :: rest) => - stats span (t => t.hasSymbolWhich(_ hasFlag PRESUPER)) - treeCopy.Block(tree, presuper ::: (supercall :: mixinConstructorCalls ::: rest), expr) - case (Nil, Nil) => - assert(clazz eq AnyValClass, clazz) - // AnyVal constructor - have to provide a real body so the - // jvm doesn't throw a VerifyError. But we can't add the - // body until now, because the typer knows that Any has no - // constructor and won't accept a call to super.init. - val superCall = Apply(Select(Super(This(tpnme.EMPTY), tpnme.EMPTY), nme.CONSTRUCTOR), Nil) - Block(List(superCall), Literal(Constant())) - } + val (presuper, supercall :: rest) = stats span (t => t.hasSymbolWhich(_ hasFlag PRESUPER)) + treeCopy.Block(tree, presuper ::: (supercall :: mixinConstructorCalls ::: rest), expr) } } diff --git a/src/compiler/scala/tools/nsc/typechecker/Typers.scala b/src/compiler/scala/tools/nsc/typechecker/Typers.scala index 59437dc036..4bb2387439 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Typers.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Typers.scala @@ -1787,11 +1787,10 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser { transformedOrTyped(ddef.rhs, EXPRmode, tpt1.tpe) } - if (meth.isPrimaryConstructor && meth.isClassConstructor && !isPastTyper && !reporter.hasErrors) { + if (meth.isPrimaryConstructor && meth.isClassConstructor && !isPastTyper && !reporter.hasErrors && !meth.owner.isSubClass(AnyValClass)) { // At this point in AnyVal there is no supercall, which will blow up // in computeParamAliases; there's nothing to be computed for Anyval anyway. - if (meth.owner ne AnyValClass) - computeParamAliases(meth.owner, vparamss1, rhs1) + computeParamAliases(meth.owner, vparamss1, rhs1) } if (tpt1.tpe.typeSymbol != NothingClass && !context.returnsSeen && rhs1.tpe.typeSymbol != NothingClass) rhs1 = checkDead(rhs1) diff --git a/test/files/codelib/code.jar.desired.sha1 b/test/files/codelib/code.jar.desired.sha1 index 5e7acf3b90..27326a06a8 100644 --- a/test/files/codelib/code.jar.desired.sha1 +++ b/test/files/codelib/code.jar.desired.sha1 @@ -1 +1 @@ -5880dd44ee9fedec44fed3f223842e42d8a63959 ?code.jar +1f3f43a79512a89aa8f4e34c9288a290af8262d7 ?code.jar diff --git a/test/files/neg/anyval-anyref-parent.check b/test/files/neg/anyval-anyref-parent.check index b40a0f2710..be895867ff 100644 --- a/test/files/neg/anyval-anyref-parent.check +++ b/test/files/neg/anyval-anyref-parent.check @@ -1,4 +1,14 @@ anyval-anyref-parent.scala:5: error: Any does not have a constructor class Bar1 extends Any // fail ^ -one error found +anyval-anyref-parent.scala:9: error: illegal inheritance; superclass Any + is not a subclass of the superclass Object + of the mixin trait Immutable +trait Foo4 extends Any with Immutable // fail + ^ +anyval-anyref-parent.scala:10: error: illegal inheritance; superclass AnyVal + is not a subclass of the superclass Object + of the mixin trait Immutable +trait Foo5 extends AnyVal with Immutable // fail + ^ +three errors found diff --git a/test/files/neg/anyval-anyref-parent.scala b/test/files/neg/anyval-anyref-parent.scala index b7bb122ea8..08568487a9 100644 --- a/test/files/neg/anyval-anyref-parent.scala +++ b/test/files/neg/anyval-anyref-parent.scala @@ -5,3 +5,7 @@ trait Foo3 extends AnyRef class Bar1 extends Any // fail @inline class Bar2 extends AnyVal class Bar3 extends AnyRef + +trait Foo4 extends Any with Immutable // fail +trait Foo5 extends AnyVal with Immutable // fail +trait Foo6 extends AnyRef with Immutable diff --git a/test/files/neg/anyval-children-2.check b/test/files/neg/anyval-children-2.check deleted file mode 100644 index cb327faeeb..0000000000 --- a/test/files/neg/anyval-children-2.check +++ /dev/null @@ -1,4 +0,0 @@ -anyval-children-2.scala:1: error: Only @inline classes (not traits) are allowed to extend AnyVal -@inline trait NotOkDingus1 extends AnyVal // fail - ^ -one error found diff --git a/test/files/neg/anyval-children-2.scala b/test/files/neg/anyval-children-2.scala deleted file mode 100644 index 4034eb22dd..0000000000 --- a/test/files/neg/anyval-children-2.scala +++ /dev/null @@ -1 +0,0 @@ -@inline trait NotOkDingus1 extends AnyVal // fail diff --git a/test/files/neg/anyval-children.check b/test/files/neg/anyval-children.check deleted file mode 100644 index 769f990210..0000000000 --- a/test/files/neg/anyval-children.check +++ /dev/null @@ -1,23 +0,0 @@ -anyval-children.scala:3: error: class AnyVal needs to be a trait to be mixed in -@inline class NotOkDingus2 extends Immutable with AnyVal // fail - ^ -anyval-children.scala:7: error: Bippy does not have a constructor -class NotOkBippy1 extends Bippy // fail - ^ -anyval-children.scala:9: error: illegal inheritance; superclass Bippy - is not a subclass of the superclass Object - of the mixin trait Immutable -class NotOkBippy2 extends Bippy with Immutable //fail - ^ -anyval-children.scala:9: error: Bippy does not have a constructor -class NotOkBippy2 extends Bippy with Immutable //fail - ^ -anyval-children.scala:11: error: illegal inheritance; superclass Bippy - is not a subclass of the superclass Object - of the mixin trait Immutable -@inline class NotOkBippy3 extends Bippy with Immutable //fail - ^ -anyval-children.scala:11: error: Bippy does not have a constructor -@inline class NotOkBippy3 extends Bippy with Immutable //fail - ^ -6 errors found diff --git a/test/files/neg/anyval-children.scala b/test/files/neg/anyval-children.scala deleted file mode 100644 index 5a6109f786..0000000000 --- a/test/files/neg/anyval-children.scala +++ /dev/null @@ -1,14 +0,0 @@ -class Bippy extends AnyVal // fail - -@inline class NotOkDingus2 extends Immutable with AnyVal // fail - -@inline object NotOkDingus3 extends AnyVal // fail - -class NotOkBippy1 extends Bippy // fail - -class NotOkBippy2 extends Bippy with Immutable //fail - -@inline class NotOkBippy3 extends Bippy with Immutable //fail - - -@inline class OkBippy extends AnyVal // ok diff --git a/test/files/scalap/caseClass/result.test b/test/files/scalap/caseClass/result.test index 8e3255859f..7dfe3a0356 100644 --- a/test/files/scalap/caseClass/result.test +++ b/test/files/scalap/caseClass/result.test @@ -1,4 +1,4 @@ -case class CaseClass[A <: scala.Seq[scala.Int]](i : A, s : scala.Predef.String) extends java.lang.Object with scala.Product with scala.Serializable { +case class CaseClass[A <: scala.Seq[scala.Int]](i : A, s : scala.Predef.String) extends scala.AnyRef with scala.Product with scala.Serializable { val i : A = { /* compiled code */ } val s : scala.Predef.String = { /* compiled code */ } def foo : scala.Int = { /* compiled code */ } diff --git a/test/files/scalap/caseObject/result.test b/test/files/scalap/caseObject/result.test index 9c66c6ebb1..867a4b2162 100644 --- a/test/files/scalap/caseObject/result.test +++ b/test/files/scalap/caseObject/result.test @@ -1,4 +1,4 @@ -case object CaseObject extends java.lang.Object with scala.Product with scala.Serializable { +case object CaseObject extends scala.AnyRef with scala.Product with scala.Serializable { def bar : scala.Int = { /* compiled code */ } override def productPrefix : java.lang.String = { /* compiled code */ } def productArity : scala.Int = { /* compiled code */ } -- cgit v1.2.3 From aee074e69ea8295c018040b606ed8f13ac08d2ab Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Tue, 7 Feb 2012 13:58:27 +0100 Subject: Added test case. --- test/files/run/Meter.scala | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) create mode 100644 test/files/run/Meter.scala (limited to 'test/files') diff --git a/test/files/run/Meter.scala b/test/files/run/Meter.scala new file mode 100644 index 0000000000..0c30ddd41e --- /dev/null +++ b/test/files/run/Meter.scala @@ -0,0 +1,19 @@ +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" +} +trait Printable extends Any { def print: Unit = Console.print(this) } + +object Test extends App { + + val x = new Meter(1) + println((x + x) / x) + println((x + x) / 0.5) + println((x < x).toString) + + +} -- cgit v1.2.3 From 52c99f57ef41c436719818b8e3860e3bfbf023e2 Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Mon, 13 Feb 2012 00:02:39 +0100 Subject: All steps of value class proposal implemented. Most restrictions are now enforced. Super calls and specialized still missing. --- src/compiler/scala/reflect/internal/Symbols.scala | 87 +++++++++------- .../scala/reflect/internal/transform/Erasure.scala | 25 ++--- src/compiler/scala/tools/nsc/Global.scala | 24 +++-- src/compiler/scala/tools/nsc/ast/TreeInfo.scala | 6 +- .../scala/tools/nsc/transform/Erasure.scala | 113 ++++++++++++++------- .../tools/nsc/transform/ExtensionMethods.scala | 3 +- .../tools/nsc/typechecker/SyntheticMethods.scala | 108 ++++++++++++++------ .../scala/tools/nsc/typechecker/Typers.scala | 32 +++++- test/files/neg/anyval-anyref-parent.check | 15 ++- test/files/neg/anyval-anyref-parent.scala | 7 +- test/files/neg/t3222.check | 6 +- test/files/pos/anyval-children.scala | 1 - test/files/run/Meter.scala | 21 +++- test/files/run/programmatic-main.check | 27 ++--- 14 files changed, 311 insertions(+), 164 deletions(-) delete mode 100644 test/files/pos/anyval-children.scala (limited to 'test/files') diff --git a/src/compiler/scala/reflect/internal/Symbols.scala b/src/compiler/scala/reflect/internal/Symbols.scala index e448ef86f6..89af10283b 100644 --- a/src/compiler/scala/reflect/internal/Symbols.scala +++ b/src/compiler/scala/reflect/internal/Symbols.scala @@ -17,7 +17,7 @@ trait Symbols extends api.Symbols { self: SymbolTable => import definitions._ protected var ids = 0 - + val emptySymbolArray = new Array[Symbol](0) def symbolCount = ids // statistics @@ -38,14 +38,14 @@ trait Symbols extends api.Symbols { self: SymbolTable => nextexid += 1 newTypeName("_" + nextexid + suffix) } - + // Set the fields which point companions at one another. Returns the module. def connectModuleToClass(m: ModuleSymbol, moduleClass: ClassSymbol): ModuleSymbol = { moduleClass.sourceModule = m m setModuleClass moduleClass m } - + /** Create a new free variable. Its owner is NoSymbol. */ def newFreeVar(name: TermName, tpe: Type, value: Any, newFlags: Long = 0L): FreeVar = @@ -67,7 +67,7 @@ trait Symbols extends api.Symbols { self: SymbolTable => def selfType: Type = typeOfThis def typeSignature: Type = info def typeSignatureIn(site: Type): Type = site memberInfo this - + def asType: Type = tpe def asTypeIn(site: Type): Type = site.memberType(this) def asTypeConstructor: Type = typeConstructor @@ -89,19 +89,19 @@ trait Symbols extends api.Symbols { self: SymbolTable => private[this] var _rawowner = initOwner // Syncnote: need not be protected, as only assignment happens in owner_=, which is not exposed to api private[this] var _rawname = initName private[this] var _rawflags = 0L - + def rawowner = _rawowner def rawname = _rawname def rawflags = _rawflags - + protected def rawflags_=(x: FlagsType) { _rawflags = x } - + private var rawpos = initPos - + val id = nextId() // identity displayed when -uniqid private[this] var _validTo: Period = NoPeriod - + def validTo = _validTo def validTo_=(x: Period) { _validTo = x} @@ -179,10 +179,10 @@ trait Symbols extends api.Symbols { self: SymbolTable => */ def newTermSymbol(name: TermName, pos: Position = NoPosition, newFlags: Long = 0L): TermSymbol = new TermSymbol(this, pos, name) initFlags newFlags - + def newAbstractTypeSymbol(name: TypeName, pos: Position = NoPosition, newFlags: Long = 0L): AbstractTypeSymbol = new AbstractTypeSymbol(this, pos, name) initFlags newFlags - + def newAliasTypeSymbol(name: TypeName, pos: Position = NoPosition, newFlags: Long = 0L): AliasTypeSymbol = new AliasTypeSymbol(this, pos, name) initFlags newFlags @@ -194,10 +194,10 @@ trait Symbols extends api.Symbols { self: SymbolTable => def newClassSymbol(name: TypeName, pos: Position = NoPosition, newFlags: Long = 0L): ClassSymbol = new ClassSymbol(this, pos, name) initFlags newFlags - + def newModuleClassSymbol(name: TypeName, pos: Position = NoPosition, newFlags: Long = 0L): ModuleClassSymbol = new ModuleClassSymbol(this, pos, name) initFlags newFlags - + /** Derive whether it is an abstract type from the flags; after creation * the DEFERRED flag will be ignored. */ @@ -206,7 +206,7 @@ trait Symbols extends api.Symbols { self: SymbolTable => newAliasTypeSymbol(name, pos, newFlags) else newAbstractTypeSymbol(name, pos, newFlags) - + def newTypeSkolemSymbol(name: TypeName, origin: AnyRef, pos: Position = NoPosition, newFlags: Long = 0L): TypeSkolem = if ((newFlags & DEFERRED) == 0L) new TypeSkolem(this, pos, name, origin) initFlags newFlags @@ -243,7 +243,7 @@ trait Symbols extends api.Symbols { self: SymbolTable => */ final def newAliasType(name: TypeName, pos: Position = NoPosition, newFlags: Long = 0L): Symbol = newAliasTypeSymbol(name, pos, newFlags) - + /** Symbol of an abstract type type T >: ... <: ... */ final def newAbstractType(name: TypeName, pos: Position = NoPosition, newFlags: Long = 0L): Symbol = @@ -261,7 +261,7 @@ trait Symbols extends api.Symbols { self: SymbolTable => def freshName() = { cnt += 1; nme.syntheticParamName(cnt) } mmap(argtypess)(tp => newValueParameter(freshName(), focusPos(owner.pos), SYNTHETIC) setInfo tp) } - + def newSyntheticTypeParam(): Symbol = newSyntheticTypeParam("T0", 0L) def newSyntheticTypeParam(name: String, newFlags: Long): Symbol = newTypeParameter(newTypeName(name), NoPosition, newFlags) setInfo TypeBounds.empty def newSyntheticTypeParams(num: Int): List[Symbol] = (0 until num).toList map (n => newSyntheticTypeParam("T" + n, 0L)) @@ -302,7 +302,7 @@ trait Symbols extends api.Symbols { self: SymbolTable => final def newClass(name: TypeName, pos: Position = NoPosition, newFlags: Long = 0L) = newClassSymbol(name, pos, newFlags) - + /** A new class with its info set to a ClassInfoType with given scope and parents. */ def newClassWithInfo(name: TypeName, parents: List[Type], scope: Scope, pos: Position = NoPosition, newFlags: Long = 0L) = { val clazz = newClass(name, pos, newFlags) @@ -354,9 +354,9 @@ trait Symbols extends api.Symbols { self: SymbolTable => def newAliasType(pos: Position, name: TypeName): Symbol = newAliasType(name, pos) @deprecated("Use the other signature", "2.10.0") def newAbstractType(pos: Position, name: TypeName): Symbol = newAbstractType(name, pos) - @deprecated("Use the other signature", "2.10.0") + @deprecated("Use the other signature", "2.10.0") def newExistential(pos: Position, name: TypeName): Symbol = newExistential(name, pos) - @deprecated("Use the other signature", "2.10.0") + @deprecated("Use the other signature", "2.10.0") def newMethod(pos: Position, name: TermName): MethodSymbol = newMethod(name, pos) // ----- locking and unlocking ------------------------------------------------------ @@ -499,11 +499,11 @@ trait Symbols extends api.Symbols { self: SymbolTable => // class C extends D( { class E { ... } ... } ). Here, E is a class local to a constructor final def isClassLocalToConstructor = isClass && hasFlag(INCONSTRUCTOR) - final def isInlineClass = + final def isInlineClass = isClass && info.parents.headOption.getOrElse(AnyClass.tpe).typeSymbol == AnyValClass && !isPrimitiveValueClass - - final def isMethodWithExtension = + + final def isMethodWithExtension = isMethod && owner.isInlineClass && !isParamAccessor && !isConstructor final def isAnonymousClass = isClass && (name containsName tpnme.ANON_CLASS_NAME) @@ -845,7 +845,7 @@ trait Symbols extends api.Symbols { self: SymbolTable => private def addModuleSuffix(n: Name): Name = if (needsModuleSuffix) n append nme.MODULE_SUFFIX_STRING else n - + def moduleSuffix: String = ( if (needsModuleSuffix) nme.MODULE_SUFFIX_STRING else "" @@ -853,7 +853,7 @@ trait Symbols extends api.Symbols { self: SymbolTable => /** Whether this symbol needs nme.MODULE_SUFFIX_STRING (aka $) appended on the java platform. */ def needsModuleSuffix = ( - hasModuleFlag + hasModuleFlag && !isMethod && !isImplClass && !isJavaDefined @@ -880,7 +880,7 @@ trait Symbols extends api.Symbols { self: SymbolTable => else if (owner.isEffectiveRoot) name else effectiveOwner.enclClass.fullNameAsName(separator) append separator append name ) - + def fullNameAsName(separator: Char): Name = nme.dropLocalSuffix(fullNameInternal(separator)) /** The encoded full path name of this symbol, where outer names and inner names @@ -1032,7 +1032,7 @@ trait Symbols extends api.Symbols { self: SymbolTable => /** Substitute second list of symbols for first in current info. */ def substInfo(syms0: List[Symbol], syms1: List[Symbol]) = modifyInfo(_.substSym(syms0, syms1)) def setInfoOwnerAdjusted(info: Type): this.type = setInfo(info atOwner this) - + /** Set the info and enter this symbol into the owner's scope. */ def setInfoAndEnter(info: Type): this.type = { setInfo(info) @@ -1341,7 +1341,7 @@ trait Symbols extends api.Symbols { self: SymbolTable => */ final def isNestedIn(that: Symbol): Boolean = owner == that || owner != NoSymbol && (owner isNestedIn that) - + /** Is this class symbol a subclass of that symbol, * and is this class symbol also different from Null or Nothing? */ def isNonBottomSubClass(that: Symbol): Boolean = false @@ -1818,7 +1818,12 @@ trait Symbols extends api.Symbols { self: SymbolTable => base.info.decl(sname) filter (_.hasAccessorFlag) } - /** The case module corresponding to this case class + /** Return the accessor method of the first parameter of this class. + * or NoSymbol if it does not exist. + */ + def firstParamAccessor: Symbol = NoSymbol + + /** The case module corresponding to this case class * @pre case class is a member of some other class or package */ final def caseModule: Symbol = { @@ -1859,7 +1864,7 @@ trait Symbols extends api.Symbols { self: SymbolTable => /** Remove any access boundary and clear flags PROTECTED | PRIVATE. */ def makePublic = this setPrivateWithin NoSymbol resetFlag AccessFlags - + /** The first parameter to the first argument list of this method, * or NoSymbol if inapplicable. */ @@ -2141,7 +2146,7 @@ trait Symbols extends api.Symbols { self: SymbolTable => def referenced: Symbol = _referenced def referenced_=(x: Symbol) { _referenced = x } - + def existentialBound = singletonBounds(this.tpe) def cloneSymbolImpl(owner: Symbol, newFlags: Long): Symbol = @@ -2235,7 +2240,7 @@ trait Symbols extends api.Symbols { self: SymbolTable => if (!isMethod && needsFlatClasses) { if (flatname eq null) flatname = nme.flattenedName(rawowner.name, rawname) - + flatname } else rawname.toTermName @@ -2271,7 +2276,7 @@ trait Symbols extends api.Symbols { self: SymbolTable => res } } - + class AliasTypeSymbol protected[Symbols] (initOwner: Symbol, initPos: Position, initName: TypeName) extends TypeSymbol(initOwner, initPos, initName) { // Temporary programmatic help tracking down who might do such a thing @@ -2286,13 +2291,13 @@ trait Symbols extends api.Symbols { self: SymbolTable => override def cloneSymbolImpl(owner: Symbol, newFlags: Long): AliasTypeSymbol = owner.newAliasTypeSymbol(name, pos, newFlags) } - + class AbstractTypeSymbol(initOwner: Symbol, initPos: Position, initName: TypeName) extends TypeSymbol(initOwner, initPos, initName) with AbstractTypeMixin { override def cloneSymbolImpl(owner: Symbol, newFlags: Long): AbstractTypeSymbol = owner.newAbstractTypeSymbol(name, pos, newFlags) } - + /** Might be mixed into TypeSymbol or TypeSkolem. */ trait AbstractTypeMixin extends TypeSymbol { @@ -2490,7 +2495,7 @@ trait Symbols extends api.Symbols { self: SymbolTable => final override def isNonClassType = false final override def isAbstractType = false final override def isAliasType = false - + override def existentialBound = GenPolyType(this.typeParams, TypeBounds.upper(this.classBound)) override def sourceFile = @@ -2518,19 +2523,19 @@ trait Symbols extends api.Symbols { self: SymbolTable => } thisTypeCache } - + override def owner: Symbol = if (needsFlatClasses) rawowner.owner else rawowner override def name: TypeName = ( if (needsFlatClasses) { if (flatname eq null) flatname = nme.flattenedName(rawowner.name, rawname).toTypeName - + flatname } else rawname.toTypeName ) - + /** A symbol carrying the self type of the class as its type */ override def thisSym: Symbol = thissym @@ -2566,6 +2571,10 @@ trait Symbols extends api.Symbols { self: SymbolTable => override def sourceModule = if (isModuleClass) companionModule else NoSymbol + override def firstParamAccessor = + info.decls.find(m => (m hasFlag PARAMACCESSOR) && m.isMethod) getOrElse NoSymbol + + private[this] var childSet: Set[Symbol] = Set() override def children = childSet override def addChild(sym: Symbol) { childSet = childSet + sym } @@ -2713,7 +2722,7 @@ trait Symbols extends api.Symbols { self: SymbolTable => val syms1 = cloneSymbolsAtOwner(syms, owner) creator(syms1, tpe.substSym(syms, syms1)) } - + /** A deep map on a symbol's paramss. */ def mapParamss[T](sym: Symbol)(f: Symbol => T): List[List[T]] = mmap(sym.info.paramss)(f) diff --git a/src/compiler/scala/reflect/internal/transform/Erasure.scala b/src/compiler/scala/reflect/internal/transform/Erasure.scala index f0981d7141..f8dfd66fbe 100644 --- a/src/compiler/scala/reflect/internal/transform/Erasure.scala +++ b/src/compiler/scala/reflect/internal/transform/Erasure.scala @@ -65,19 +65,16 @@ trait Erasure { if (cls.owner.isClass) cls.owner.tpe else pre // why not cls.isNestedClass? } - protected def valueClassErasure(clazz: Symbol): Type = + def valueClassErasure(clazz: Symbol): Type = clazz.primaryConstructor.info.params.head.tpe - + protected def eraseInlineClassRef(clazz: Symbol): Type = scalaErasure(valueClassErasure(clazz)) - - protected def underlyingParamAccessor(clazz: Symbol) = - clazz.info.decls.find(_ hasFlag PARAMACCESSOR).get - + abstract class ErasureMap extends TypeMap { def mergeParents(parents: List[Type]): Type - def eraseNormalClassRef(pre: Type, clazz: Symbol): Type = + def eraseNormalClassRef(pre: Type, clazz: Symbol): Type = typeRef(apply(rebindInnerClass(pre, clazz)), clazz, List()) // #2585 def apply(tp: Type): Type = { @@ -95,7 +92,7 @@ trait Erasure { else if (sym == UnitClass) erasedTypeRef(BoxedUnitClass) else if (sym.isRefinementClass) apply(mergeParents(tp.parents)) else if (sym.isInlineClass) eraseInlineClassRef(sym) - else if (sym.isClass) eraseNormalClassRef(pre, sym) + else if (sym.isClass) eraseNormalClassRef(pre, sym) else apply(sym.info) // alias type or abstract type case PolyType(tparams, restpe) => apply(restpe) @@ -162,13 +159,11 @@ trait Erasure { log("Identified divergence between java/scala erasure:\n scala: " + old + "\n java: " + res) } res - } else if (sym.isMethodWithExtension || sym.isConstructor && sym.owner.isInlineClass) + } else if (sym.isTerm && sym.owner.isInlineClass) scalaErasureAvoiding(sym.owner, tp) - else if (sym.isValue && sym.owner.isMethodWithExtension) - scala.tools.nsc.util.trace("avoid unboxed: "+sym+"/"+sym.owner.owner+"/"+tp) { - scalaErasureAvoiding(sym.owner.owner, tp) - } - else + else if (sym.isValue && sym.owner.isMethodWithExtension) + scalaErasureAvoiding(sym.owner.owner, tp) + else scalaErasure(tp) } @@ -191,7 +186,7 @@ trait Erasure { def mergeParents(parents: List[Type]): Type = intersectionDominator(parents) } - + def scalaErasureAvoiding(clazz: Symbol, tpe: Type): Type = { tpe match { case PolyType(tparams, restpe) => diff --git a/src/compiler/scala/tools/nsc/Global.scala b/src/compiler/scala/tools/nsc/Global.scala index 281a2eb49b..3f6a0f8f73 100644 --- a/src/compiler/scala/tools/nsc/Global.scala +++ b/src/compiler/scala/tools/nsc/Global.scala @@ -154,7 +154,7 @@ class Global(var currentSettings: Settings, var reporter: Reporter) extends Symb /** Register top level class (called on entering the class) */ def registerTopLevelSym(sym: Symbol) {} - + // ------------------ Reporting ------------------------------------- // not deprecated yet, but a method called "error" imported into @@ -500,6 +500,13 @@ class Global(var currentSettings: Settings, var reporter: Reporter) extends Symb val runsRightAfter = Some("explicitouter") } with Erasure + // phaseName = "posterasure" + object postErasure extends { + val global: Global.this.type = Global.this + val runsAfter = List("erasure") + val runsRightAfter = Some("erasure") + } with PostErasure + // phaseName = "lazyvals" object lazyVals extends { final val FLAGS_PER_WORD = 32 @@ -659,6 +666,7 @@ class Global(var currentSettings: Settings, var reporter: Reporter) extends Symb specializeTypes -> "@specialized-driven class and method specialization", explicitOuter -> "this refs to outer pointers, translate patterns", erasure -> "erase types, add interfaces for traits", + postErasure -> "clean up erased inline classes", lazyVals -> "allocate bitmaps, translate lazy vals into lazified defs", lambdaLift -> "move nested functions to top level", constructors -> "move field definitions into constructors", @@ -703,18 +711,18 @@ class Global(var currentSettings: Settings, var reporter: Reporter) extends Symb private lazy val unitTimings = mutable.HashMap[CompilationUnit, Long]() withDefaultValue 0L // tracking time spent per unit private def unitTimingsFormatted(): String = { def toMillis(nanos: Long) = "%.3f" format nanos / 1000000d - + val formatter = new util.TableDef[(String, String)] { >> ("ms" -> (_._1)) >+ " " << ("path" -> (_._2)) } "" + ( - new formatter.Table(unitTimings.toList sortBy (-_._2) map { + new formatter.Table(unitTimings.toList sortBy (-_._2) map { case (unit, nanos) => (toMillis(nanos), unit.source.path) }) ) } - + protected def addToPhasesSet(sub: SubComponent, descr: String) { phasesSet += sub phasesDescMap(sub) = descr @@ -861,7 +869,7 @@ class Global(var currentSettings: Settings, var reporter: Reporter) extends Symb /** Counts for certain classes of warnings during this run. */ var deprecationWarnings: List[(Position, String)] = Nil var uncheckedWarnings: List[(Position, String)] = Nil - + /** A flag whether macro expansions failed */ var macroExpansionFailed = false @@ -1008,7 +1016,7 @@ class Global(var currentSettings: Settings, var reporter: Reporter) extends Symb } def cancel() { reporter.cancelled = true } - + private def currentProgress = (phasec * size) + unitc private def totalProgress = (phaseDescriptors.size - 1) * size // -1: drops terminal phase private def refreshProgress() = if (size > 0) progress(currentProgress, totalProgress) @@ -1175,12 +1183,12 @@ class Global(var currentSettings: Settings, var reporter: Reporter) extends Symb */ def compileUnits(units: List[CompilationUnit], fromPhase: Phase) { try compileUnitsInternal(units, fromPhase) - catch { case ex => + catch { case ex => globalError(supplementErrorMessage("uncaught exception during compilation: " + ex.getClass.getName)) throw ex } } - + private def compileUnitsInternal(units: List[CompilationUnit], fromPhase: Phase) { units foreach addUnit if (opt.profileAll) { diff --git a/src/compiler/scala/tools/nsc/ast/TreeInfo.scala b/src/compiler/scala/tools/nsc/ast/TreeInfo.scala index 81a6659b3c..9f361e5bcc 100644 --- a/src/compiler/scala/tools/nsc/ast/TreeInfo.scala +++ b/src/compiler/scala/tools/nsc/ast/TreeInfo.scala @@ -42,11 +42,11 @@ abstract class TreeInfo extends reflect.internal.TreeInfo { case ClassDef(_, `name`, _, _) :: Nil => true case _ => super.firstDefinesClassOrObject(trees, name) } - - def isInterface(mods: HasFlags, body: List[Tree]) = + + def isInterface(mods: HasFlags, body: List[Tree]) = mods.hasTraitFlag && (body forall isInterfaceMember) - def isAllowedInAnyTrait(stat: Tree): Boolean = stat match { + def isAllowedInUniversalTrait(stat: Tree): Boolean = stat match { case _: ValDef => false case Import(_, _) | EmptyTree => true case _: DefTree => true diff --git a/src/compiler/scala/tools/nsc/transform/Erasure.scala b/src/compiler/scala/tools/nsc/transform/Erasure.scala index fa64fbf48b..debf2e4b97 100644 --- a/src/compiler/scala/tools/nsc/transform/Erasure.scala +++ b/src/compiler/scala/tools/nsc/transform/Erasure.scala @@ -336,7 +336,7 @@ abstract class Erasure extends AddInterfaces class UnknownSig extends Exception override def eraseInlineClassRef(clazz: Symbol): Type = ErasedInlineType(clazz) - + /** The symbol's erased info. This is the type's erasure, except for the following symbols: * @@ -372,29 +372,47 @@ abstract class Erasure extends AddInterfaces override def newTyper(context: Context) = new Eraser(context) - /** An extractor object for boxed expressions + private def safeToRemoveUnbox(cls: Symbol): Boolean = + (cls == definitions.NullClass) || isBoxedValueClass(cls) + + /** An extractor object for unboxed expressions (maybe subsumed by posterasure?) */ + object Unboxed { + def unapply(tree: Tree): Option[Tree] = tree match { + case Apply(fn, List(arg)) if isUnbox(fn.symbol) && safeToRemoveUnbox(arg.tpe.typeSymbol) => + Some(arg) + case Apply( + TypeApply( + cast @ Select( + Apply( + sel @ Select(arg, acc), + List()), + asinstanceof), + List(tpt)), + List()) + if cast.symbol == Object_asInstanceOf && + tpt.tpe.typeSymbol.isInlineClass && + sel.symbol == tpt.tpe.typeSymbol.firstParamAccessor => + Some(arg) + case _ => + None + } + } + + /** An extractor object for boxed expressions (maybe subsumed by posterasure?) */ object Boxed { def unapply(tree: Tree): Option[Tree] = tree match { + case Apply(Select(New(tpt), nme.CONSTRUCTOR), List(arg)) if (tpt.tpe.typeSymbol.isInlineClass) => + Some(arg) case LabelDef(name, params, Boxed(rhs)) => Some(treeCopy.LabelDef(tree, name, params, rhs) setType rhs.tpe) - case Select(_, _) if tree.symbol == BoxedUnit_UNIT => - Some(Literal(Constant()) setPos tree.pos setType UnitClass.tpe) - case Block(List(unboxed), ret @ Select(_, _)) if ret.symbol == BoxedUnit_UNIT => - Some(if (unboxed.tpe.typeSymbol == UnitClass) tree - else Block(List(unboxed), Literal(Constant()) setPos tree.pos setType UnitClass.tpe)) - case Apply(fn, List(unboxed)) if isBox(fn.symbol) => - Some(unboxed) case _ => None } } - */ /** The modifier typer which retypes with erased types. */ class Eraser(_context: Context) extends Typer(_context) { - private def safeToRemoveUnbox(cls: Symbol): Boolean = - (cls == definitions.NullClass) || isBoxedValueClass(cls) - + private def isUnboxedType(tpe: Type) = tpe match { case ErasedInlineType(_) => true case _ => isPrimitiveValueClass(tpe.typeSymbol) @@ -403,24 +421,33 @@ abstract class Erasure extends AddInterfaces private def isUnboxedValueMember(sym: Symbol) = sym != NoSymbol && isPrimitiveValueClass(sym.owner) + private def box(tree: Tree, target: => String): Tree = { + val result = box1(tree) + log("boxing "+tree+":"+tree.tpe+" to "+target+" = "+result+":"+result.tpe) + result + } + /** Box `tree` of unboxed type */ - private def box(tree: Tree): Tree = tree match { + private def box1(tree: Tree): Tree = tree match { case LabelDef(name, params, rhs) => - val rhs1 = box(rhs) + val rhs1 = box1(rhs) treeCopy.LabelDef(tree, name, params, rhs1) setType rhs1.tpe case _ => val tree1 = tree.tpe match { case ErasedInlineType(clazz) => - util.trace("converting "+tree.tpe+" to "+valueClassErasure(clazz)+":")( - New(clazz, cast(tree, valueClassErasure(clazz))) - ) + tree match { + case Unboxed(arg) if arg.tpe.typeSymbol == clazz => + log("shortcircuiting unbox -> box "+arg); arg + case _ => + New(clazz, cast(tree, valueClassErasure(clazz))) + } case _ => tree.tpe.typeSymbol match { case UnitClass => if (treeInfo isExprSafeToInline tree) REF(BoxedUnit_UNIT) else BLOCK(tree, REF(BoxedUnit_UNIT)) case NothingClass => tree // a non-terminating expression doesn't need boxing - case x => + case x => assert(x != ArrayClass) tree match { /** Can't always remove a Box(Unbox(x)) combination because the process of boxing x @@ -440,13 +467,19 @@ abstract class Erasure extends AddInterfaces typedPos(tree.pos)(tree1) } + private def unbox(tree: Tree, pt: Type): Tree = { + val result = unbox1(tree, pt) + log("unboxing "+tree+":"+tree.tpe+" to "+pt+" = "+result+":"+result.tpe) + result + } + /** Unbox `tree` of boxed type to expected type `pt`. * * @param tree the given tree * @param pt the expected type. * @return the unboxed tree */ - private def unbox(tree: Tree, pt: Type): Tree = tree match { + private def unbox1(tree: Tree, pt: Type): Tree = tree match { /* case Boxed(unboxed) => println("unbox shorten: "+tree) // this never seems to kick in during build and test; therefore disabled. @@ -458,8 +491,15 @@ abstract class Erasure extends AddInterfaces case _ => val tree1 = pt match { case ErasedInlineType(clazz) => - val tree0 = adaptToType(tree, valueClassErasure(clazz)) - cast(Apply(Select(tree0, underlyingParamAccessor(clazz)), List()), pt) + tree match { + case Boxed(arg) if arg.tpe.isInstanceOf[ErasedInlineType] => + log("shortcircuiting box -> unbox "+arg) + arg + case _ => + log("not boxed: "+tree) + val tree0 = adaptToType(tree, clazz.tpe) + cast(Apply(Select(tree0, clazz.firstParamAccessor), List()), pt) + } case _ => pt.typeSymbol match { case UnitClass => @@ -498,9 +538,7 @@ abstract class Erasure extends AddInterfaces if (tree.tpe <:< pt) tree else if (isUnboxedType(tree.tpe) && !isUnboxedType(pt)) { - val tree1 = util.trace("boxing "+tree.tpe+" to "+pt+" = ")(box(tree)) - println(tree1.tpe) - adaptToType(tree1, pt) + adaptToType(box(tree, pt.toString), pt) } else if (tree.tpe.isInstanceOf[MethodType] && tree.tpe.params.isEmpty) { assert(tree.symbol.isStable, "adapt "+tree+":"+tree.tpe+" to "+pt) adaptToType(Apply(tree, List()) setPos tree.pos setType tree.tpe.resultType, pt) @@ -512,10 +550,6 @@ abstract class Erasure extends AddInterfaces cast(tree, pt) } - // @PP 1/25/2011: This is less inaccurate than it was (I removed - // BoxedAnyArray, asInstanceOf$erased, and other long ago eliminated symbols) - // but I do not think it yet describes the code beneath it. - /** Replace member references as follows: * * - `x == y` for == in class Any becomes `x equals y` with equals in class Object. @@ -532,7 +566,8 @@ abstract class Erasure extends AddInterfaces private def adaptMember(tree: Tree): Tree = { //Console.println("adaptMember: " + tree); tree match { - case Apply(TypeApply(sel @ Select(qual, name), List(targ)), List()) if tree.symbol == Any_asInstanceOf => + case Apply(TypeApply(sel @ Select(qual, name), List(targ)), List()) + if tree.symbol == Any_asInstanceOf || tree.symbol == Object_asInstanceOf => val qual1 = typedQualifier(qual, NOmode, ObjectClass.tpe) // need to have an expected type, see #3037 val qualClass = qual1.tpe.typeSymbol /* @@ -545,10 +580,11 @@ abstract class Erasure extends AddInterfaces */ if (isUnboxedType(targ.tpe)) unbox(qual1, targ.tpe) else tree - case Apply(TypeApply(sel @ Select(qual, name), List(targ)), List()) if tree.symbol == Any_isInstanceOf => + case Apply(TypeApply(sel @ Select(qual, name), List(targ)), List()) + if tree.symbol == Any_isInstanceOf || tree.symbol == Object_asInstanceOf => targ.tpe match { case ErasedInlineType(clazz) => targ.setType(scalaErasure(clazz.tpe)) - case _ => + case _ => } tree case Select(qual, name) => @@ -565,13 +601,12 @@ abstract class Erasure extends AddInterfaces adaptMember(atPos(tree.pos)(Select(qual, getMember(ObjectClass, name)))) else { var qual1 = typedQualifier(qual) - if ((isPrimitiveValueClass(qual1.tpe.typeSymbol) && !isUnboxedValueMember(tree.symbol))) { - println("boxing "+qual1.tpe+" to member "+tree.symbol) - qual1 = box(qual1) - } else if (!isPrimitiveValueClass(qual1.tpe.typeSymbol) && isUnboxedValueMember(tree.symbol)) + if ((isUnboxedType(qual1.tpe) && !isUnboxedValueMember(tree.symbol))) + qual1 = box(qual1, "owner "+tree.symbol.owner) + else if (!isUnboxedType(qual1.tpe) && isUnboxedValueMember(tree.symbol)) qual1 = unbox(qual1, tree.symbol.owner.tpe) - if (isPrimitiveValueClass(tree.symbol.owner) && !isPrimitiveValueClass(qual1.tpe.typeSymbol)) + if (isUnboxedValueMember(tree.symbol) && !isUnboxedType(qual1.tpe)) tree.symbol = NoSymbol else if (qual1.tpe.isInstanceOf[MethodType] && qual1.tpe.params.isEmpty) { assert(qual1.symbol.isStable, qual1.symbol); @@ -998,7 +1033,7 @@ abstract class Erasure extends AddInterfaces } else { tree } - + case Select(qual, name) => val owner = tree.symbol.owner // println("preXform: "+ (tree, tree.symbol, tree.symbol.owner, tree.symbol.owner.isRefinementClass)) @@ -1065,7 +1100,7 @@ abstract class Erasure extends AddInterfaces */ override def transform(tree: Tree): Tree = { val tree1 = preTransformer.transform(tree) - println("tree after pretransform: "+tree1) + log("tree after pretransform: "+tree1) atPhase(phase.next) { val tree2 = mixinTransformer.transform(tree1) debuglog("tree after addinterfaces: \n" + tree2) diff --git a/src/compiler/scala/tools/nsc/transform/ExtensionMethods.scala b/src/compiler/scala/tools/nsc/transform/ExtensionMethods.scala index 114ec721d8..e5f2d49d52 100644 --- a/src/compiler/scala/tools/nsc/transform/ExtensionMethods.scala +++ b/src/compiler/scala/tools/nsc/transform/ExtensionMethods.scala @@ -65,7 +65,7 @@ abstract class ExtensionMethods extends Transform with TypingTransformers { matching.head } - private def normalize(stpe: Type, clazz: Symbol): Type = stpe match { + private def normalize(stpe: Type, clazz: Symbol): Type = stpe match { case PolyType(tparams, restpe) => GenPolyType(tparams dropRight clazz.typeParams.length, normalize(restpe, clazz)) case MethodType(tparams, restpe) => @@ -123,7 +123,6 @@ abstract class ExtensionMethods extends Transform with TypingTransformers { def thisParamRef = gen.mkAttributedIdent(extensionMeth.info.params.head setPos extensionMeth.pos) val GenPolyType(extensionTpeParams, extensionMono) = extensionMeth.info val origTpeParams = origMeth.typeParams ::: currentOwner.typeParams - println("expanding "+tree+"/"+allParams(extensionMono)+"/"+extensionMeth.info) val extensionBody = rhs .substTreeSyms(origTpeParams, extensionTpeParams) .substTreeSyms(vparamss.flatten map (_.symbol), allParams(extensionMono).tail) diff --git a/src/compiler/scala/tools/nsc/typechecker/SyntheticMethods.scala b/src/compiler/scala/tools/nsc/typechecker/SyntheticMethods.scala index 3ee5bf601d..e0b4072fa1 100644 --- a/src/compiler/scala/tools/nsc/typechecker/SyntheticMethods.scala +++ b/src/compiler/scala/tools/nsc/typechecker/SyntheticMethods.scala @@ -39,6 +39,7 @@ trait SyntheticMethods extends ast.TreeDSL { /** Add the synthetic methods to case classes. */ def addSyntheticMethods(templ: Template, clazz0: Symbol, context: Context): Template = { + if (phase.erasedTypes) return templ @@ -47,8 +48,8 @@ trait SyntheticMethods extends ast.TreeDSL { newTyper( if (reporter.hasErrors) context makeSilent false else context ) ) import synthesizer._ - - if (clazz0 isSubClass AnyValClass) return { + + if (clazz0 == AnyValClass || isPrimitiveValueClass(clazz0)) return { if (clazz0.info member nme.getClass_ isDeferred) { val getClassMethod = createMethod(nme.getClass_, getClassReturnType(clazz.tpe)) { sym => // XXX dummy implementation for now @@ -96,8 +97,8 @@ trait SyntheticMethods extends ast.TreeDSL { def hasOverridingImplementation(meth: Symbol) = { val sym = clazz.info nonPrivateMember meth.name - sym.alternatives filterNot (_ eq meth) exists { m0 => - !m0.isDeferred && !m0.isSynthetic && (typeInClazz(m0) matches typeInClazz(meth)) + sym.alternatives exists { m0 => + (m0 ne meth) && !m0.isDeferred && !m0.isSynthetic && (m0.owner != AnyValClass) && (typeInClazz(m0) matches typeInClazz(meth)) } } def readConstantValue[T](name: String, default: T = null.asInstanceOf[T]): T = { @@ -122,13 +123,49 @@ trait SyntheticMethods extends ast.TreeDSL { // def productElementNameMethod = perElementMethod(nme.productElementName, StringClass.tpe)(x => LIT(x.name.toString)) + var syntheticCanEqual = false + /** The canEqual method for case classes. * def canEqual(that: Any) = that.isInstanceOf[This] */ - def canEqualMethod: Tree = ( - createMethod(nme.canEqual_, List(AnyClass.tpe), BooleanClass.tpe)(m => + def canEqualMethod: Tree = { + syntheticCanEqual = true + createMethod(nme.canEqual_, List(AnyClass.tpe), BooleanClass.tpe)(m => Ident(m.firstParam) IS_OBJ typeCaseType(clazz)) - ) + } + + /** (that.isInstanceOf[this.C]) + * where that is the given methods first parameter. + */ + def thatTest(eqmeth: Symbol): Tree = + gen.mkIsInstanceOf(Ident(eqmeth.firstParam), typeCaseType(clazz), true, false) + + /** (that.asInstanceOf[this.C]) + * where that is the given methods first parameter. + */ + def thatCast(eqmeth: Symbol): Tree = + gen.mkCast(Ident(eqmeth.firstParam), clazz.tpe) + + /** The equality method core for case classes and inline clases. + * 1+ args: + * (that.isInstanceOf[this.C]) && { + * val x$1 = that.asInstanceOf[this.C] + * (this.arg_1 == x$1.arg_1) && (this.arg_2 == x$1.arg_2) && ... && (x$1 canEqual this) + * } + * Drop canBuildFrom part if class is final and canBuildFrom is synthesized + */ + def equalsCore(eqmeth: Symbol, accessors: List[Symbol]) = { + val otherName = context.unit.freshTermName(clazz.name + "$") + val otherSym = eqmeth.newValue(otherName, eqmeth.pos, SYNTHETIC) setInfo clazz.tpe + val pairwise = accessors map (acc => fn(Select(This(clazz), acc), acc.tpe member nme.EQ, Select(Ident(otherSym), acc))) + val canEq = gen.mkMethodCall(otherSym, nme.canEqual_, Nil, List(This(clazz))) + val tests = if (clazz.isInlineClass || clazz.isFinal && syntheticCanEqual) pairwise else pairwise :+ canEq + + thatTest(eqmeth) AND Block( + ValDef(otherSym, thatCast(eqmeth)), + AND(tests: _*) + ) + } /** The equality method for case classes. * 0 args: @@ -141,34 +178,36 @@ trait SyntheticMethods extends ast.TreeDSL { * } * } */ - def equalsClassMethod: Tree = createMethod(nme.equals_, List(AnyClass.tpe), BooleanClass.tpe) { m => - val arg0 = Ident(m.firstParam) - val thatTest = gen.mkIsInstanceOf(arg0, typeCaseType(clazz), true, false) - val thatCast = gen.mkCast(arg0, clazz.tpe) - - def argsBody: Tree = { - val otherName = context.unit.freshTermName(clazz.name + "$") - val otherSym = m.newValue(otherName, m.pos, SYNTHETIC) setInfo clazz.tpe - val pairwise = accessors map (acc => fn(Select(This(clazz), acc), acc.tpe member nme.EQ, Select(Ident(otherSym), acc))) - val canEq = gen.mkMethodCall(otherSym, nme.canEqual_, Nil, List(This(clazz))) - def block = Block(ValDef(otherSym, thatCast), AND(pairwise :+ canEq: _*)) - - (This(clazz) ANY_EQ arg0) OR { - thatTest AND Block( - ValDef(otherSym, thatCast), - AND(pairwise :+ canEq: _*) - ) - } - } + def equalsCaseClassMethod: Tree = createMethod(nme.equals_, List(AnyClass.tpe), BooleanClass.tpe) { m => if (accessors.isEmpty) - thatTest AND ((thatCast DOT nme.canEqual_)(This(clazz))) + if (clazz.isFinal) thatTest(m) + else thatTest(m) AND ((thatCast(m) DOT nme.canEqual_)(This(clazz))) else - argsBody + (This(clazz) ANY_EQ Ident(m.firstParam)) OR equalsCore(m, accessors) + } + + /** The equality method for value classes + * def equals(that: Any) = (this.asInstanceOf[AnyRef]) eq that.asInstanceOf[AnyRef]) || { + * (that.isInstanceOf[this.C]) && { + * val x$1 = that.asInstanceOf[this.C] + * (this.underlying == that.underlying + */ + def equalsInlineClassMethod: Tree = createMethod(nme.equals_, List(AnyClass.tpe), BooleanClass.tpe) { m => + equalsCore(m, List(clazz.firstParamAccessor)) + } + + /** The hashcode method for value classes + * def hashCode(): Int = this.underlying.hashCode + */ + def hashCodeInlineClassMethod: Tree = createMethod(nme.hashCode_, Nil, IntClass.tpe) { m => + Select( + Select(This(clazz), clazz.firstParamAccessor), + nme.hashCode_) } /** The _1, _2, etc. methods to implement ProductN. */ - def productNMethods = { + def productNMethods = { val accs = accessors.toIndexedSeq 1 to arity map (num => productProj(arity, num) -> (() => projectionMethod(accs(num - 1), num))) } @@ -190,7 +229,7 @@ trait SyntheticMethods extends ast.TreeDSL { def caseClassMethods = productMethods ++ productNMethods ++ Seq( Object_hashCode -> (() => forwardToRuntime(Object_hashCode)), Object_toString -> (() => forwardToRuntime(Object_toString)), - Object_equals -> (() => equalsClassMethod) + Object_equals -> (() => equalsCaseClassMethod) ) def caseObjectMethods = productMethods ++ Seq( @@ -200,6 +239,11 @@ trait SyntheticMethods extends ast.TreeDSL { // Object_equals -> (() => createMethod(Object_equals)(m => This(clazz) ANY_EQ Ident(m.firstParam))) ) + def inlineClassMethods = List( + Any_hashCode -> (() => hashCodeInlineClassMethod), + Any_equals -> (() => equalsInlineClassMethod) + ) + /** If you serialize a singleton and then deserialize it twice, * you will have two instances of your singleton unless you implement * readResolve. Here it is implemented for all objects which have @@ -214,10 +258,12 @@ trait SyntheticMethods extends ast.TreeDSL { def synthesize(): List[Tree] = { val methods = ( - if (!clazz.isCase) Nil + if (clazz.isInlineClass) inlineClassMethods + else if (!clazz.isCase) Nil else if (clazz.isModuleClass) caseObjectMethods else caseClassMethods ) + def impls = for ((m, impl) <- methods ; if !hasOverridingImplementation(m)) yield impl() def extras = ( if (needsReadResolve) { diff --git a/src/compiler/scala/tools/nsc/typechecker/Typers.scala b/src/compiler/scala/tools/nsc/typechecker/Typers.scala index e6a3ddbe31..008a2e1764 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Typers.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Typers.scala @@ -1193,6 +1193,27 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser { } } + private def validateInlineClass(clazz: Symbol, body: List[Tree]) = { + if (clazz.isTrait) + unit.error(clazz.pos, "Only classes (not traits) are allowed to extend AnyVal") + if (!clazz.isStatic) + unit.error(clazz.pos, "Value class may not be a "+ + (if (clazz.owner.isTerm) "local class" else "member of another class")) + clazz.info.decls.toList.filter(acc => acc.isMethod && (acc hasFlag PARAMACCESSOR)) match { + case List(acc) => + def isUnderlyingAcc(sym: Symbol) = + 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) + case x => + unit.error(clazz.pos, "Value class needs to have exactly one public val parameter") + } + } + def parentTypes(templ: Template): List[Tree] = if (templ.parents.isEmpty) List(TypeTree(AnyRefClass.tpe)) else try { @@ -1209,7 +1230,7 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser { supertpt = TypeTree(supertpt1.tpe.firstParent) setPos supertpt.pos.focus } } - if (supertpt.tpe.typeSymbol == AnyClass && firstParent.isTrait && firstParent != AnyValClass) + if (supertpt.tpe.typeSymbol == AnyClass && firstParent.isTrait) supertpt.tpe = AnyRefClass.tpe // Determine @@ -1300,7 +1321,7 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser { else xs ) } - + fixDuplicates(supertpt :: mixins) mapConserve (tpt => checkNoEscaping.privates(clazz, tpt)) } catch { @@ -1418,7 +1439,7 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser { val impl2 = finishMethodSynthesis(impl1, clazz, context) if (clazz.isTrait && clazz.info.parents.nonEmpty && clazz.info.firstParent.typeSymbol == AnyClass) for (stat <- impl2.body) - if (!treeInfo.isAllowedInAnyTrait(stat)) + if (!treeInfo.isAllowedInUniversalTrait(stat)) unit.error(stat.pos, "this statement is not allowed in trait extending from class Any: "+stat) if ((clazz != ClassfileAnnotationClass) && (clazz isNonBottomSubClass ClassfileAnnotationClass)) @@ -1536,6 +1557,7 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser { if ((clazz isSubClass ClassfileAnnotationClass) && !clazz.owner.isPackageClass) unit.error(clazz.pos, "inner classes cannot be classfile annotations") + if (!phase.erasedTypes && !clazz.info.resultType.isError) // @S: prevent crash for duplicated type members checkFinitary(clazz.info.resultType.asInstanceOf[ClassInfoType]) @@ -1544,6 +1566,10 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser { else templ.body flatMap rewrappingWrapperTrees(namer.finishGetterSetter(Typer.this, _)) val body1 = typedStats(body, templ.symbol) + + if (clazz.isInlineClass) + validateInlineClass(clazz, body1) + treeCopy.Template(templ, parents1, self1, body1) setType clazz.tpe } diff --git a/test/files/neg/anyval-anyref-parent.check b/test/files/neg/anyval-anyref-parent.check index be895867ff..e1903f5fcc 100644 --- a/test/files/neg/anyval-anyref-parent.check +++ b/test/files/neg/anyval-anyref-parent.check @@ -1,14 +1,23 @@ +anyval-anyref-parent.scala:2: error: Only classes (not traits) are allowed to extend AnyVal +trait Foo2 extends AnyVal // fail + ^ anyval-anyref-parent.scala:5: error: Any does not have a constructor class Bar1 extends Any // fail ^ -anyval-anyref-parent.scala:9: error: illegal inheritance; superclass Any +anyval-anyref-parent.scala:6: error: Value class needs to have exactly one public val parameter +class Bar2(x: Int) extends AnyVal // fail + ^ +anyval-anyref-parent.scala:10: error: illegal inheritance; superclass Any is not a subclass of the superclass Object of the mixin trait Immutable trait Foo4 extends Any with Immutable // fail ^ -anyval-anyref-parent.scala:10: error: illegal inheritance; superclass AnyVal +anyval-anyref-parent.scala:11: error: illegal inheritance; superclass AnyVal is not a subclass of the superclass Object of the mixin trait Immutable trait Foo5 extends AnyVal with Immutable // fail ^ -three errors found +anyval-anyref-parent.scala:11: error: Only classes (not traits) are allowed to extend AnyVal +trait Foo5 extends AnyVal with Immutable // fail + ^ +6 errors found diff --git a/test/files/neg/anyval-anyref-parent.scala b/test/files/neg/anyval-anyref-parent.scala index 08568487a9..f927992e59 100644 --- a/test/files/neg/anyval-anyref-parent.scala +++ b/test/files/neg/anyval-anyref-parent.scala @@ -1,10 +1,11 @@ trait Foo1 extends Any -trait Foo2 extends AnyVal +trait Foo2 extends AnyVal // fail trait Foo3 extends AnyRef class Bar1 extends Any // fail -@inline class Bar2 extends AnyVal -class Bar3 extends AnyRef +class Bar2(x: Int) extends AnyVal // fail +class Bar3(val x: Int) extends AnyVal // fail +class Bar4 extends AnyRef trait Foo4 extends Any with Immutable // fail trait Foo5 extends AnyVal with Immutable // fail diff --git a/test/files/neg/t3222.check b/test/files/neg/t3222.check index b1e1e50448..e724024f45 100644 --- a/test/files/neg/t3222.check +++ b/test/files/neg/t3222.check @@ -1,7 +1,7 @@ -t3222.scala:1: error: not found: type B -@throws(classOf[B]) - ^ t3222.scala:4: error: not found: type D def foo(@throws(classOf[D]) x: Int) {} ^ +t3222.scala:1: error: not found: type B +@throws(classOf[B]) + ^ two errors found diff --git a/test/files/pos/anyval-children.scala b/test/files/pos/anyval-children.scala deleted file mode 100644 index 4ef10a094f..0000000000 --- a/test/files/pos/anyval-children.scala +++ /dev/null @@ -1 +0,0 @@ -@inline class Bippy extends AnyVal \ No newline at end of file diff --git a/test/files/run/Meter.scala b/test/files/run/Meter.scala index 0c30ddd41e..5700025880 100644 --- a/test/files/run/Meter.scala +++ b/test/files/run/Meter.scala @@ -10,10 +10,29 @@ trait Printable extends Any { def print: Unit = Console.print(this) } object Test extends App { + { + val x: Meter = new Meter(1) + val a: Object = x.asInstanceOf[Object] + val y: Meter = a.asInstanceOf[Meter] + + val u: Double = 1 + val b: Object = u.asInstanceOf[Object] + val v: Double = b.asInstanceOf[Double] + } + val x = new Meter(1) + val y = x println((x + x) / x) println((x + x) / 0.5) println((x < x).toString) - + + println("x.hashCode: "+x.hashCode) + println("x == 1: "+(x == 1)) + println("x == y: "+(x == y)) + assert(x.hashCode == (1.0).hashCode) + + val a: Any = x + val b: Any = y + println("a == b: "+(a == b)) } diff --git a/test/files/run/programmatic-main.check b/test/files/run/programmatic-main.check index b5a54f5ea7..9ddd4a6e14 100644 --- a/test/files/run/programmatic-main.check +++ b/test/files/run/programmatic-main.check @@ -13,17 +13,18 @@ specialize 11 @specialized-driven class and method specialization explicitouter 12 this refs to outer pointers, translate patterns erasure 13 erase types, add interfaces for traits - lazyvals 14 allocate bitmaps, translate lazy vals into lazified defs - lambdalift 15 move nested functions to top level - constructors 16 move field definitions into constructors - flatten 17 eliminate inner classes - mixin 18 mixin composition - cleanup 19 platform-specific cleanups, generate reflective calls - icode 20 generate portable intermediate code - inliner 21 optimization: do inlining -inlineExceptionHandlers 22 optimization: inline exception handlers - closelim 23 optimization: eliminate uncalled closures - dce 24 optimization: eliminate dead code - jvm 25 generate JVM bytecode - terminal 26 The last phase in the compiler chain + posterasure 14 clean up erased inline classes + lazyvals 15 allocate bitmaps, translate lazy vals into lazified defs + lambdalift 16 move nested functions to top level + constructors 17 move field definitions into constructors + flatten 18 eliminate inner classes + mixin 19 mixin composition + cleanup 20 platform-specific cleanups, generate reflective calls + icode 21 generate portable intermediate code + inliner 22 optimization: do inlining +inlineExceptionHandlers 23 optimization: inline exception handlers + closelim 24 optimization: eliminate uncalled closures + dce 25 optimization: eliminate dead code + jvm 26 generate JVM bytecode + terminal 27 The last phase in the compiler chain -- cgit v1.2.3 From 436f141d21db0b5fa88adc9ada7059e992be58cc Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Mon, 13 Feb 2012 09:02:38 +0100 Subject: Added missing files from last commit --- .../scala/tools/nsc/transform/PostErasure.scala | 61 ++++++++++++++++++++++ test/files/neg/anytrait.check | 7 +++ test/files/neg/anytrait.scala | 10 ++++ test/files/run/Meter.check | 7 +++ 4 files changed, 85 insertions(+) create mode 100644 src/compiler/scala/tools/nsc/transform/PostErasure.scala create mode 100644 test/files/neg/anytrait.check create mode 100644 test/files/neg/anytrait.scala create mode 100644 test/files/run/Meter.check (limited to 'test/files') diff --git a/src/compiler/scala/tools/nsc/transform/PostErasure.scala b/src/compiler/scala/tools/nsc/transform/PostErasure.scala new file mode 100644 index 0000000000..1efa9ef3d5 --- /dev/null +++ b/src/compiler/scala/tools/nsc/transform/PostErasure.scala @@ -0,0 +1,61 @@ +package scala.tools.nsc +package transform + +trait PostErasure extends InfoTransform with TypingTransformers { + + val global: Global + import global._ + import definitions._ + + val phaseName: String = "posterasure" + + def newTransformer(unit: CompilationUnit): Transformer = new PostErasureTransformer(unit) + override def changesBaseClasses = false + + object elimErasedInline extends TypeMap { + def apply(tp: Type) = tp match { + case ErasedInlineType(clazz) => erasure.valueClassErasure(clazz) + case _ => mapOver(tp) + } + } + + def transformInfo(sym: Symbol, tp: Type) = elimErasedInline(tp) + + class PostErasureTransformer(unit: CompilationUnit) extends TypingTransformer(unit) { + + override def transform(tree: Tree) = + super.transform(tree) setType elimErasedInline(tree.tpe) match { + case // new C(arg).underlying ==> arg + Apply(sel @ Select( + Apply(Select(New(tpt), nme.CONSTRUCTOR), List(arg)), + acc), List()) + if atPhase(currentRun.erasurePhase) { + tpt.tpe.typeSymbol.isInlineClass && + sel.symbol == tpt.tpe.typeSymbol.firstParamAccessor + } => + if (settings.debug.value) log("Removing "+tree+" -> "+arg) + arg + case // new C(arg1) == new C(arg2) ==> arg1 == arg2 + Apply(sel @ Select( + Apply(Select(New(tpt1), nme.CONSTRUCTOR), List(arg1)), + cmp), + List(Apply(Select(New(tpt2), nme.CONSTRUCTOR), List(arg2)))) + if atPhase(currentRun.erasurePhase) { + tpt1.tpe.typeSymbol.isInlineClass && + (cmp == nme.EQ || cmp == nme.NE) && + tpt2.tpe.typeSymbol == tpt1.tpe.typeSymbol + } => + val result = Apply(Select(arg1, cmp) setPos sel.pos, List(arg2)) setPos tree.pos + log("shortcircuiting equality "+tree+" -> "+result) + localTyper.typed(result) + + case // arg.asInstanceOf[T] ==> arg if arg.tpe == T + Apply(TypeApply(cast @ Select(arg, asinstanceof), List(tpt)), List()) + if cast.symbol == Object_asInstanceOf && arg.tpe =:= tpt.tpe => // !!! <:< ? + if (settings.debug.value) log("Shortening "+tree+" -> "+arg) + arg + case tree1 => + tree1 + } + } +} \ No newline at end of file diff --git a/test/files/neg/anytrait.check b/test/files/neg/anytrait.check new file mode 100644 index 0000000000..99c24b85a0 --- /dev/null +++ b/test/files/neg/anytrait.check @@ -0,0 +1,7 @@ +anytrait.scala:3: error: this statement is not allowed in trait extending from class Any: private[this] var x: Int = 1 + var x = 1 + ^ +anytrait.scala:5: error: this statement is not allowed in trait extending from class Any: T.this.x_=(T.this.x.+(1)) + { x += 1 } + ^ +two errors found diff --git a/test/files/neg/anytrait.scala b/test/files/neg/anytrait.scala new file mode 100644 index 0000000000..1501486105 --- /dev/null +++ b/test/files/neg/anytrait.scala @@ -0,0 +1,10 @@ +trait T extends Any { + + var x = 1 + + { x += 1 } + + type T = Int + + val y: T +} diff --git a/test/files/run/Meter.check b/test/files/run/Meter.check new file mode 100644 index 0000000000..a936073489 --- /dev/null +++ b/test/files/run/Meter.check @@ -0,0 +1,7 @@ +2.0 +4.0m +false +x.hashCode: 1072693248 +x == 1: false +x == y: true +a == b: true -- cgit v1.2.3 From 087aee792e20ccf339be1a14349b7fbde647d394 Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Mon, 13 Feb 2012 11:39:25 +0100 Subject: Setting up things to demonstrate a swallowed type error in manifest generation. --- .../scala/tools/nsc/typechecker/Contexts.scala | 7 ++++--- .../scala/tools/nsc/typechecker/Implicits.scala | 20 ++++++++++++-------- src/compiler/scala/tools/nsc/typechecker/Infer.scala | 12 ++++++++---- test/files/run/Meter.scala | 2 ++ 4 files changed, 26 insertions(+), 15 deletions(-) (limited to 'test/files') diff --git a/src/compiler/scala/tools/nsc/typechecker/Contexts.scala b/src/compiler/scala/tools/nsc/typechecker/Contexts.scala index b5afd681d2..c6f2bffabe 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Contexts.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Contexts.scala @@ -21,7 +21,7 @@ trait Contexts { self: Analyzer => outer = this enclClass = this enclMethod = this - + override def nextEnclosing(p: Context => Boolean): Context = this override def enclosingContextChain: List[Context] = Nil override def implicitss: List[List[ImplicitInfo]] = Nil @@ -177,7 +177,7 @@ trait Contexts { self: Analyzer => buffer.clear() current } - + def logError(err: AbsTypeError) = buffer += err def withImplicitsDisabled[T](op: => T): T = { @@ -237,7 +237,7 @@ trait Contexts { self: Analyzer => c.implicitsEnabled = true c } - + def makeNewImport(sym: Symbol): Context = makeNewImport(gen.mkWildcardImport(sym)) @@ -308,6 +308,7 @@ trait Contexts { self: Analyzer => unit.error(pos, if (checking) "\n**** ERROR DURING INTERNAL CHECKING ****\n" + msg else msg) def issue(err: AbsTypeError) { + if (settings.debug.value) println("issuing error: "+err) if (reportErrors) unitError(err.errPos, addDiagString(err.errMsg)) else if (bufferErrors) { buffer += err } else throw new TypeError(err.errPos, err.errMsg) diff --git a/src/compiler/scala/tools/nsc/typechecker/Implicits.scala b/src/compiler/scala/tools/nsc/typechecker/Implicits.scala index d73689622f..7d1198a4a2 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Implicits.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Implicits.scala @@ -215,7 +215,7 @@ trait Implicits { object HasMethodMatching { val dummyMethod = NoSymbol.newTermSymbol(newTermName("typer$dummy")) def templateArgType(argtpe: Type) = new BoundedWildcardType(TypeBounds.lower(argtpe)) - + def apply(name: Name, argtpes: List[Type], restpe: Type): Type = { val mtpe = MethodType(dummyMethod.newSyntheticValueParams(argtpes map templateArgType), restpe) memberWildcardType(name, mtpe) @@ -571,7 +571,7 @@ trait Implicits { else { val tvars = undetParams map freshVar def ptInstantiated = pt.instantiateTypeParams(undetParams, tvars) - + printInference("[search] considering %s (pt contains %s) trying %s against pt=%s".format( if (undetParams.isEmpty) "no tparams" else undetParams.map(_.name).mkString(", "), typeVarsInType(ptInstantiated) filterNot (_.isGround) match { case Nil => "no tvars" ; case tvs => tvs.mkString(", ") }, @@ -594,7 +594,7 @@ trait Implicits { // we must be conservative in leaving type params in undetparams // prototype == WildcardType: want to remove all inferred Nothings val AdjustedTypeArgs(okParams, okArgs) = adjustTypeArgs(undetParams, tvars, targs) - + val subst: TreeTypeSubstituter = if (okParams.isEmpty) EmptyTreeTypeSubstituter else { @@ -621,7 +621,7 @@ trait Implicits { case Apply(TypeApply(fun, args), _) => typedTypeApply(itree2, EXPRmode, fun, args) // t2421c case t => t } - + if (context.hasErrors) fail("typing TypeApply reported errors for the implicit tree") else { @@ -780,13 +780,13 @@ trait Implicits { val newPending = undoLog undo { is filterNot (alt => alt == i || { try improves(i, alt) - catch { - case e: CyclicReference => + catch { + case e: CyclicReference => if (printInfers) { println(i+" discarded because cyclic reference occurred") e.printStackTrace() } - true + true } }) } @@ -1094,7 +1094,11 @@ trait Implicits { /** Creates a tree that calls the factory method called constructor in object reflect.Manifest */ def manifestFactoryCall(constructor: String, tparg: Type, args: Tree*): Tree = if (args contains EmptyTree) EmptyTree - else typedPos(tree.pos.focus)(gen.mkManifestFactoryCall(full, constructor, tparg, args.toList)) + else typedPos(tree.pos.focus) { + val mani = gen.mkManifestFactoryCall(full, constructor, tparg, args.toList) + if (settings.debug.value) println("generated manifest: "+mani) // DEBUG + mani + } /** Creates a tree representing one of the singleton manifests.*/ def findSingletonManifest(name: String) = typedPos(tree.pos.focus) { diff --git a/src/compiler/scala/tools/nsc/typechecker/Infer.scala b/src/compiler/scala/tools/nsc/typechecker/Infer.scala index b97fbebec2..94fa485e14 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Infer.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Infer.scala @@ -196,6 +196,10 @@ trait Infer { /* -- Error Messages --------------------------------------------------- */ def setError[T <: Tree](tree: T): T = { + if (settings.debug.value) { // DEBUG + println("set error: "+tree); + throw new Error() + } def name = newTermName("") def errorClass = if (context.reportErrors) context.owner.newErrorClass(name.toTypeName) else stdErrorClass def errorValue = if (context.reportErrors) context.owner.newErrorValue(name) else stdErrorValue @@ -210,9 +214,9 @@ trait Infer { def getContext = context def issue(err: AbsTypeError): Unit = context.issue(err) - - def isPossiblyMissingArgs(found: Type, req: Type) = (found.resultApprox ne found) && isWeaklyCompatible(found.resultApprox, req) - + + def isPossiblyMissingArgs(found: Type, req: Type) = (found.resultApprox ne found) && isWeaklyCompatible(found.resultApprox, req) + def explainTypes(tp1: Type, tp2: Type) = withDisambiguation(List(), tp1, tp2)(global.explainTypes(tp1, tp2)) @@ -465,7 +469,7 @@ trait Infer { */ def adjustTypeArgs(tparams: List[Symbol], tvars: List[TypeVar], targs: List[Type], restpe: Type = WildcardType): AdjustedTypeArgs.Result = { val buf = AdjustedTypeArgs.Result.newBuilder[Symbol, Option[Type]] - + foreach3(tparams, tvars, targs) { (tparam, tvar, targ) => val retract = ( targ.typeSymbol == NothingClass // only retract Nothings diff --git a/test/files/run/Meter.scala b/test/files/run/Meter.scala index 5700025880..e4d9abaa21 100644 --- a/test/files/run/Meter.scala +++ b/test/files/run/Meter.scala @@ -35,4 +35,6 @@ object Test extends App { val a: Any = x val b: Any = y println("a == b: "+(a == b)) + + val arr = Array(x, y + x) } -- cgit v1.2.3 From ee560229d1be78294b17ba4b0b6f36e8dd68d376 Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Mon, 13 Feb 2012 14:27:41 +0100 Subject: Fixing problems with generation of isInstanceOf, classOf. --- src/compiler/scala/tools/nsc/transform/Erasure.scala | 8 ++++++-- src/library/scala/reflect/ClassManifest.scala | 8 ++++---- test/files/run/Meter.scala | 1 + 3 files changed, 11 insertions(+), 6 deletions(-) (limited to 'test/files') diff --git a/src/compiler/scala/tools/nsc/transform/Erasure.scala b/src/compiler/scala/tools/nsc/transform/Erasure.scala index debf2e4b97..7eb819f058 100644 --- a/src/compiler/scala/tools/nsc/transform/Erasure.scala +++ b/src/compiler/scala/tools/nsc/transform/Erasure.scala @@ -583,7 +583,7 @@ abstract class Erasure extends AddInterfaces case Apply(TypeApply(sel @ Select(qual, name), List(targ)), List()) if tree.symbol == Any_isInstanceOf || tree.symbol == Object_asInstanceOf => targ.tpe match { - case ErasedInlineType(clazz) => targ.setType(scalaErasure(clazz.tpe)) + case ErasedInlineType(clazz) => targ.setType(clazz.tpe) case _ => } tree @@ -1065,7 +1065,11 @@ abstract class Erasure extends AddInterfaces case Literal(ct) if ct.tag == ClassTag && ct.typeValue.typeSymbol != definitions.UnitClass => - treeCopy.Literal(tree, Constant(erasure(NoSymbol, ct.typeValue))) + val erased = ct.typeValue match { + case TypeRef(pre, clazz, args) if clazz.isInlineClass => typeRef(pre, clazz, List()) + case tpe => erasure(NoSymbol, tpe) + } + treeCopy.Literal(tree, Constant(erased)) case _ => tree diff --git a/src/library/scala/reflect/ClassManifest.scala b/src/library/scala/reflect/ClassManifest.scala index 466b57dea7..6342979add 100644 --- a/src/library/scala/reflect/ClassManifest.scala +++ b/src/library/scala/reflect/ClassManifest.scala @@ -205,18 +205,18 @@ object ClassManifest { * pass varargs as arrays into this, we get an infinitely recursive call * to boxArray. (Besides, having a separate case is more efficient) */ - def classType[T <: AnyRef](clazz: jClass[_]): ClassManifest[T] = + def classType[T](clazz: jClass[_]): ClassManifest[T] = new ClassTypeManifest[T](None, clazz, Nil) /** ClassManifest for the class type `clazz[args]`, where `clazz` is * a top-level or static class and `args` are its type arguments */ - def classType[T <: AnyRef](clazz: jClass[_], arg1: OptManifest[_], args: OptManifest[_]*): ClassManifest[T] = + def classType[T](clazz: jClass[_], arg1: OptManifest[_], args: OptManifest[_]*): ClassManifest[T] = new ClassTypeManifest[T](None, clazz, arg1 :: args.toList) /** ClassManifest for the class type `clazz[args]`, where `clazz` is * a class with non-package prefix type `prefix` and type arguments `args`. */ - def classType[T <: AnyRef](prefix: OptManifest[_], clazz: jClass[_], args: OptManifest[_]*): ClassManifest[T] = + def classType[T](prefix: OptManifest[_], clazz: jClass[_], args: OptManifest[_]*): ClassManifest[T] = new ClassTypeManifest[T](Some(prefix), clazz, args.toList) def arrayType[T](arg: OptManifest[_]): ClassManifest[Array[T]] = arg match { @@ -249,7 +249,7 @@ object ClassManifest { /** Manifest for the class type `clazz[args]`, where `clazz` is * a top-level or static class: todo: we should try to merge this with Manifest's class */ -private class ClassTypeManifest[T <: AnyRef]( +private class ClassTypeManifest[T]( prefix: Option[OptManifest[_]], val erasure: jClass[_], override val typeArguments: List[OptManifest[_]]) extends ClassManifest[T] diff --git a/test/files/run/Meter.scala b/test/files/run/Meter.scala index e4d9abaa21..0db917aeee 100644 --- a/test/files/run/Meter.scala +++ b/test/files/run/Meter.scala @@ -25,6 +25,7 @@ object Test extends App { println((x + x) / x) println((x + x) / 0.5) println((x < x).toString) + println("x.isInstanceOf[Meter]: "+x.isInstanceOf[Meter]) println("x.hashCode: "+x.hashCode) -- cgit v1.2.3 From ea96b48d9274e90b64b66e51507460c004c01643 Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Tue, 14 Feb 2012 18:37:56 +0100 Subject: Changed erasure behavior of arrays to use always boxed representation. Conflicts: test/files/run/Meter.scala --- .../scala/reflect/internal/transform/Erasure.scala | 98 ++++++++++++---------- .../scala/tools/nsc/transform/Erasure.scala | 2 +- src/library/scala/reflect/api/Types.scala | 2 +- test/files/run/Meter.scala | 41 +++++++++ 4 files changed, 95 insertions(+), 48 deletions(-) (limited to 'test/files') diff --git a/src/compiler/scala/reflect/internal/transform/Erasure.scala b/src/compiler/scala/reflect/internal/transform/Erasure.scala index 2be7ec3190..bd6a77fb07 100644 --- a/src/compiler/scala/reflect/internal/transform/Erasure.scala +++ b/src/compiler/scala/reflect/internal/transform/Erasure.scala @@ -71,50 +71,56 @@ trait Erasure { abstract class ErasureMap extends TypeMap { def mergeParents(parents: List[Type]): Type + def eraseNormalClassRef(pre: Type, clazz: Symbol): Type = + typeRef(apply(rebindInnerClass(pre, clazz)), clazz, List()) // #2585 + protected def eraseInlineClassRef(clazz: Symbol): Type = scalaErasure(underlyingOfValueClass(clazz)) - def apply(tp: Type): Type = { - tp match { - case ConstantType(_) => - tp - case st: SubType => - apply(st.supertype) - case TypeRef(pre, sym, args) => - if (sym == ArrayClass) - if (unboundedGenericArrayLevel(tp) == 1) ObjectClass.tpe - else if (args.head.typeSymbol.isBottomClass) ObjectArray - else typeRef(apply(pre), sym, args map this) - else if (sym == AnyClass || sym == AnyValClass || sym == SingletonClass || sym == NotNullClass) erasedTypeRef(ObjectClass) - else if (sym == UnitClass) erasedTypeRef(BoxedUnitClass) - else if (sym.isRefinementClass) apply(mergeParents(tp.parents)) - else if (sym.isInlineClass) eraseInlineClassRef(sym) - else if (sym.isClass) typeRef(apply(rebindInnerClass(pre, sym)), sym, List()) // #2585 - else apply(sym.info) // alias type or abstract type - case PolyType(tparams, restpe) => - apply(restpe) - case ExistentialType(tparams, restpe) => - apply(restpe) - case mt @ MethodType(params, restpe) => - MethodType( - cloneSymbolsAndModify(params, ErasureMap.this), - if (restpe.typeSymbol == UnitClass) erasedTypeRef(UnitClass) - // this replaces each typeref that refers to an argument - // by the type `p.tpe` of the actual argument p (p in params) - else apply(mt.resultType(params map (_.tpe)))) - case RefinedType(parents, decls) => - apply(mergeParents(parents)) - case AnnotatedType(_, atp, _) => - apply(atp) - case ClassInfoType(parents, decls, clazz) => - ClassInfoType( - if (clazz == ObjectClass || isPrimitiveValueClass(clazz)) Nil - else if (clazz == ArrayClass) List(erasedTypeRef(ObjectClass)) - else removeLaterObjects(parents map this), - decls, clazz) - case _ => - mapOver(tp) - } + def apply(tp: Type): Type = tp match { + case ConstantType(_) => + tp + case st: SubType => + apply(st.supertype) + case TypeRef(pre, sym, args) => + if (sym == ArrayClass) + if (unboundedGenericArrayLevel(tp) == 1) ObjectClass.tpe + else if (args.head.typeSymbol.isBottomClass) ObjectArray + else typeRef(apply(pre), sym, args map applyInArray) + else if (sym == AnyClass || sym == AnyValClass || sym == SingletonClass || sym == NotNullClass) erasedTypeRef(ObjectClass) + else if (sym == UnitClass) erasedTypeRef(BoxedUnitClass) + else if (sym.isRefinementClass) apply(mergeParents(tp.parents)) + else if (sym.isInlineClass) eraseInlineClassRef(sym) + else if (sym.isClass) eraseNormalClassRef(pre, sym) + else apply(sym.info) // alias type or abstract type + case PolyType(tparams, restpe) => + apply(restpe) + case ExistentialType(tparams, restpe) => + apply(restpe) + case mt @ MethodType(params, restpe) => + MethodType( + cloneSymbolsAndModify(params, ErasureMap.this), + if (restpe.typeSymbol == UnitClass) erasedTypeRef(UnitClass) + // this replaces each typeref that refers to an argument + // by the type `p.tpe` of the actual argument p (p in params) + else apply(mt.resultType(params map (_.tpe)))) + case RefinedType(parents, decls) => + apply(mergeParents(parents)) + case AnnotatedType(_, atp, _) => + apply(atp) + case ClassInfoType(parents, decls, clazz) => + ClassInfoType( + if (clazz == ObjectClass || isPrimitiveValueClass(clazz)) Nil + else if (clazz == ArrayClass) List(erasedTypeRef(ObjectClass)) + else removeLaterObjects(parents map this), + decls, clazz) + case _ => + mapOver(tp) + } + + private def applyInArray(tp: Type): Type = tp match { + case TypeRef(pre, sym, args) if (sym.isInlineClass) => eraseNormalClassRef(pre, sym) + case _ => apply(tp) } } @@ -159,7 +165,7 @@ trait Erasure { } else scalaErasure(tp) } - + /** This is used as the Scala erasure during the erasure phase itself * It differs from normal erasure in that value classes are erased to ErasedInlineTypes which * are then later converted to the underlying parameter type in phase posterasure. @@ -172,7 +178,7 @@ trait Erasure { else if (sym.isValue && sym.owner.isMethodWithExtension) specialErasureAvoiding(sym.owner.owner, tp) else - specialErasure(tp) + specialErasure(tp) /** Scala's more precise erasure than java's is problematic as follows: * @@ -193,9 +199,9 @@ trait Erasure { def mergeParents(parents: List[Type]): Type = intersectionDominator(parents) } - + object scalaErasure extends ScalaErasureMap - + /** This is used as the Scala erasure during the erasure phase itself * It differs from normal erasure in that value classes are erased to ErasedInlineTypes which * are then later converted to the underlying parameter type in phase posterasure. @@ -203,7 +209,7 @@ trait Erasure { object specialErasure extends ScalaErasureMap { override def eraseInlineClassRef(clazz: Symbol): Type = ErasedInlineType(clazz) } - + def specialErasureAvoiding(clazz: Symbol, tpe: Type): Type = { tpe match { case PolyType(tparams, restpe) => diff --git a/src/compiler/scala/tools/nsc/transform/Erasure.scala b/src/compiler/scala/tools/nsc/transform/Erasure.scala index 30448b6eaa..5e481f570d 100644 --- a/src/compiler/scala/tools/nsc/transform/Erasure.scala +++ b/src/compiler/scala/tools/nsc/transform/Erasure.scala @@ -1063,7 +1063,7 @@ abstract class Erasure extends AddInterfaces case Literal(ct) if ct.tag == ClassTag && ct.typeValue.typeSymbol != definitions.UnitClass => val erased = ct.typeValue match { - case TypeRef(pre, clazz, args) if clazz.isInlineClass => typeRef(pre, clazz, List()) + case TypeRef(pre, clazz, args) if clazz.isInlineClass => scalaErasure.eraseNormalClassRef(pre, clazz) case tpe => specialErasure(NoSymbol, tpe) } treeCopy.Literal(tree, Constant(erased)) diff --git a/src/library/scala/reflect/api/Types.scala b/src/library/scala/reflect/api/Types.scala index 8a91956320..09ee90355e 100755 --- a/src/library/scala/reflect/api/Types.scala +++ b/src/library/scala/reflect/api/Types.scala @@ -46,7 +46,7 @@ trait Types { self: Universe => /** Substitute types in `to` for corresponding occurrences of references to * symbols `from` in this type. */ - def substituteTypes(from: List[Symbol], to: List[Type]): Type // !!! Too many things with names like "subst" + def substituteTypes(from: List[Symbol], to: List[Type]): Type /** If this is a parameterized types, the type arguments. * Otherwise the empty list diff --git a/test/files/run/Meter.scala b/test/files/run/Meter.scala index 0db917aeee..66d35bfc75 100644 --- a/test/files/run/Meter.scala +++ b/test/files/run/Meter.scala @@ -6,6 +6,28 @@ class Meter(val underlying: Double) extends AnyVal with Printable { def < (other: Meter): Boolean = this.underlying < other.underlying override def toString: String = underlying.toString+"m" } +object Meter extends (Double => Meter) { + + def apply(x: Double): Meter = new Meter(x) + + class FlatArray(underlying: Array[Double]) { + def length = underlying.length + def apply(i: Int): Meter = new Meter(underlying(i)) + def update(i: Int, m: Meter) = underlying(i) = m.underlying + override def toString = underlying.toList map Meter mkString ("Meter.FlatArray(", ", ", ")") + } + + object FlatArray { + + def apply(xs: Meter*) = { + val elems = Array.ofDim[Double](xs.length) + for (i <- 0 until xs.length) + elems(i) = xs(i).asInstanceOf[Double] + new FlatArray(elems) + } + } + +} trait Printable extends Any { def print: Unit = Console.print(this) } object Test extends App { @@ -37,5 +59,24 @@ object Test extends App { val b: Any = y println("a == b: "+(a == b)) + { val arr = Array(x, y + x) + println(arr.deep) + def foo[T <: Printable](x: Array[T]) { + for (i <- 0 until x.length) { x(i).print; println(" "+x(i)) } + } + val m = arr(0) + println(m) + foo(arr) + } + + val arr = Meter.FlatArray(x, y + x) + println(arr) + def foo(x: Meter.FlatArray) { + for (i <- 0 until x.length) { x(i).print; println(" "+x(i)) } + } + val m = arr(0) + println(m) + foo(arr) + } -- cgit v1.2.3 From cd6426a8c501eda2105196fc5a254d8f0dd77633 Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Wed, 15 Feb 2012 12:04:36 +0100 Subject: Changed array erasure scheme to never unbox elements of inline classes. --- .../scala/reflect/internal/transform/Erasure.scala | 100 +++++++++++---------- .../scala/tools/nsc/backend/jvm/GenJVM.scala | 6 +- .../scala/tools/nsc/transform/AddInterfaces.scala | 14 +-- .../scala/tools/nsc/transform/Erasure.scala | 21 +++-- .../scala/tools/nsc/typechecker/RefChecks.scala | 3 +- test/files/run/Meter.scala | 34 +++---- 6 files changed, 90 insertions(+), 88 deletions(-) (limited to 'test/files') diff --git a/src/compiler/scala/reflect/internal/transform/Erasure.scala b/src/compiler/scala/reflect/internal/transform/Erasure.scala index bd6a77fb07..2cf171aad3 100644 --- a/src/compiler/scala/reflect/internal/transform/Erasure.scala +++ b/src/compiler/scala/reflect/internal/transform/Erasure.scala @@ -118,7 +118,7 @@ trait Erasure { mapOver(tp) } - private def applyInArray(tp: Type): Type = tp match { + def applyInArray(tp: Type): Type = tp match { case TypeRef(pre, sym, args) if (sym.isInlineClass) => eraseNormalClassRef(pre, sym) case _ => apply(tp) } @@ -153,32 +153,42 @@ trait Erasure { * parents |Ps|, but with duplicate references of Object removed. * - for all other types, the type itself (with any sub-components erased) */ - def erasure(sym: Symbol, tp: Type): Type = { - if (sym != NoSymbol && sym.enclClass.isJavaDefined) { - val res = javaErasure(tp) - if (verifyJavaErasure && sym.isMethod) { - val old = scalaErasure(tp) - if (!(res =:= old)) - log("Identified divergence between java/scala erasure:\n scala: " + old + "\n java: " + res) - } - res - } else - scalaErasure(tp) - } + def erasure(sym: Symbol): ErasureMap = + if (sym == NoSymbol || !sym.enclClass.isJavaDefined) scalaErasure + else if (verifyJavaErasure && sym.isMethod) verifiedJavaErasure + else javaErasure /** This is used as the Scala erasure during the erasure phase itself * It differs from normal erasure in that value classes are erased to ErasedInlineTypes which * are then later converted to the underlying parameter type in phase posterasure. */ - def specialErasure(sym: Symbol, tp: Type): Type = + def specialErasure(sym: Symbol)(tp: Type): Type = if (sym != NoSymbol && sym.enclClass.isJavaDefined) - erasure(sym, tp) + erasure(sym)(tp) else if (sym.isTerm && sym.owner.isInlineClass) specialErasureAvoiding(sym.owner, tp) else if (sym.isValue && sym.owner.isMethodWithExtension) specialErasureAvoiding(sym.owner.owner, tp) else - specialErasure(tp) + specialScalaErasure(tp) + + def specialErasureAvoiding(clazz: Symbol, tpe: Type): Type = { + tpe match { + case PolyType(tparams, restpe) => + specialErasureAvoiding(clazz, restpe) + case ExistentialType(tparams, restpe) => + specialErasureAvoiding(clazz, restpe) + case mt @ MethodType(params, restpe) => + MethodType( + cloneSymbolsAndModify(params, specialErasureAvoiding(clazz, _)), + if (restpe.typeSymbol == UnitClass) erasedTypeRef(UnitClass) + else specialErasureAvoiding(clazz, (mt.resultType(params map (_.tpe))))) + case TypeRef(pre, `clazz`, args) => + typeRef(pre, clazz, List()) + case _ => + specialScalaErasure(tpe) + } + } /** Scala's more precise erasure than java's is problematic as follows: * @@ -200,31 +210,34 @@ trait Erasure { intersectionDominator(parents) } + class JavaErasureMap extends ErasureMap { + /** In java, always take the first parent. + * An intersection such as `Object with Trait` erases to Object. + */ + def mergeParents(parents: List[Type]): Type = + if (parents.isEmpty) ObjectClass.tpe + else parents.head + } + object scalaErasure extends ScalaErasureMap /** This is used as the Scala erasure during the erasure phase itself * It differs from normal erasure in that value classes are erased to ErasedInlineTypes which * are then later converted to the underlying parameter type in phase posterasure. */ - object specialErasure extends ScalaErasureMap { + object specialScalaErasure extends ScalaErasureMap { override def eraseInlineClassRef(clazz: Symbol): Type = ErasedInlineType(clazz) } - def specialErasureAvoiding(clazz: Symbol, tpe: Type): Type = { - tpe match { - case PolyType(tparams, restpe) => - specialErasureAvoiding(clazz, restpe) - case ExistentialType(tparams, restpe) => - specialErasureAvoiding(clazz, restpe) - case mt @ MethodType(params, restpe) => - MethodType( - cloneSymbolsAndModify(params, specialErasureAvoiding(clazz, _)), - if (restpe.typeSymbol == UnitClass) erasedTypeRef(UnitClass) - else specialErasureAvoiding(clazz, (mt.resultType(params map (_.tpe))))) - case TypeRef(pre, `clazz`, args) => - typeRef(pre, clazz, List()) - case _ => - specialErasure(tpe) + object javaErasure extends JavaErasureMap + + object verifiedJavaErasure extends JavaErasureMap { + override def apply(tp: Type): Type = { + val res = javaErasure(tp) + val old = scalaErasure(tp) + if (!(res =:= old)) + log("Identified divergence between java/scala erasure:\n scala: " + old + "\n java: " + res) + res } } @@ -263,18 +276,9 @@ trait Erasure { } } - object javaErasure extends ErasureMap { - /** In java, always take the first parent. - * An intersection such as `Object with Trait` erases to Object. - */ - def mergeParents(parents: List[Type]): Type = - if (parents.isEmpty) ObjectClass.tpe - else parents.head - } - /** Type reference after erasure */ def erasedTypeRef(sym: Symbol): Type = - typeRef(erasure(sym, sym.owner.tpe), sym, Nil) + typeRef(erasure(sym)(sym.owner.tpe), sym, Nil) /** The symbol's erased info. This is the type's erasure, except for the following symbols: * @@ -288,25 +292,25 @@ trait Erasure { if (sym == Object_asInstanceOf) sym.info else if (sym == Object_isInstanceOf || sym == ArrayClass) - PolyType(sym.info.typeParams, specialErasure(sym, sym.info.resultType)) + PolyType(sym.info.typeParams, specialErasure(sym)(sym.info.resultType)) else if (sym.isAbstractType) TypeBounds(WildcardType, WildcardType) else if (sym.isTerm && sym.owner == ArrayClass) { if (sym.isClassConstructor) tp match { case MethodType(params, TypeRef(pre, sym1, args)) => - MethodType(cloneSymbolsAndModify(params, specialErasure(sym, _)), - typeRef(specialErasure(sym, pre), sym1, args)) + MethodType(cloneSymbolsAndModify(params, specialErasure(sym)), + typeRef(specialErasure(sym)(pre), sym1, args)) } else if (sym.name == nme.apply) tp else if (sym.name == nme.update) (tp: @unchecked) match { case MethodType(List(index, tvar), restpe) => - MethodType(List(index.cloneSymbol.setInfo(specialErasure(sym, index.tpe)), tvar), + MethodType(List(index.cloneSymbol.setInfo(specialErasure(sym)(index.tpe)), tvar), erasedTypeRef(UnitClass)) } - else specialErasure(sym, tp) + else specialErasure(sym)(tp) } else if ( sym.owner != NoSymbol && sym.owner.owner == ArrayClass && @@ -316,7 +320,7 @@ trait Erasure { // symbol here tp } else { - specialErasure(sym, tp) + specialErasure(sym)(tp) } } } diff --git a/src/compiler/scala/tools/nsc/backend/jvm/GenJVM.scala b/src/compiler/scala/tools/nsc/backend/jvm/GenJVM.scala index b5232fff09..cc38979487 100644 --- a/src/compiler/scala/tools/nsc/backend/jvm/GenJVM.scala +++ b/src/compiler/scala/tools/nsc/backend/jvm/GenJVM.scala @@ -154,7 +154,7 @@ abstract class GenJVM extends SubComponent with GenJVMUtil with GenAndroid with if (settings.Ygenjavap.isDefault) { if(settings.Ydumpclasses.isDefault) new ClassBytecodeWriter { } - else + else new ClassBytecodeWriter with DumpBytecodeWriter { } } else new ClassBytecodeWriter with JavapBytecodeWriter { } @@ -209,7 +209,7 @@ abstract class GenJVM extends SubComponent with GenJVMUtil with GenAndroid with val BeanInfoSkipAttr = definitions.getRequiredClass("scala.beans.BeanInfoSkip") val BeanDisplayNameAttr = definitions.getRequiredClass("scala.beans.BeanDisplayName") val BeanDescriptionAttr = definitions.getRequiredClass("scala.beans.BeanDescription") - + final val ExcludedForwarderFlags = { import Flags._ ( CASE | SPECIALIZED | LIFTED | PROTECTED | STATIC | BridgeAndPrivateFlags ) @@ -702,7 +702,7 @@ abstract class GenJVM extends SubComponent with GenJVMUtil with GenAndroid with if ((settings.check.value contains "genjvm")) { val normalizedTpe = atPhase(currentRun.erasurePhase)(erasure.prepareSigMap(memberTpe)) val bytecodeTpe = owner.thisType.memberInfo(sym) - if (!sym.isType && !sym.isConstructor && !(erasure.erasure(sym, normalizedTpe) =:= bytecodeTpe)) { + if (!sym.isType && !sym.isConstructor && !(erasure.erasure(sym)(normalizedTpe) =:= bytecodeTpe)) { clasz.cunit.warning(sym.pos, """|compiler bug: created generic signature for %s in %s that does not conform to its erasure |signature: %s diff --git a/src/compiler/scala/tools/nsc/transform/AddInterfaces.scala b/src/compiler/scala/tools/nsc/transform/AddInterfaces.scala index 531a475bc6..cab440ef52 100644 --- a/src/compiler/scala/tools/nsc/transform/AddInterfaces.scala +++ b/src/compiler/scala/tools/nsc/transform/AddInterfaces.scala @@ -11,7 +11,7 @@ import Flags._ import scala.collection.{ mutable, immutable } import collection.mutable.ListBuffer -abstract class AddInterfaces extends InfoTransform { +abstract class AddInterfaces extends InfoTransform { self: Erasure => import global._ // the global environment import definitions._ // standard classes and methods @@ -21,14 +21,6 @@ abstract class AddInterfaces extends InfoTransform { */ override def phaseNewFlags: Long = lateDEFERRED | lateINTERFACE - /** Type reference after erasure; defined in Erasure. - */ - def erasedTypeRef(sym: Symbol): Type - - /** Erasure calculation; defined in Erasure. - */ - def erasure(sym: Symbol, tpe: Type): Type - /** A lazily constructed map that associates every non-interface trait with * its implementation class. */ @@ -175,14 +167,14 @@ abstract class AddInterfaces extends InfoTransform { /** If `tp` refers to a non-interface trait, return a * reference to its implementation class. Otherwise return `tp`. */ - def mixinToImplClass(tp: Type): Type = erasure(sym, + def mixinToImplClass(tp: Type): Type = erasure(sym) { tp match { //@MATN: no normalize needed (comes after erasure) case TypeRef(pre, sym, _) if sym.needsImplClass => typeRef(pre, implClass(sym), Nil) case _ => tp } - ) + } def implType(tp: Type): Type = tp match { case ClassInfoType(parents, decls, _) => assert(phase == implClassPhase, tp) diff --git a/src/compiler/scala/tools/nsc/transform/Erasure.scala b/src/compiler/scala/tools/nsc/transform/Erasure.scala index 5e481f570d..306e00e38d 100644 --- a/src/compiler/scala/tools/nsc/transform/Erasure.scala +++ b/src/compiler/scala/tools/nsc/transform/Erasure.scala @@ -290,7 +290,7 @@ abstract class Erasure extends AddInterfaces ) ) } - else jsig(erasure(sym0, tp), existentiallyBound, toplevel, primitiveOK) + else jsig(erasure(sym0)(tp), existentiallyBound, toplevel, primitiveOK) case PolyType(tparams, restpe) => assert(tparams.nonEmpty) val poly = if (toplevel) polyParamSig(tparams) else "" @@ -310,7 +310,7 @@ abstract class Erasure extends AddInterfaces println("something's wrong: "+sym0+":"+sym0.tpe+" has a bounded wildcard type") jsig(bounds.hi, existentiallyBound, toplevel, primitiveOK) case _ => - val etp = erasure(sym0, tp) + val etp = erasure(sym0)(tp) if (etp eq tp) throw new UnknownSig else jsig(etp) } @@ -793,7 +793,7 @@ abstract class Erasure extends AddInterfaces val other = opc.overridden //println("bridge? " + member + ":" + member.tpe + member.locationString + " to " + other + ":" + other.tpe + other.locationString)//DEBUG if (atPhase(currentRun.explicitouterPhase)(!member.isDeferred)) { - val otpe = erasure(owner, other.tpe) + val otpe = erasure(owner)(other.tpe) val bridgeNeeded = atPhase(phase.next) ( !(other.tpe =:= member.tpe) && !(deconstMap(other.tpe) =:= deconstMap(member.tpe)) && @@ -838,7 +838,7 @@ abstract class Erasure extends AddInterfaces IF (typeTest) THEN bridgingCall ELSE REF(NoneModule) } else bridgingCall }); - debuglog("generating bridge from " + other + "(" + Flags.flagsToString(bridge.flags) + ")" + ":" + otpe + other.locationString + " to " + member + ":" + erasure(owner, member.tpe) + member.locationString + " =\n " + bridgeDef); + debuglog("generating bridge from " + other + "(" + Flags.flagsToString(bridge.flags) + ")" + ":" + otpe + other.locationString + " to " + member + ":" + erasure(owner)(member.tpe) + member.locationString + " =\n " + bridgeDef); bridgeDef } } :: bridges @@ -910,7 +910,7 @@ abstract class Erasure extends AddInterfaces gen.mkMethodCall( qual1(), fun.symbol, - List(specialErasure(fun.symbol, arg.tpe)), + List(specialErasure(fun.symbol)(arg.tpe)), Nil ), isArrayTest(qual1()) @@ -943,7 +943,7 @@ abstract class Erasure extends AddInterfaces // need to do the cast in adaptMember treeCopy.Apply( tree, - SelectFromArray(qual, name, erasure(tree.symbol, qual.tpe)).copyAttrs(fn), + SelectFromArray(qual, name, erasure(tree.symbol)(qual.tpe)).copyAttrs(fn), args) } case Apply(fn @ Select(qual, _), Nil) if interceptedMethods(fn.symbol) => @@ -1064,7 +1064,7 @@ abstract class Erasure extends AddInterfaces && ct.typeValue.typeSymbol != definitions.UnitClass => val erased = ct.typeValue match { case TypeRef(pre, clazz, args) if clazz.isInlineClass => scalaErasure.eraseNormalClassRef(pre, clazz) - case tpe => specialErasure(NoSymbol, tpe) + case tpe => specialScalaErasure(tpe) } treeCopy.Literal(tree, Constant(erased)) @@ -1084,10 +1084,13 @@ abstract class Erasure extends AddInterfaces val tree1 = preErase(tree) tree1 match { case EmptyTree | TypeTree() => - tree1 setType specialErasure(NoSymbol, tree1.tpe) + tree1 setType specialScalaErasure(tree1.tpe) + case ArrayValue(elemtpt, trees) => + treeCopy.ArrayValue( + tree1, elemtpt setType specialScalaErasure.applyInArray(elemtpt.tpe), trees map transform) setType null case DefDef(_, _, _, _, tpt, _) => val result = super.transform(tree1) setType null - tpt.tpe = specialErasure(tree1.symbol, tree1.symbol.tpe).resultType + tpt.tpe = specialErasure(tree1.symbol)(tree1.symbol.tpe).resultType result case _ => super.transform(tree1) setType null diff --git a/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala b/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala index 064a3dd229..91ea7c7cd9 100644 --- a/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala +++ b/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala @@ -515,7 +515,8 @@ abstract class RefChecks extends InfoTransform with reflect.internal.transform.R !other.isDeferred && other.isJavaDefined && { // #3622: erasure operates on uncurried types -- // note on passing sym in both cases: only sym.isType is relevant for uncurry.transformInfo - def uncurryAndErase(tp: Type) = erasure.erasure(sym, uncurry.transformInfo(sym, tp)) + // !!! erasure.erasure(sym, uncurry.transformInfo(sym, tp)) gives erreneous of inaccessible type - check whether that's still the case! + def uncurryAndErase(tp: Type) = erasure.erasure(sym)(uncurry.transformInfo(sym, tp)) val tp1 = uncurryAndErase(clazz.thisType.memberType(sym)) val tp2 = uncurryAndErase(clazz.thisType.memberType(other)) atPhase(currentRun.erasurePhase.next)(tp1 matches tp2) diff --git a/test/files/run/Meter.scala b/test/files/run/Meter.scala index 66d35bfc75..da99f81722 100644 --- a/test/files/run/Meter.scala +++ b/test/files/run/Meter.scala @@ -59,24 +59,26 @@ object Test extends App { val b: Any = y println("a == b: "+(a == b)) - { - val arr = Array(x, y + x) - println(arr.deep) - def foo[T <: Printable](x: Array[T]) { - for (i <- 0 until x.length) { x(i).print; println(" "+x(i)) } - } - val m = arr(0) - println(m) - foo(arr) + { println("testing native arrays") + val arr = Array(x, y + x) + println(arr.deep) + def foo[T <: Printable](x: Array[T]) { + for (i <- 0 until x.length) { x(i).print; println(" "+x(i)) } + } + val m = arr(0) + println(m) + foo(arr) } - val arr = Meter.FlatArray(x, y + x) - println(arr) - def foo(x: Meter.FlatArray) { - for (i <- 0 until x.length) { x(i).print; println(" "+x(i)) } + { println("testing wrapped arrays") + val arr = Meter.FlatArray(x, y + x) + println(arr) + def foo(x: Meter.FlatArray) { + for (i <- 0 until x.length) { x(i).print; println(" "+x(i)) } + } + val m = arr(0) + println(m) + foo(arr) } - val m = arr(0) - println(m) - foo(arr) } -- cgit v1.2.3 From 280192f2c5e92f9f8fb3238f1b4bfdf2566e6fdf Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Wed, 15 Feb 2012 15:33:09 +0100 Subject: New scheme for "Rows" of value classes. --- src/library/scala/Boxed.scala | 18 ++++++++ .../scala/collection/generic/RowFactory.scala | 49 ++++++++++++++++++++++ test/files/run/Meter.scala | 40 ++++++------------ 3 files changed, 79 insertions(+), 28 deletions(-) create mode 100644 src/library/scala/Boxed.scala create mode 100644 src/library/scala/collection/generic/RowFactory.scala (limited to 'test/files') diff --git a/src/library/scala/Boxed.scala b/src/library/scala/Boxed.scala new file mode 100644 index 0000000000..6055b3f436 --- /dev/null +++ b/src/library/scala/Boxed.scala @@ -0,0 +1,18 @@ +/* __ *\ +** ________ ___ / / ___ Scala API ** +** / __/ __// _ | / / / _ | (c) 2002-2011, LAMP/EPFL ** +** __\ \/ /__/ __ |/ /__/ __ | http://www.scala-lang.org/ ** +** /____/\___/_/ |_/____/_/ | | ** +** |/ ** +\* */ + +package scala + +/** A trait that can be implemented by user-defined value classes + */ +trait Boxed[Unboxed] extends Any { + + /** The underlying value wrapped by the value class */ + def unbox: Unboxed +} + diff --git a/src/library/scala/collection/generic/RowFactory.scala b/src/library/scala/collection/generic/RowFactory.scala new file mode 100644 index 0000000000..c1559c9397 --- /dev/null +++ b/src/library/scala/collection/generic/RowFactory.scala @@ -0,0 +1,49 @@ +package scala.collection +package generic + +import mutable.{Builder, ArrayBuffer} +import scala.specialized + +/** A factory class for rows -- flat arrays of value classes that use the unboxed representation + * of the element type. + * + */ +abstract class RowFactory[@specialized Unboxed: ClassManifest, Boxed <: scala.Boxed[Unboxed]] extends (Unboxed => Boxed) { box => + + /** Convert to boxed representation + */ + def apply(x: Unboxed): Boxed + + class Row(elems: Array[Unboxed]) extends mutable.IndexedSeq[Boxed] with mutable.IndexedSeqLike[Boxed, Row] { + + override protected[this] def newBuilder: Builder[Boxed, Row] = Row.newBuilder + + def apply(idx: Int): Boxed = box(elems(idx)) + + def update(idx: Int, elem: Boxed): Unit = elems(idx) = elem.unbox + + def length = elems.length + + override def foreach[U](f: Boxed => U): Unit = elems foreach (elem => f(box(elem))) + + } + + object Row { + def fromSeq(elems: Seq[Boxed]): Row = { + val xs: Array[Unboxed] = new Array[Unboxed](elems.length) + var i = 0 + for (elem <- elems) { xs(i) = elem.unbox; i += 1 } + new Row(xs) + } + + def apply(elems: Boxed*) = fromSeq(elems) + + def newBuilder: Builder[Boxed, Row] = new ArrayBuffer mapResult fromSeq + + implicit def canBuildFrom: CanBuildFrom[Row, Boxed, Row] = + new CanBuildFrom[Row, Boxed, Row] { + def apply(): Builder[Boxed, Row] = newBuilder + def apply(from: Row): Builder[Boxed, Row] = newBuilder + } + } +} diff --git a/test/files/run/Meter.scala b/test/files/run/Meter.scala index da99f81722..15d35054a2 100644 --- a/test/files/run/Meter.scala +++ b/test/files/run/Meter.scala @@ -1,33 +1,17 @@ -class Meter(val underlying: Double) extends AnyVal with Printable { +import collection.generic.RowFactory + +class Meter(val unbox: Double) extends AnyVal with Boxed[Double] 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" + new Meter(this.unbox + other.unbox) + def / (other: Meter): Double = this.unbox / other.unbox + def / (factor: Double): Meter = new Meter(this.unbox / factor) + def < (other: Meter): Boolean = this.unbox < other.unbox + override def toString: String = unbox.toString+"m" } -object Meter extends (Double => Meter) { - +object Meter extends RowFactory[Double, Meter] { def apply(x: Double): Meter = new Meter(x) - - class FlatArray(underlying: Array[Double]) { - def length = underlying.length - def apply(i: Int): Meter = new Meter(underlying(i)) - def update(i: Int, m: Meter) = underlying(i) = m.underlying - override def toString = underlying.toList map Meter mkString ("Meter.FlatArray(", ", ", ")") - } - - object FlatArray { - - def apply(xs: Meter*) = { - val elems = Array.ofDim[Double](xs.length) - for (i <- 0 until xs.length) - elems(i) = xs(i).asInstanceOf[Double] - new FlatArray(elems) - } - } - } + trait Printable extends Any { def print: Unit = Console.print(this) } object Test extends App { @@ -71,9 +55,9 @@ object Test extends App { } { println("testing wrapped arrays") - val arr = Meter.FlatArray(x, y + x) + val arr = Meter.Row(x, y + x) println(arr) - def foo(x: Meter.FlatArray) { + def foo(x: Meter.Row) { for (i <- 0 until x.length) { x(i).print; println(" "+x(i)) } } val m = arr(0) -- cgit v1.2.3 From d638588797bff0998b588ba3552e6caefbf7b8e3 Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Wed, 15 Feb 2012 16:08:38 +0100 Subject: Updated check file. --- test/files/run/Meter.check | 11 +++++++++++ 1 file changed, 11 insertions(+) (limited to 'test/files') diff --git a/test/files/run/Meter.check b/test/files/run/Meter.check index a936073489..d5073b3c31 100644 --- a/test/files/run/Meter.check +++ b/test/files/run/Meter.check @@ -1,7 +1,18 @@ 2.0 4.0m false +x.isInstanceOf[Meter]: true x.hashCode: 1072693248 x == 1: false x == y: true a == b: true +testing native arrays +Array(1.0m, 2.0m) +1.0m +1.0m 1.0m +2.0m 2.0m +testing wrapped arrays +RowFactory(1.0m, 2.0m) +1.0m +1.0m 1.0m +2.0m 2.0m -- cgit v1.2.3 From 186d8554456b6a2d024ada1bd2dd1a29cc0c430f Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Wed, 15 Feb 2012 18:12:17 +0100 Subject: Trying generic value classes. Does not work yet, but fixed on bug already. --- .../scala/tools/nsc/transform/ExtensionMethods.scala | 4 ++-- test/files/run/GenericValueClass.scala | 12 ++++++++++++ 2 files changed, 14 insertions(+), 2 deletions(-) create mode 100644 test/files/run/GenericValueClass.scala (limited to 'test/files') diff --git a/src/compiler/scala/tools/nsc/transform/ExtensionMethods.scala b/src/compiler/scala/tools/nsc/transform/ExtensionMethods.scala index e5f2d49d52..79dc6b4986 100644 --- a/src/compiler/scala/tools/nsc/transform/ExtensionMethods.scala +++ b/src/compiler/scala/tools/nsc/transform/ExtensionMethods.scala @@ -152,8 +152,8 @@ abstract class ExtensionMethods extends Transform with TypingTransformers { case stat @ ModuleDef(mods, name, tmpl @ Template(parents, self, body)) => extensionDefs.remove(stat.symbol) match { case Some(buf) => - val extensionDefs = buf.toList map { mdef => atOwner(stat.symbol) { localTyper.typed(mdef) }} - treeCopy.ModuleDef(stat, mods, name, treeCopy.Template(tmpl, parents, self, body ++ buf)) + val extensionDefs = buf.toList map { mdef => atOwner(stat.symbol) { localTyper.typed(mdef) } } + treeCopy.ModuleDef(stat, mods, name, treeCopy.Template(tmpl, parents, self, body ++ extensionDefs)) case None => stat } diff --git a/test/files/run/GenericValueClass.scala b/test/files/run/GenericValueClass.scala new file mode 100644 index 0000000000..10068d6cae --- /dev/null +++ b/test/files/run/GenericValueClass.scala @@ -0,0 +1,12 @@ +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) + +} -- cgit v1.2.3 From 8cc7de74d35b437b7126d02a6219796b5872ac14 Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Fri, 17 Feb 2012 16:35:48 +0100 Subject: New FlatArray scheme for handling value classes. --- src/library/scala/Boxed.scala | 18 --- src/library/scala/BoxingConversions.scala | 5 + .../scala/collection/generic/RowFactory.scala | 49 ------- .../scala/collection/mutable/FlatArray.scala | 150 +++++++++++++++++++++ test/files/run/Meter.scala | 33 +++-- 5 files changed, 176 insertions(+), 79 deletions(-) delete mode 100644 src/library/scala/Boxed.scala create mode 100644 src/library/scala/BoxingConversions.scala delete mode 100644 src/library/scala/collection/generic/RowFactory.scala create mode 100644 src/library/scala/collection/mutable/FlatArray.scala (limited to 'test/files') diff --git a/src/library/scala/Boxed.scala b/src/library/scala/Boxed.scala deleted file mode 100644 index 6055b3f436..0000000000 --- a/src/library/scala/Boxed.scala +++ /dev/null @@ -1,18 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2002-2011, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | http://www.scala-lang.org/ ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - -package scala - -/** A trait that can be implemented by user-defined value classes - */ -trait Boxed[Unboxed] extends Any { - - /** The underlying value wrapped by the value class */ - def unbox: Unboxed -} - diff --git a/src/library/scala/BoxingConversions.scala b/src/library/scala/BoxingConversions.scala new file mode 100644 index 0000000000..fd1bd6c121 --- /dev/null +++ b/src/library/scala/BoxingConversions.scala @@ -0,0 +1,5 @@ +package scala +abstract class BoxingConversions[Boxed, Unboxed] { + def box(x: Unboxed): Boxed + def unbox(x: Boxed): Unboxed +} diff --git a/src/library/scala/collection/generic/RowFactory.scala b/src/library/scala/collection/generic/RowFactory.scala deleted file mode 100644 index c1559c9397..0000000000 --- a/src/library/scala/collection/generic/RowFactory.scala +++ /dev/null @@ -1,49 +0,0 @@ -package scala.collection -package generic - -import mutable.{Builder, ArrayBuffer} -import scala.specialized - -/** A factory class for rows -- flat arrays of value classes that use the unboxed representation - * of the element type. - * - */ -abstract class RowFactory[@specialized Unboxed: ClassManifest, Boxed <: scala.Boxed[Unboxed]] extends (Unboxed => Boxed) { box => - - /** Convert to boxed representation - */ - def apply(x: Unboxed): Boxed - - class Row(elems: Array[Unboxed]) extends mutable.IndexedSeq[Boxed] with mutable.IndexedSeqLike[Boxed, Row] { - - override protected[this] def newBuilder: Builder[Boxed, Row] = Row.newBuilder - - def apply(idx: Int): Boxed = box(elems(idx)) - - def update(idx: Int, elem: Boxed): Unit = elems(idx) = elem.unbox - - def length = elems.length - - override def foreach[U](f: Boxed => U): Unit = elems foreach (elem => f(box(elem))) - - } - - object Row { - def fromSeq(elems: Seq[Boxed]): Row = { - val xs: Array[Unboxed] = new Array[Unboxed](elems.length) - var i = 0 - for (elem <- elems) { xs(i) = elem.unbox; i += 1 } - new Row(xs) - } - - def apply(elems: Boxed*) = fromSeq(elems) - - def newBuilder: Builder[Boxed, Row] = new ArrayBuffer mapResult fromSeq - - implicit def canBuildFrom: CanBuildFrom[Row, Boxed, Row] = - new CanBuildFrom[Row, Boxed, Row] { - def apply(): Builder[Boxed, Row] = newBuilder - def apply(from: Row): Builder[Boxed, Row] = newBuilder - } - } -} diff --git a/src/library/scala/collection/mutable/FlatArray.scala b/src/library/scala/collection/mutable/FlatArray.scala new file mode 100644 index 0000000000..0650d09861 --- /dev/null +++ b/src/library/scala/collection/mutable/FlatArray.scala @@ -0,0 +1,150 @@ +/* __ *\ +** ________ ___ / / ___ Scala API ** +** / __/ __// _ | / / / _ | (c) 2002-2011, LAMP/EPFL ** +** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** +** /____/\___/_/ |_/____/_/ | | ** +** |/ ** +\* */ + + + +package scala.collection +package mutable + +import scala.reflect.ClassManifest +import generic.CanBuildFrom + +/** + * A class representing `Array[T]`. + * + * @tparam T type of the elements in this wrapped array. + * + * @author Martin Odersky, Stephane Micheloud + * @version 1.0 + * @since 2.8 + * @define Coll WrappedArray + * @define coll wrapped array + * @define orderDependent + * @define orderDependentFold + * @define mayNotTerminateInf + * @define willNotTerminateInf + */ +abstract sealed class FlatArray[T] +extends AbstractSeq[T] + with IndexedSeq[T] + with IndexedSeqOptimized[T, FlatArray[T]] +{ + + override protected[this] def thisCollection: FlatArray[T] = this + override protected[this] def toCollection(repr: FlatArray[T]): FlatArray[T] = repr + + /** The length of the array */ + def length: Int + + /** The element at given index */ + def apply(index: Int): T + + /** Update element at given index */ + def update(index: Int, elem: T): Unit + + override def stringPrefix = "FlatArray" + + override protected[this] def newBuilder: Builder[T, FlatArray[T]] = ??? // implemented in FlatArray.Impl + + /** Clones this object, including the underlying Array. */ + override def clone: FlatArray[T] = ??? // implemented in FlatArray.Impl +} + + +/** A companion object used to create instances of `WrappedArray`. + */ +object FlatArray { + + def empty[Boxed, Unboxed](elems: Boxed*) + (implicit boxings: BoxingConversions[Boxed, Unboxed], elemManifest: ClassManifest[Unboxed]): FlatArray[Boxed] = apply() + + def apply[Boxed, Unboxed](elems: Boxed*) + (implicit boxings: BoxingConversions[Boxed, Unboxed], elemManifest: ClassManifest[Unboxed]): FlatArray[Boxed] = { + val b = newBuilder[Boxed, Unboxed] + b.sizeHint(elems.length) + b ++= elems + b.result + } + + def newBuilder[Boxed, Unboxed] + (implicit boxings: BoxingConversions[Boxed, Unboxed], elemManifest: ClassManifest[Unboxed]): Builder[Boxed, FlatArray[Boxed]] = + new Bldr[Boxed, Unboxed](boxings, elemManifest) + + implicit def canBuildFrom[Boxed, Unboxed]( + implicit + boxings: BoxingConversions[Boxed, Unboxed], + elemManifest: ClassManifest[Unboxed]): CanBuildFrom[FlatArray[_], Boxed, FlatArray[Boxed]] = + new CanBuildFrom[FlatArray[_], Boxed, FlatArray[Boxed]] { + def apply(from: FlatArray[_]): Builder[Boxed, FlatArray[Boxed]] = + newBuilder[Boxed, Unboxed] + def apply: Builder[Boxed, FlatArray[Boxed]] = + newBuilder[Boxed, Unboxed] + } + + private class Bldr[Boxed, Unboxed](boxings: BoxingConversions[Boxed, Unboxed], manifest: ClassManifest[Unboxed]) extends Builder[Boxed, FlatArray[Boxed]] { + + private var elems: Array[Unboxed] = _ + private var capacity: Int = 0 + private var size: Int = 0 + + private def resize(size: Int) { + val newelems = manifest.newArray(size) + if (this.size > 0) Array.copy(elems, 0, newelems, 0, this.size) + elems = newelems + capacity = size + } + + override def sizeHint(size: Int) { + if (capacity < size) resize(size) + } + + private def ensureSize(size: Int) { + if (capacity < size) { + var newsize = if (capacity == 0) 16 else capacity * 2 + while (newsize < size) newsize *= 2 + resize(newsize) + } + } + + def +=(elem: Boxed): this.type = { + ensureSize(size + 1) + elems(size) = boxings.unbox(elem) + size += 1 + this + } + + def clear() { + size = 0 + } + + def result(): FlatArray[Boxed] = { + if (capacity == 0 || capacity != size) resize(size) + new FlatArray.Impl(elems, boxings, manifest) + } + } + + private class Impl[Boxed, Unboxed]( + elems: Array[Unboxed], + boxings: BoxingConversions[Boxed, Unboxed], + elemManifest: ClassManifest[Unboxed]) extends FlatArray[Boxed] { + + def length = elems.length + + def apply(idx: Int): Boxed = boxings.box(elems(idx)) + + def update(idx: Int, elem: Boxed) = elems(idx) = boxings.unbox(elem) + + /** Creates new builder for this collection ==> move to subclasses + */ + override protected[this] def newBuilder: Builder[Boxed, FlatArray[Boxed]] = + new Bldr[Boxed, Unboxed](boxings, elemManifest) + + /** Clones this object, including the underlying Array. */ + override def clone: FlatArray[Boxed] = new Impl[Boxed, Unboxed](elems.clone(), boxings, elemManifest) + } +} diff --git a/test/files/run/Meter.scala b/test/files/run/Meter.scala index 15d35054a2..936b8d98b7 100644 --- a/test/files/run/Meter.scala +++ b/test/files/run/Meter.scala @@ -1,17 +1,21 @@ -import collection.generic.RowFactory - -class Meter(val unbox: Double) extends AnyVal with Boxed[Double] with Printable { +class Meter(val underlying: Double) extends AnyVal with Printable { def + (other: Meter): Meter = - new Meter(this.unbox + other.unbox) - def / (other: Meter): Double = this.unbox / other.unbox - def / (factor: Double): Meter = new Meter(this.unbox / factor) - def < (other: Meter): Boolean = this.unbox < other.unbox - override def toString: String = unbox.toString+"m" + 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 RowFactory[Double, Meter] { +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 + } + +} trait Printable extends Any { def print: Unit = Console.print(this) } object Test extends App { @@ -55,14 +59,19 @@ object Test extends App { } { println("testing wrapped arrays") - val arr = Meter.Row(x, y + x) + import collection.mutable.FlatArray + val arr = FlatArray(x, y + x) println(arr) - def foo(x: Meter.Row) { + def foo(x: FlatArray[Meter]) { for (i <- 0 until x.length) { x(i).print; println(" "+x(i)) } } val m = arr(0) println(m) foo(arr) + val ys: Seq[Meter] = arr map (_ + new Meter(1)) + println(ys) + val zs = arr map (_ / Meter(1)) + println(zs) } } -- cgit v1.2.3 From 64aaef72504b46b9d40359eb0476ad8416f36023 Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Sun, 19 Feb 2012 18:02:44 +0100 Subject: Implemented super access in value classes, restrictions for value classes. --- src/compiler/scala/reflect/internal/Symbols.scala | 2 +- src/compiler/scala/tools/nsc/Global.scala | 15 +++--- .../tools/nsc/typechecker/SuperAccessors.scala | 3 ++ .../scala/tools/nsc/typechecker/Typers.scala | 18 ++++--- test/files/neg/valueclasses.check | 46 ++++++++++++++++++ test/files/neg/valueclasses.scala | 36 ++++++++++++++ test/files/run/GenericValueClass.scala | 12 ----- test/files/run/Meter.check | 13 +++-- test/files/run/Meter.scala | 55 ++++++++++++++++------ test/files/run/programmatic-main.check | 4 +- 10 files changed, 156 insertions(+), 48 deletions(-) create mode 100644 test/files/neg/valueclasses.check create mode 100644 test/files/neg/valueclasses.scala delete mode 100644 test/files/run/GenericValueClass.scala (limited to 'test/files') 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 -- cgit v1.2.3 From 8dc2bbe4bdc83edfb44172110f0ffef52df8a1c9 Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Wed, 22 Feb 2012 09:59:18 +0100 Subject: Updatwd check file. --- test/files/neg/anytrait.check | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'test/files') diff --git a/test/files/neg/anytrait.check b/test/files/neg/anytrait.check index 99c24b85a0..9dd970b58c 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 trait extending from class Any: private[this] var x: Int = 1 +anytrait.scala:3: error: this statement is not allowed in universal trait extending from class Any: private[this] var x: Int = 1 var x = 1 ^ -anytrait.scala:5: error: this statement is not allowed in 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: T.this.x_=(T.this.x.+(1)) { x += 1 } ^ two errors found -- cgit v1.2.3 From 4eae7511a297b9d51e1aea2da38c5dacf786efa0 Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Wed, 22 Feb 2012 23:05:26 +0100 Subject: Compiler now ready to accept value classes in standard library. Time for a new STARR! --- src/compiler/scala/tools/nsc/typechecker/Namers.scala | 2 +- src/library/scala/runtime/StringAdd.scala | 7 +++++++ src/library/scala/runtime/StringFormat.scala | 10 +++++++++- test/files/neg/valueclasses.check | 5 +---- test/files/neg/valueclasses.scala | 2 +- 5 files changed, 19 insertions(+), 7 deletions(-) (limited to 'test/files') diff --git a/src/compiler/scala/tools/nsc/typechecker/Namers.scala b/src/compiler/scala/tools/nsc/typechecker/Namers.scala index 5207fe8331..687c325760 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Namers.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Namers.scala @@ -103,7 +103,7 @@ trait Namers extends MethodSynthesis { def enclosingNamerWithScope(scope: Scope) = { var cx = context while (cx != NoContext && cx.scope != scope) cx = cx.outer - if (cx == context) thisNamer + if (cx == NoContext || cx == context) thisNamer else newNamer(cx) } diff --git a/src/library/scala/runtime/StringAdd.scala b/src/library/scala/runtime/StringAdd.scala index a1256c3f3b..a7e78ea9a3 100644 --- a/src/library/scala/runtime/StringAdd.scala +++ b/src/library/scala/runtime/StringAdd.scala @@ -8,8 +8,15 @@ package scala.runtime +/** A wrapper class that adds string concatenation `+` to any value */ final class StringAdd(val self: Any) { + // Note: The implicit conversion from Any to StringAdd is one of two + // implicit conversions from Any to AnyRef in Predef. It is important to have at least + // two such conversions, so that silent conversions from value types to AnyRef + // are avoided. If StringFormat should become a value class, another + // implicit conversion from Any to AnyRef has to be introduced in Predef + def +(other: String) = String.valueOf(self) + other } diff --git a/src/library/scala/runtime/StringFormat.scala b/src/library/scala/runtime/StringFormat.scala index 94bba4043c..1f0183afbb 100644 --- a/src/library/scala/runtime/StringFormat.scala +++ b/src/library/scala/runtime/StringFormat.scala @@ -8,7 +8,15 @@ package scala.runtime -final class StringFormat(val self: Any) extends AnyVal { +/** A wrapper class that adds a `formatted` operation to any value + */ +final class StringFormat(val self: Any) { + + // Note: The implicit conversion from Any to StringFormat is one of two + // implicit conversions from Any to AnyRef in Predef. It is important to have at least + // two such conversions, so that silent conversions from value types to AnyRef + // are avoided. If StringFormat should become a value class, another + // implicit conversion from Any to AnyRef has to be introduced in Predef /** Returns string formatted according to given `format` string. * Format strings are as for `String.format` diff --git a/test/files/neg/valueclasses.check b/test/files/neg/valueclasses.check index c4430c8e1a..30ee689511 100644 --- a/test/files/neg/valueclasses.check +++ b/test/files/neg/valueclasses.check @@ -34,13 +34,10 @@ 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 +14 errors found diff --git a/test/files/neg/valueclasses.scala b/test/files/neg/valueclasses.scala index 2794a852ee..5979f6f684 100644 --- a/test/files/neg/valueclasses.scala +++ b/test/files/neg/valueclasses.scala @@ -24,7 +24,7 @@ class V9(val x: Int) extends AnyVal { val y = x // fail } -class V10[T](val x: T) extends AnyVal // fail +class V10[T](val x: T) extends AnyVal // ok class V11[T](val x: List[T]) extends AnyVal // ok class V12[@specialized T, U](val x: (T, U)) extends AnyVal // fail -- cgit v1.2.3 From edaf481155a550c2b5199de6702c7cbdc2007d58 Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Mon, 5 Mar 2012 16:05:07 +0100 Subject: new and updated test cases for value classes. --- test/files/neg/t900.check | 4 ++-- test/files/neg/valueclasses.scala | 18 ++++++++++++++++++ test/files/run/genericValueClass.check | 2 ++ test/files/run/genericValueClass.scala | 17 +++++++++++++++++ 4 files changed, 39 insertions(+), 2 deletions(-) create mode 100644 test/files/run/genericValueClass.check create mode 100644 test/files/run/genericValueClass.scala (limited to 'test/files') diff --git a/test/files/neg/t900.check b/test/files/neg/t900.check index cede26258b..047094ad6e 100644 --- a/test/files/neg/t900.check +++ b/test/files/neg/t900.check @@ -2,8 +2,8 @@ t900.scala:4: error: type mismatch; found : Foo.this.x.type (with underlying type Foo.this.bar) required: AnyRef Note that implicit conversions are not applicable because they are ambiguous: - both method any2Ensuring in object Predef of type [A](x: A)Ensuring[A] - and method any2ArrowAssoc in object Predef of type [A](x: A)ArrowAssoc[A] + both method any2stringadd in object Predef of type (x: Any)scala.runtime.StringAdd + and method any2stringfmt in object Predef of type (x: Any)scala.runtime.StringFormat are possible conversion functions from Foo.this.x.type to AnyRef def break(): x.type ^ diff --git a/test/files/neg/valueclasses.scala b/test/files/neg/valueclasses.scala index 5979f6f684..e405d95489 100644 --- a/test/files/neg/valueclasses.scala +++ b/test/files/neg/valueclasses.scala @@ -31,6 +31,24 @@ class V12[@specialized T, U](val x: (T, U)) extends AnyVal // fail class V13(x: Int) extends AnyVal // fail +package time { +object TOD { + final val SecondsPerDay = 86400 + + def apply(seconds: Int) = { + val n = seconds % SecondsPerDay + new TOD(if (n >= 0) n else n + SecondsPerDay) + } +} + +final class TOD private (val secondsOfDay: Int) extends AnyVal { // should fail with private constructor + def hours = secondsOfDay / 3600 + def minutes = (secondsOfDay / 60) % 60 + def seconds = secondsOfDay % 60 + + override def toString = "%02d:%02d:%02d".format(hours, minutes, seconds) +} +} diff --git a/test/files/run/genericValueClass.check b/test/files/run/genericValueClass.check new file mode 100644 index 0000000000..ec3a41a6a9 --- /dev/null +++ b/test/files/run/genericValueClass.check @@ -0,0 +1,2 @@ +(1,abc) +(2,def) diff --git a/test/files/run/genericValueClass.scala b/test/files/run/genericValueClass.scala new file mode 100644 index 0000000000..68162bb685 --- /dev/null +++ b/test/files/run/genericValueClass.scala @@ -0,0 +1,17 @@ +final class ArrowAssoc[A](val __leftOfArrow: A) extends AnyVal { + @inline def -> [B](y: B): Tuple2[A, B] = Tuple2(__leftOfArrow, y) + def →[B](y: B): Tuple2[A, B] = ->(y) +} + +object Test extends App { + { + @inline implicit def any2ArrowAssoc[A](x: A): ArrowAssoc[A] = new ArrowAssoc(x) + val x = 1 -> "abc" + println(x) + } + + { + val y = 2 -> "def" + println(y) + } +} -- cgit v1.2.3 From fa55e4f0f8d2834becdb9a9aef9c3ea65cb31fee Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Mon, 5 Mar 2012 16:07:51 +0100 Subject: Added check that primary constructor of a value class must be public. --- src/compiler/scala/tools/nsc/typechecker/Typers.scala | 15 +++++++++------ test/files/neg/valueclasses-doubledefs.scala | 6 ++++++ 2 files changed, 15 insertions(+), 6 deletions(-) create mode 100644 test/files/neg/valueclasses-doubledefs.scala (limited to 'test/files') diff --git a/src/compiler/scala/tools/nsc/typechecker/Typers.scala b/src/compiler/scala/tools/nsc/typechecker/Typers.scala index 7f6e253045..20616e7af2 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Typers.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Typers.scala @@ -1195,23 +1195,26 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser { private def validateDerivedValueClass(clazz: Symbol, body: List[Tree]) = { if (clazz.isTrait) - unit.error(clazz.pos, "Only classes (not traits) are allowed to extend AnyVal") + unit.error(clazz.pos, "only classes (not traits) are allowed to extend AnyVal") if (!clazz.isStatic) - unit.error(clazz.pos, "Value class may not be a "+ + unit.error(clazz.pos, "value class may not be a "+ (if (clazz.owner.isTerm) "local class" else "member of another class")) + val constr = clazz.primaryConstructor + if ((constr hasFlag (PRIVATE | PROTECTED)) || constr.privateWithin != NoSymbol) + unit.error(constr.pos, "value class must have public primary constructor") clazz.info.decls.toList.filter(acc => acc.isMethod && (acc hasFlag PARAMACCESSOR)) match { case List(acc) => def isUnderlyingAcc(sym: Symbol) = 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") + unit.error(acc.pos, "value class needs to have a publicly accessible val parameter") 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) + 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") + unit.error(clazz.pos, "value class needs to have exactly one public val parameter") } for (tparam <- clazz.typeParams) if (tparam hasAnnotation definitions.SpecializedClass) diff --git a/test/files/neg/valueclasses-doubledefs.scala b/test/files/neg/valueclasses-doubledefs.scala new file mode 100644 index 0000000000..87bcf8fee3 --- /dev/null +++ b/test/files/neg/valueclasses-doubledefs.scala @@ -0,0 +1,6 @@ +class Meter(val x: Double) extends AnyVal + +class Foo { + def apply(x: Double) = x.toString + def apply(x: Meter) = x.toString +} -- cgit v1.2.3 From 1e9277689461452c594dc547dc0b0ceab8cd3e7d Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Tue, 6 Mar 2012 17:48:42 +0100 Subject: Fixes to value classes: Flags now double definitions, private constructors as errors. Fixed erasure scheme. --- src/build/genprod.scala | 2 +- .../scala/tools/nsc/transform/Erasure.scala | 6 +++-- src/library/scala/Function0.scala | 8 +++--- src/library/scala/Function1.scala | 16 +++-------- src/library/scala/Function10.scala | 4 +-- src/library/scala/Function11.scala | 4 +-- src/library/scala/Function12.scala | 4 +-- src/library/scala/Function13.scala | 4 +-- src/library/scala/Function14.scala | 4 +-- src/library/scala/Function15.scala | 4 +-- src/library/scala/Function16.scala | 4 +-- src/library/scala/Function17.scala | 4 +-- src/library/scala/Function18.scala | 4 +-- src/library/scala/Function19.scala | 4 +-- src/library/scala/Function2.scala | 6 ++--- src/library/scala/Function20.scala | 4 +-- src/library/scala/Function21.scala | 4 +-- src/library/scala/Function22.scala | 4 +-- src/library/scala/Function3.scala | 4 +-- src/library/scala/Function4.scala | 4 +-- src/library/scala/Function5.scala | 4 +-- src/library/scala/Function6.scala | 4 +-- src/library/scala/Function7.scala | 4 +-- src/library/scala/Function8.scala | 4 +-- src/library/scala/Function9.scala | 4 +-- src/library/scala/Product.scala | 2 +- src/library/scala/Product1.scala | 6 ++--- src/library/scala/Product10.scala | 6 ++--- src/library/scala/Product11.scala | 6 ++--- src/library/scala/Product12.scala | 6 ++--- src/library/scala/Product13.scala | 6 ++--- src/library/scala/Product14.scala | 6 ++--- src/library/scala/Product15.scala | 6 ++--- src/library/scala/Product16.scala | 6 ++--- src/library/scala/Product17.scala | 6 ++--- src/library/scala/Product18.scala | 6 ++--- src/library/scala/Product19.scala | 6 ++--- src/library/scala/Product2.scala | 6 ++--- src/library/scala/Product20.scala | 6 ++--- src/library/scala/Product21.scala | 6 ++--- src/library/scala/Product22.scala | 6 ++--- src/library/scala/Product3.scala | 6 ++--- src/library/scala/Product4.scala | 6 ++--- src/library/scala/Product5.scala | 6 ++--- src/library/scala/Product6.scala | 6 ++--- src/library/scala/Product7.scala | 6 ++--- src/library/scala/Product8.scala | 6 ++--- src/library/scala/Product9.scala | 6 ++--- src/library/scala/Tuple1.scala | 2 +- src/library/scala/Tuple10.scala | 2 +- src/library/scala/Tuple11.scala | 2 +- src/library/scala/Tuple12.scala | 2 +- src/library/scala/Tuple13.scala | 2 +- src/library/scala/Tuple14.scala | 2 +- src/library/scala/Tuple15.scala | 2 +- src/library/scala/Tuple16.scala | 2 +- src/library/scala/Tuple17.scala | 2 +- src/library/scala/Tuple18.scala | 2 +- src/library/scala/Tuple19.scala | 2 +- src/library/scala/Tuple2.scala | 2 +- src/library/scala/Tuple20.scala | 2 +- src/library/scala/Tuple21.scala | 2 +- src/library/scala/Tuple22.scala | 2 +- src/library/scala/Tuple3.scala | 2 +- src/library/scala/Tuple4.scala | 2 +- src/library/scala/Tuple5.scala | 2 +- src/library/scala/Tuple6.scala | 2 +- src/library/scala/Tuple7.scala | 2 +- src/library/scala/Tuple8.scala | 2 +- src/library/scala/Tuple9.scala | 2 +- test/files/neg/anyval-anyref-parent.check | 6 ++--- test/files/neg/valueclasses-doubledefs.check | 7 +++++ test/files/neg/valueclasses.check | 31 ++++++++++++---------- test/files/run/valueclasses-constr.check | 2 ++ test/files/run/valueclasses-constr.scala | 25 +++++++++++++++++ 75 files changed, 199 insertions(+), 168 deletions(-) create mode 100644 test/files/neg/valueclasses-doubledefs.check create mode 100644 test/files/run/valueclasses-constr.check create mode 100644 test/files/run/valueclasses-constr.scala (limited to 'test/files') diff --git a/src/build/genprod.scala b/src/build/genprod.scala index 9e5b6810c1..a830ed90e4 100644 --- a/src/build/genprod.scala +++ b/src/build/genprod.scala @@ -603,7 +603,7 @@ object {className} {{ /** {className} is a cartesian product of {i} component{s}. * @since 2.3 */ -trait {className}{covariantArgs} extends Product {{ +trait {className}{covariantArgs} extends Any with Product {{ /** The arity of this product. * @return {i} */ diff --git a/src/compiler/scala/tools/nsc/transform/Erasure.scala b/src/compiler/scala/tools/nsc/transform/Erasure.scala index f3cb50e5c4..beb7083caa 100644 --- a/src/compiler/scala/tools/nsc/transform/Erasure.scala +++ b/src/compiler/scala/tools/nsc/transform/Erasure.scala @@ -642,8 +642,10 @@ abstract class Erasure extends AddInterfaces tree match { case InjectDerivedValue(arg) => val clazz = tree.symbol - util.trace("transforming inject "+arg+":"+underlyingOfValueClass(clazz)+"/"+ErasedValueType(clazz))( - typed1(arg, mode, underlyingOfValueClass(clazz)) setType ErasedValueType(clazz)) + val result = typed1(arg, mode, underlyingOfValueClass(clazz)) setType ErasedValueType(clazz) + log("transforming inject "+arg+":"+underlyingOfValueClass(clazz)+"/"+ErasedValueType(clazz)+" = "+result) + return result + case _ => super.typed1(adaptMember(tree), mode, pt) } diff --git a/src/library/scala/Function0.scala b/src/library/scala/Function0.scala index f68bbcc454..11b5ccd294 100644 --- a/src/library/scala/Function0.scala +++ b/src/library/scala/Function0.scala @@ -6,18 +6,18 @@ ** |/ ** \* */ // GENERATED CODE: DO NOT EDIT. -// genprod generated these sources at: Sun Jul 31 00:37:30 CEST 2011 +// genprod generated these sources at: Tue Mar 06 13:49:54 CET 2012 package scala /** A function of 0 parameters. - * + * * In the following example, the definition of javaVersion is a * shorthand for the anonymous class definition anonfun0: * * {{{ - * object Main extends Application { + * object Main extends App { * val javaVersion = () => sys.props("java.version") * * val anonfun0 = new Function0[String] { @@ -32,6 +32,6 @@ trait Function0[@specialized +R] extends AnyRef { self => * @return the result of function application. */ def apply(): R - + override def toString() = "" } diff --git a/src/library/scala/Function1.scala b/src/library/scala/Function1.scala index 7517e6604b..c07b06f10c 100644 --- a/src/library/scala/Function1.scala +++ b/src/library/scala/Function1.scala @@ -11,12 +11,12 @@ package scala /** A function of 1 parameter. - * + * * In the following example, the definition of succ is a * shorthand for the anonymous class definition anonfun1: * * {{{ - * object Main extends Application { + * object Main extends App { * val succ = (x: Int) => x + 1 * val anonfun1 = new Function1[Int, Int] { * def apply(x: Int): Int = x + 1 @@ -24,22 +24,14 @@ package scala * assert(succ(0) == anonfun1(0)) * } * }}} - * - * Note that `Function1` does not define a total function, as might - * be suggested by the existence of [[scala.PartialFunction]]. The only - * distinction between `Function1` and `PartialFunction` is that the - * latter can specify inputs which it will not handle. - * */ @annotation.implicitNotFound(msg = "No implicit view available from ${T1} => ${R}.") trait Function1[@specialized(scala.Int, scala.Long, scala.Float, scala.Double) -T1, @specialized(scala.Unit, scala.Boolean, scala.Int, scala.Float, scala.Long, scala.Double) +R] extends AnyRef { self => - /** Apply the body of this function to the argument. It may throw an - * exception. - * + /** Apply the body of this function to the argument. * @return the result of function application. */ def apply(v1: T1): R - + /** Composes two instances of Function1 in a new Function1, with this function applied last. * * @tparam A the type to which function `g` can be applied diff --git a/src/library/scala/Function10.scala b/src/library/scala/Function10.scala index 6f17606afd..47a5076628 100644 --- a/src/library/scala/Function10.scala +++ b/src/library/scala/Function10.scala @@ -11,14 +11,14 @@ package scala /** A function of 10 parameters. - * + * */ trait Function10[-T1, -T2, -T3, -T4, -T5, -T6, -T7, -T8, -T9, -T10, +R] extends AnyRef { self => /** Apply the body of this function to the arguments. * @return the result of function application. */ def apply(v1: T1, v2: T2, v3: T3, v4: T4, v5: T5, v6: T6, v7: T7, v8: T8, v9: T9, v10: T10): R - + /** Creates a curried version of this function. * * @return a function `f` such that `f(x1)(x2)(x3)(x4)(x5)(x6)(x7)(x8)(x9)(x10) == apply(x1, x2, x3, x4, x5, x6, x7, x8, x9, x10)` diff --git a/src/library/scala/Function11.scala b/src/library/scala/Function11.scala index 7a73bd35bf..4decd653fc 100644 --- a/src/library/scala/Function11.scala +++ b/src/library/scala/Function11.scala @@ -11,14 +11,14 @@ package scala /** A function of 11 parameters. - * + * */ trait Function11[-T1, -T2, -T3, -T4, -T5, -T6, -T7, -T8, -T9, -T10, -T11, +R] extends AnyRef { self => /** Apply the body of this function to the arguments. * @return the result of function application. */ def apply(v1: T1, v2: T2, v3: T3, v4: T4, v5: T5, v6: T6, v7: T7, v8: T8, v9: T9, v10: T10, v11: T11): R - + /** Creates a curried version of this function. * * @return a function `f` such that `f(x1)(x2)(x3)(x4)(x5)(x6)(x7)(x8)(x9)(x10)(x11) == apply(x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11)` diff --git a/src/library/scala/Function12.scala b/src/library/scala/Function12.scala index c099c0436a..58b0b448b3 100644 --- a/src/library/scala/Function12.scala +++ b/src/library/scala/Function12.scala @@ -11,14 +11,14 @@ package scala /** A function of 12 parameters. - * + * */ trait Function12[-T1, -T2, -T3, -T4, -T5, -T6, -T7, -T8, -T9, -T10, -T11, -T12, +R] extends AnyRef { self => /** Apply the body of this function to the arguments. * @return the result of function application. */ def apply(v1: T1, v2: T2, v3: T3, v4: T4, v5: T5, v6: T6, v7: T7, v8: T8, v9: T9, v10: T10, v11: T11, v12: T12): R - + /** Creates a curried version of this function. * * @return a function `f` such that `f(x1)(x2)(x3)(x4)(x5)(x6)(x7)(x8)(x9)(x10)(x11)(x12) == apply(x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12)` diff --git a/src/library/scala/Function13.scala b/src/library/scala/Function13.scala index f13db28f30..256518e898 100644 --- a/src/library/scala/Function13.scala +++ b/src/library/scala/Function13.scala @@ -11,14 +11,14 @@ package scala /** A function of 13 parameters. - * + * */ trait Function13[-T1, -T2, -T3, -T4, -T5, -T6, -T7, -T8, -T9, -T10, -T11, -T12, -T13, +R] extends AnyRef { self => /** Apply the body of this function to the arguments. * @return the result of function application. */ def apply(v1: T1, v2: T2, v3: T3, v4: T4, v5: T5, v6: T6, v7: T7, v8: T8, v9: T9, v10: T10, v11: T11, v12: T12, v13: T13): R - + /** Creates a curried version of this function. * * @return a function `f` such that `f(x1)(x2)(x3)(x4)(x5)(x6)(x7)(x8)(x9)(x10)(x11)(x12)(x13) == apply(x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13)` diff --git a/src/library/scala/Function14.scala b/src/library/scala/Function14.scala index d0345cc552..26e3b83eee 100644 --- a/src/library/scala/Function14.scala +++ b/src/library/scala/Function14.scala @@ -11,14 +11,14 @@ package scala /** A function of 14 parameters. - * + * */ trait Function14[-T1, -T2, -T3, -T4, -T5, -T6, -T7, -T8, -T9, -T10, -T11, -T12, -T13, -T14, +R] extends AnyRef { self => /** Apply the body of this function to the arguments. * @return the result of function application. */ def apply(v1: T1, v2: T2, v3: T3, v4: T4, v5: T5, v6: T6, v7: T7, v8: T8, v9: T9, v10: T10, v11: T11, v12: T12, v13: T13, v14: T14): R - + /** Creates a curried version of this function. * * @return a function `f` such that `f(x1)(x2)(x3)(x4)(x5)(x6)(x7)(x8)(x9)(x10)(x11)(x12)(x13)(x14) == apply(x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14)` diff --git a/src/library/scala/Function15.scala b/src/library/scala/Function15.scala index 69ff039f5b..a0911b08e2 100644 --- a/src/library/scala/Function15.scala +++ b/src/library/scala/Function15.scala @@ -11,14 +11,14 @@ package scala /** A function of 15 parameters. - * + * */ trait Function15[-T1, -T2, -T3, -T4, -T5, -T6, -T7, -T8, -T9, -T10, -T11, -T12, -T13, -T14, -T15, +R] extends AnyRef { self => /** Apply the body of this function to the arguments. * @return the result of function application. */ def apply(v1: T1, v2: T2, v3: T3, v4: T4, v5: T5, v6: T6, v7: T7, v8: T8, v9: T9, v10: T10, v11: T11, v12: T12, v13: T13, v14: T14, v15: T15): R - + /** Creates a curried version of this function. * * @return a function `f` such that `f(x1)(x2)(x3)(x4)(x5)(x6)(x7)(x8)(x9)(x10)(x11)(x12)(x13)(x14)(x15) == apply(x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15)` diff --git a/src/library/scala/Function16.scala b/src/library/scala/Function16.scala index d544d89303..9d014842da 100644 --- a/src/library/scala/Function16.scala +++ b/src/library/scala/Function16.scala @@ -11,14 +11,14 @@ package scala /** A function of 16 parameters. - * + * */ trait Function16[-T1, -T2, -T3, -T4, -T5, -T6, -T7, -T8, -T9, -T10, -T11, -T12, -T13, -T14, -T15, -T16, +R] extends AnyRef { self => /** Apply the body of this function to the arguments. * @return the result of function application. */ def apply(v1: T1, v2: T2, v3: T3, v4: T4, v5: T5, v6: T6, v7: T7, v8: T8, v9: T9, v10: T10, v11: T11, v12: T12, v13: T13, v14: T14, v15: T15, v16: T16): R - + /** Creates a curried version of this function. * * @return a function `f` such that `f(x1)(x2)(x3)(x4)(x5)(x6)(x7)(x8)(x9)(x10)(x11)(x12)(x13)(x14)(x15)(x16) == apply(x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16)` diff --git a/src/library/scala/Function17.scala b/src/library/scala/Function17.scala index 16c71e7ada..19f2df9c6f 100644 --- a/src/library/scala/Function17.scala +++ b/src/library/scala/Function17.scala @@ -11,14 +11,14 @@ package scala /** A function of 17 parameters. - * + * */ trait Function17[-T1, -T2, -T3, -T4, -T5, -T6, -T7, -T8, -T9, -T10, -T11, -T12, -T13, -T14, -T15, -T16, -T17, +R] extends AnyRef { self => /** Apply the body of this function to the arguments. * @return the result of function application. */ def apply(v1: T1, v2: T2, v3: T3, v4: T4, v5: T5, v6: T6, v7: T7, v8: T8, v9: T9, v10: T10, v11: T11, v12: T12, v13: T13, v14: T14, v15: T15, v16: T16, v17: T17): R - + /** Creates a curried version of this function. * * @return a function `f` such that `f(x1)(x2)(x3)(x4)(x5)(x6)(x7)(x8)(x9)(x10)(x11)(x12)(x13)(x14)(x15)(x16)(x17) == apply(x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16, x17)` diff --git a/src/library/scala/Function18.scala b/src/library/scala/Function18.scala index dfd70c2353..4176678335 100644 --- a/src/library/scala/Function18.scala +++ b/src/library/scala/Function18.scala @@ -11,14 +11,14 @@ package scala /** A function of 18 parameters. - * + * */ trait Function18[-T1, -T2, -T3, -T4, -T5, -T6, -T7, -T8, -T9, -T10, -T11, -T12, -T13, -T14, -T15, -T16, -T17, -T18, +R] extends AnyRef { self => /** Apply the body of this function to the arguments. * @return the result of function application. */ def apply(v1: T1, v2: T2, v3: T3, v4: T4, v5: T5, v6: T6, v7: T7, v8: T8, v9: T9, v10: T10, v11: T11, v12: T12, v13: T13, v14: T14, v15: T15, v16: T16, v17: T17, v18: T18): R - + /** Creates a curried version of this function. * * @return a function `f` such that `f(x1)(x2)(x3)(x4)(x5)(x6)(x7)(x8)(x9)(x10)(x11)(x12)(x13)(x14)(x15)(x16)(x17)(x18) == apply(x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16, x17, x18)` diff --git a/src/library/scala/Function19.scala b/src/library/scala/Function19.scala index 63decd03ad..4d6a3779ba 100644 --- a/src/library/scala/Function19.scala +++ b/src/library/scala/Function19.scala @@ -11,14 +11,14 @@ package scala /** A function of 19 parameters. - * + * */ trait Function19[-T1, -T2, -T3, -T4, -T5, -T6, -T7, -T8, -T9, -T10, -T11, -T12, -T13, -T14, -T15, -T16, -T17, -T18, -T19, +R] extends AnyRef { self => /** Apply the body of this function to the arguments. * @return the result of function application. */ def apply(v1: T1, v2: T2, v3: T3, v4: T4, v5: T5, v6: T6, v7: T7, v8: T8, v9: T9, v10: T10, v11: T11, v12: T12, v13: T13, v14: T14, v15: T15, v16: T16, v17: T17, v18: T18, v19: T19): R - + /** Creates a curried version of this function. * * @return a function `f` such that `f(x1)(x2)(x3)(x4)(x5)(x6)(x7)(x8)(x9)(x10)(x11)(x12)(x13)(x14)(x15)(x16)(x17)(x18)(x19) == apply(x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16, x17, x18, x19)` diff --git a/src/library/scala/Function2.scala b/src/library/scala/Function2.scala index a4ad87fa97..9062b699c8 100644 --- a/src/library/scala/Function2.scala +++ b/src/library/scala/Function2.scala @@ -11,12 +11,12 @@ package scala /** A function of 2 parameters. - * + * * In the following example, the definition of max is a * shorthand for the anonymous class definition anonfun2: * * {{{ - * object Main extends Application { + * object Main extends App { * val max = (x: Int, y: Int) => if (x < y) y else x * * val anonfun2 = new Function2[Int, Int, Int] { @@ -31,7 +31,7 @@ trait Function2[@specialized(scala.Int, scala.Long, scala.Double) -T1, @speciali * @return the result of function application. */ def apply(v1: T1, v2: T2): R - + /** Creates a curried version of this function. * * @return a function `f` such that `f(x1)(x2) == apply(x1, x2)` diff --git a/src/library/scala/Function20.scala b/src/library/scala/Function20.scala index 7219c9be81..3568805e4f 100644 --- a/src/library/scala/Function20.scala +++ b/src/library/scala/Function20.scala @@ -11,14 +11,14 @@ package scala /** A function of 20 parameters. - * + * */ trait Function20[-T1, -T2, -T3, -T4, -T5, -T6, -T7, -T8, -T9, -T10, -T11, -T12, -T13, -T14, -T15, -T16, -T17, -T18, -T19, -T20, +R] extends AnyRef { self => /** Apply the body of this function to the arguments. * @return the result of function application. */ def apply(v1: T1, v2: T2, v3: T3, v4: T4, v5: T5, v6: T6, v7: T7, v8: T8, v9: T9, v10: T10, v11: T11, v12: T12, v13: T13, v14: T14, v15: T15, v16: T16, v17: T17, v18: T18, v19: T19, v20: T20): R - + /** Creates a curried version of this function. * * @return a function `f` such that `f(x1)(x2)(x3)(x4)(x5)(x6)(x7)(x8)(x9)(x10)(x11)(x12)(x13)(x14)(x15)(x16)(x17)(x18)(x19)(x20) == apply(x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16, x17, x18, x19, x20)` diff --git a/src/library/scala/Function21.scala b/src/library/scala/Function21.scala index c7d55960db..d700c01a7d 100644 --- a/src/library/scala/Function21.scala +++ b/src/library/scala/Function21.scala @@ -11,14 +11,14 @@ package scala /** A function of 21 parameters. - * + * */ trait Function21[-T1, -T2, -T3, -T4, -T5, -T6, -T7, -T8, -T9, -T10, -T11, -T12, -T13, -T14, -T15, -T16, -T17, -T18, -T19, -T20, -T21, +R] extends AnyRef { self => /** Apply the body of this function to the arguments. * @return the result of function application. */ def apply(v1: T1, v2: T2, v3: T3, v4: T4, v5: T5, v6: T6, v7: T7, v8: T8, v9: T9, v10: T10, v11: T11, v12: T12, v13: T13, v14: T14, v15: T15, v16: T16, v17: T17, v18: T18, v19: T19, v20: T20, v21: T21): R - + /** Creates a curried version of this function. * * @return a function `f` such that `f(x1)(x2)(x3)(x4)(x5)(x6)(x7)(x8)(x9)(x10)(x11)(x12)(x13)(x14)(x15)(x16)(x17)(x18)(x19)(x20)(x21) == apply(x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16, x17, x18, x19, x20, x21)` diff --git a/src/library/scala/Function22.scala b/src/library/scala/Function22.scala index 196421c830..f4f053ccb0 100644 --- a/src/library/scala/Function22.scala +++ b/src/library/scala/Function22.scala @@ -11,14 +11,14 @@ package scala /** A function of 22 parameters. - * + * */ trait Function22[-T1, -T2, -T3, -T4, -T5, -T6, -T7, -T8, -T9, -T10, -T11, -T12, -T13, -T14, -T15, -T16, -T17, -T18, -T19, -T20, -T21, -T22, +R] extends AnyRef { self => /** Apply the body of this function to the arguments. * @return the result of function application. */ def apply(v1: T1, v2: T2, v3: T3, v4: T4, v5: T5, v6: T6, v7: T7, v8: T8, v9: T9, v10: T10, v11: T11, v12: T12, v13: T13, v14: T14, v15: T15, v16: T16, v17: T17, v18: T18, v19: T19, v20: T20, v21: T21, v22: T22): R - + /** Creates a curried version of this function. * * @return a function `f` such that `f(x1)(x2)(x3)(x4)(x5)(x6)(x7)(x8)(x9)(x10)(x11)(x12)(x13)(x14)(x15)(x16)(x17)(x18)(x19)(x20)(x21)(x22) == apply(x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16, x17, x18, x19, x20, x21, x22)` diff --git a/src/library/scala/Function3.scala b/src/library/scala/Function3.scala index 09a5aa5828..96c4f23947 100644 --- a/src/library/scala/Function3.scala +++ b/src/library/scala/Function3.scala @@ -11,14 +11,14 @@ package scala /** A function of 3 parameters. - * + * */ trait Function3[-T1, -T2, -T3, +R] extends AnyRef { self => /** Apply the body of this function to the arguments. * @return the result of function application. */ def apply(v1: T1, v2: T2, v3: T3): R - + /** Creates a curried version of this function. * * @return a function `f` such that `f(x1)(x2)(x3) == apply(x1, x2, x3)` diff --git a/src/library/scala/Function4.scala b/src/library/scala/Function4.scala index 00da84636a..b07d761676 100644 --- a/src/library/scala/Function4.scala +++ b/src/library/scala/Function4.scala @@ -11,14 +11,14 @@ package scala /** A function of 4 parameters. - * + * */ trait Function4[-T1, -T2, -T3, -T4, +R] extends AnyRef { self => /** Apply the body of this function to the arguments. * @return the result of function application. */ def apply(v1: T1, v2: T2, v3: T3, v4: T4): R - + /** Creates a curried version of this function. * * @return a function `f` such that `f(x1)(x2)(x3)(x4) == apply(x1, x2, x3, x4)` diff --git a/src/library/scala/Function5.scala b/src/library/scala/Function5.scala index 3915048906..4c3a2bf4b0 100644 --- a/src/library/scala/Function5.scala +++ b/src/library/scala/Function5.scala @@ -11,14 +11,14 @@ package scala /** A function of 5 parameters. - * + * */ trait Function5[-T1, -T2, -T3, -T4, -T5, +R] extends AnyRef { self => /** Apply the body of this function to the arguments. * @return the result of function application. */ def apply(v1: T1, v2: T2, v3: T3, v4: T4, v5: T5): R - + /** Creates a curried version of this function. * * @return a function `f` such that `f(x1)(x2)(x3)(x4)(x5) == apply(x1, x2, x3, x4, x5)` diff --git a/src/library/scala/Function6.scala b/src/library/scala/Function6.scala index 183a7332e1..f1afbb9f25 100644 --- a/src/library/scala/Function6.scala +++ b/src/library/scala/Function6.scala @@ -11,14 +11,14 @@ package scala /** A function of 6 parameters. - * + * */ trait Function6[-T1, -T2, -T3, -T4, -T5, -T6, +R] extends AnyRef { self => /** Apply the body of this function to the arguments. * @return the result of function application. */ def apply(v1: T1, v2: T2, v3: T3, v4: T4, v5: T5, v6: T6): R - + /** Creates a curried version of this function. * * @return a function `f` such that `f(x1)(x2)(x3)(x4)(x5)(x6) == apply(x1, x2, x3, x4, x5, x6)` diff --git a/src/library/scala/Function7.scala b/src/library/scala/Function7.scala index 10f8e9b599..4eda7059e8 100644 --- a/src/library/scala/Function7.scala +++ b/src/library/scala/Function7.scala @@ -11,14 +11,14 @@ package scala /** A function of 7 parameters. - * + * */ trait Function7[-T1, -T2, -T3, -T4, -T5, -T6, -T7, +R] extends AnyRef { self => /** Apply the body of this function to the arguments. * @return the result of function application. */ def apply(v1: T1, v2: T2, v3: T3, v4: T4, v5: T5, v6: T6, v7: T7): R - + /** Creates a curried version of this function. * * @return a function `f` such that `f(x1)(x2)(x3)(x4)(x5)(x6)(x7) == apply(x1, x2, x3, x4, x5, x6, x7)` diff --git a/src/library/scala/Function8.scala b/src/library/scala/Function8.scala index 8144b36101..582ee2ee3b 100644 --- a/src/library/scala/Function8.scala +++ b/src/library/scala/Function8.scala @@ -11,14 +11,14 @@ package scala /** A function of 8 parameters. - * + * */ trait Function8[-T1, -T2, -T3, -T4, -T5, -T6, -T7, -T8, +R] extends AnyRef { self => /** Apply the body of this function to the arguments. * @return the result of function application. */ def apply(v1: T1, v2: T2, v3: T3, v4: T4, v5: T5, v6: T6, v7: T7, v8: T8): R - + /** Creates a curried version of this function. * * @return a function `f` such that `f(x1)(x2)(x3)(x4)(x5)(x6)(x7)(x8) == apply(x1, x2, x3, x4, x5, x6, x7, x8)` diff --git a/src/library/scala/Function9.scala b/src/library/scala/Function9.scala index ee04ed0915..2adbc2bbdb 100644 --- a/src/library/scala/Function9.scala +++ b/src/library/scala/Function9.scala @@ -11,14 +11,14 @@ package scala /** A function of 9 parameters. - * + * */ trait Function9[-T1, -T2, -T3, -T4, -T5, -T6, -T7, -T8, -T9, +R] extends AnyRef { self => /** Apply the body of this function to the arguments. * @return the result of function application. */ def apply(v1: T1, v2: T2, v3: T3, v4: T4, v5: T5, v6: T6, v7: T7, v8: T8, v9: T9): R - + /** Creates a curried version of this function. * * @return a function `f` such that `f(x1)(x2)(x3)(x4)(x5)(x6)(x7)(x8)(x9) == apply(x1, x2, x3, x4, x5, x6, x7, x8, x9)` diff --git a/src/library/scala/Product.scala b/src/library/scala/Product.scala index 90ae82b6d0..1459ab9ea5 100644 --- a/src/library/scala/Product.scala +++ b/src/library/scala/Product.scala @@ -17,7 +17,7 @@ package scala * @version 1.0 * @since 2.3 */ -trait Product extends Equals { +trait Product extends Any with Equals { /** The n^th^ element of this product, 0-based. In other words, for a * product `A(x,,1,,, ..., x,,k,,)`, returns `x,,(n+1),, where `0 < n < k`. * diff --git a/src/library/scala/Product1.scala b/src/library/scala/Product1.scala index ab8b0a4505..d268b35f60 100644 --- a/src/library/scala/Product1.scala +++ b/src/library/scala/Product1.scala @@ -17,13 +17,13 @@ object Product1 { /** Product1 is a cartesian product of 1 component. * @since 2.3 */ -trait Product1[@specialized(Int, Long, Double) +T1] extends Product { +trait Product1[@specialized(Int, Long, Double) +T1] extends Any with Product { /** The arity of this product. * @return 1 */ override def productArity = 1 - + /** Returns the n-th projection of this product if 0 < n <= productArity, * otherwise throws an `IndexOutOfBoundsException`. * @@ -33,7 +33,7 @@ trait Product1[@specialized(Int, Long, Double) +T1] extends Product { */ @throws(classOf[IndexOutOfBoundsException]) - override def productElement(n: Int) = n match { + override def productElement(n: Int) = n match { case 0 => _1 case _ => throw new IndexOutOfBoundsException(n.toString()) } diff --git a/src/library/scala/Product10.scala b/src/library/scala/Product10.scala index 536fb2fed9..cae9e5a664 100644 --- a/src/library/scala/Product10.scala +++ b/src/library/scala/Product10.scala @@ -17,13 +17,13 @@ object Product10 { /** Product10 is a cartesian product of 10 components. * @since 2.3 */ -trait Product10[+T1, +T2, +T3, +T4, +T5, +T6, +T7, +T8, +T9, +T10] extends Product { +trait Product10[+T1, +T2, +T3, +T4, +T5, +T6, +T7, +T8, +T9, +T10] extends Any with Product { /** The arity of this product. * @return 10 */ override def productArity = 10 - + /** Returns the n-th projection of this product if 0 < n <= productArity, * otherwise throws an `IndexOutOfBoundsException`. * @@ -33,7 +33,7 @@ trait Product10[+T1, +T2, +T3, +T4, +T5, +T6, +T7, +T8, +T9, +T10] extends Produ */ @throws(classOf[IndexOutOfBoundsException]) - override def productElement(n: Int) = n match { + override def productElement(n: Int) = n match { case 0 => _1 case 1 => _2 case 2 => _3 diff --git a/src/library/scala/Product11.scala b/src/library/scala/Product11.scala index 7d49eccc5e..0647b28414 100644 --- a/src/library/scala/Product11.scala +++ b/src/library/scala/Product11.scala @@ -17,13 +17,13 @@ object Product11 { /** Product11 is a cartesian product of 11 components. * @since 2.3 */ -trait Product11[+T1, +T2, +T3, +T4, +T5, +T6, +T7, +T8, +T9, +T10, +T11] extends Product { +trait Product11[+T1, +T2, +T3, +T4, +T5, +T6, +T7, +T8, +T9, +T10, +T11] extends Any with Product { /** The arity of this product. * @return 11 */ override def productArity = 11 - + /** Returns the n-th projection of this product if 0 < n <= productArity, * otherwise throws an `IndexOutOfBoundsException`. * @@ -33,7 +33,7 @@ trait Product11[+T1, +T2, +T3, +T4, +T5, +T6, +T7, +T8, +T9, +T10, +T11] extends */ @throws(classOf[IndexOutOfBoundsException]) - override def productElement(n: Int) = n match { + override def productElement(n: Int) = n match { case 0 => _1 case 1 => _2 case 2 => _3 diff --git a/src/library/scala/Product12.scala b/src/library/scala/Product12.scala index 0e9c4a01a2..a080aafa7a 100644 --- a/src/library/scala/Product12.scala +++ b/src/library/scala/Product12.scala @@ -17,13 +17,13 @@ object Product12 { /** Product12 is a cartesian product of 12 components. * @since 2.3 */ -trait Product12[+T1, +T2, +T3, +T4, +T5, +T6, +T7, +T8, +T9, +T10, +T11, +T12] extends Product { +trait Product12[+T1, +T2, +T3, +T4, +T5, +T6, +T7, +T8, +T9, +T10, +T11, +T12] extends Any with Product { /** The arity of this product. * @return 12 */ override def productArity = 12 - + /** Returns the n-th projection of this product if 0 < n <= productArity, * otherwise throws an `IndexOutOfBoundsException`. * @@ -33,7 +33,7 @@ trait Product12[+T1, +T2, +T3, +T4, +T5, +T6, +T7, +T8, +T9, +T10, +T11, +T12] e */ @throws(classOf[IndexOutOfBoundsException]) - override def productElement(n: Int) = n match { + override def productElement(n: Int) = n match { case 0 => _1 case 1 => _2 case 2 => _3 diff --git a/src/library/scala/Product13.scala b/src/library/scala/Product13.scala index a0629201d0..425aebf3e7 100644 --- a/src/library/scala/Product13.scala +++ b/src/library/scala/Product13.scala @@ -17,13 +17,13 @@ object Product13 { /** Product13 is a cartesian product of 13 components. * @since 2.3 */ -trait Product13[+T1, +T2, +T3, +T4, +T5, +T6, +T7, +T8, +T9, +T10, +T11, +T12, +T13] extends Product { +trait Product13[+T1, +T2, +T3, +T4, +T5, +T6, +T7, +T8, +T9, +T10, +T11, +T12, +T13] extends Any with Product { /** The arity of this product. * @return 13 */ override def productArity = 13 - + /** Returns the n-th projection of this product if 0 < n <= productArity, * otherwise throws an `IndexOutOfBoundsException`. * @@ -33,7 +33,7 @@ trait Product13[+T1, +T2, +T3, +T4, +T5, +T6, +T7, +T8, +T9, +T10, +T11, +T12, + */ @throws(classOf[IndexOutOfBoundsException]) - override def productElement(n: Int) = n match { + override def productElement(n: Int) = n match { case 0 => _1 case 1 => _2 case 2 => _3 diff --git a/src/library/scala/Product14.scala b/src/library/scala/Product14.scala index 32dda81c3e..3d7e4896ef 100644 --- a/src/library/scala/Product14.scala +++ b/src/library/scala/Product14.scala @@ -17,13 +17,13 @@ object Product14 { /** Product14 is a cartesian product of 14 components. * @since 2.3 */ -trait Product14[+T1, +T2, +T3, +T4, +T5, +T6, +T7, +T8, +T9, +T10, +T11, +T12, +T13, +T14] extends Product { +trait Product14[+T1, +T2, +T3, +T4, +T5, +T6, +T7, +T8, +T9, +T10, +T11, +T12, +T13, +T14] extends Any with Product { /** The arity of this product. * @return 14 */ override def productArity = 14 - + /** Returns the n-th projection of this product if 0 < n <= productArity, * otherwise throws an `IndexOutOfBoundsException`. * @@ -33,7 +33,7 @@ trait Product14[+T1, +T2, +T3, +T4, +T5, +T6, +T7, +T8, +T9, +T10, +T11, +T12, + */ @throws(classOf[IndexOutOfBoundsException]) - override def productElement(n: Int) = n match { + override def productElement(n: Int) = n match { case 0 => _1 case 1 => _2 case 2 => _3 diff --git a/src/library/scala/Product15.scala b/src/library/scala/Product15.scala index 57851f9870..7bca7a2a1b 100644 --- a/src/library/scala/Product15.scala +++ b/src/library/scala/Product15.scala @@ -17,13 +17,13 @@ object Product15 { /** Product15 is a cartesian product of 15 components. * @since 2.3 */ -trait Product15[+T1, +T2, +T3, +T4, +T5, +T6, +T7, +T8, +T9, +T10, +T11, +T12, +T13, +T14, +T15] extends Product { +trait Product15[+T1, +T2, +T3, +T4, +T5, +T6, +T7, +T8, +T9, +T10, +T11, +T12, +T13, +T14, +T15] extends Any with Product { /** The arity of this product. * @return 15 */ override def productArity = 15 - + /** Returns the n-th projection of this product if 0 < n <= productArity, * otherwise throws an `IndexOutOfBoundsException`. * @@ -33,7 +33,7 @@ trait Product15[+T1, +T2, +T3, +T4, +T5, +T6, +T7, +T8, +T9, +T10, +T11, +T12, + */ @throws(classOf[IndexOutOfBoundsException]) - override def productElement(n: Int) = n match { + override def productElement(n: Int) = n match { case 0 => _1 case 1 => _2 case 2 => _3 diff --git a/src/library/scala/Product16.scala b/src/library/scala/Product16.scala index 75076f3b3c..c5042cbc90 100644 --- a/src/library/scala/Product16.scala +++ b/src/library/scala/Product16.scala @@ -17,13 +17,13 @@ object Product16 { /** Product16 is a cartesian product of 16 components. * @since 2.3 */ -trait Product16[+T1, +T2, +T3, +T4, +T5, +T6, +T7, +T8, +T9, +T10, +T11, +T12, +T13, +T14, +T15, +T16] extends Product { +trait Product16[+T1, +T2, +T3, +T4, +T5, +T6, +T7, +T8, +T9, +T10, +T11, +T12, +T13, +T14, +T15, +T16] extends Any with Product { /** The arity of this product. * @return 16 */ override def productArity = 16 - + /** Returns the n-th projection of this product if 0 < n <= productArity, * otherwise throws an `IndexOutOfBoundsException`. * @@ -33,7 +33,7 @@ trait Product16[+T1, +T2, +T3, +T4, +T5, +T6, +T7, +T8, +T9, +T10, +T11, +T12, + */ @throws(classOf[IndexOutOfBoundsException]) - override def productElement(n: Int) = n match { + override def productElement(n: Int) = n match { case 0 => _1 case 1 => _2 case 2 => _3 diff --git a/src/library/scala/Product17.scala b/src/library/scala/Product17.scala index 9ee6072ffe..b5651ec712 100644 --- a/src/library/scala/Product17.scala +++ b/src/library/scala/Product17.scala @@ -17,13 +17,13 @@ object Product17 { /** Product17 is a cartesian product of 17 components. * @since 2.3 */ -trait Product17[+T1, +T2, +T3, +T4, +T5, +T6, +T7, +T8, +T9, +T10, +T11, +T12, +T13, +T14, +T15, +T16, +T17] extends Product { +trait Product17[+T1, +T2, +T3, +T4, +T5, +T6, +T7, +T8, +T9, +T10, +T11, +T12, +T13, +T14, +T15, +T16, +T17] extends Any with Product { /** The arity of this product. * @return 17 */ override def productArity = 17 - + /** Returns the n-th projection of this product if 0 < n <= productArity, * otherwise throws an `IndexOutOfBoundsException`. * @@ -33,7 +33,7 @@ trait Product17[+T1, +T2, +T3, +T4, +T5, +T6, +T7, +T8, +T9, +T10, +T11, +T12, + */ @throws(classOf[IndexOutOfBoundsException]) - override def productElement(n: Int) = n match { + override def productElement(n: Int) = n match { case 0 => _1 case 1 => _2 case 2 => _3 diff --git a/src/library/scala/Product18.scala b/src/library/scala/Product18.scala index 25d0839af1..088a48ae32 100644 --- a/src/library/scala/Product18.scala +++ b/src/library/scala/Product18.scala @@ -17,13 +17,13 @@ object Product18 { /** Product18 is a cartesian product of 18 components. * @since 2.3 */ -trait Product18[+T1, +T2, +T3, +T4, +T5, +T6, +T7, +T8, +T9, +T10, +T11, +T12, +T13, +T14, +T15, +T16, +T17, +T18] extends Product { +trait Product18[+T1, +T2, +T3, +T4, +T5, +T6, +T7, +T8, +T9, +T10, +T11, +T12, +T13, +T14, +T15, +T16, +T17, +T18] extends Any with Product { /** The arity of this product. * @return 18 */ override def productArity = 18 - + /** Returns the n-th projection of this product if 0 < n <= productArity, * otherwise throws an `IndexOutOfBoundsException`. * @@ -33,7 +33,7 @@ trait Product18[+T1, +T2, +T3, +T4, +T5, +T6, +T7, +T8, +T9, +T10, +T11, +T12, + */ @throws(classOf[IndexOutOfBoundsException]) - override def productElement(n: Int) = n match { + override def productElement(n: Int) = n match { case 0 => _1 case 1 => _2 case 2 => _3 diff --git a/src/library/scala/Product19.scala b/src/library/scala/Product19.scala index 5464de7264..4f4a98c6a0 100644 --- a/src/library/scala/Product19.scala +++ b/src/library/scala/Product19.scala @@ -17,13 +17,13 @@ object Product19 { /** Product19 is a cartesian product of 19 components. * @since 2.3 */ -trait Product19[+T1, +T2, +T3, +T4, +T5, +T6, +T7, +T8, +T9, +T10, +T11, +T12, +T13, +T14, +T15, +T16, +T17, +T18, +T19] extends Product { +trait Product19[+T1, +T2, +T3, +T4, +T5, +T6, +T7, +T8, +T9, +T10, +T11, +T12, +T13, +T14, +T15, +T16, +T17, +T18, +T19] extends Any with Product { /** The arity of this product. * @return 19 */ override def productArity = 19 - + /** Returns the n-th projection of this product if 0 < n <= productArity, * otherwise throws an `IndexOutOfBoundsException`. * @@ -33,7 +33,7 @@ trait Product19[+T1, +T2, +T3, +T4, +T5, +T6, +T7, +T8, +T9, +T10, +T11, +T12, + */ @throws(classOf[IndexOutOfBoundsException]) - override def productElement(n: Int) = n match { + override def productElement(n: Int) = n match { case 0 => _1 case 1 => _2 case 2 => _3 diff --git a/src/library/scala/Product2.scala b/src/library/scala/Product2.scala index 8097245926..eb67e5d46e 100644 --- a/src/library/scala/Product2.scala +++ b/src/library/scala/Product2.scala @@ -17,13 +17,13 @@ object Product2 { /** Product2 is a cartesian product of 2 components. * @since 2.3 */ -trait Product2[@specialized(Int, Long, Double) +T1, @specialized(Int, Long, Double) +T2] extends Product { +trait Product2[@specialized(Int, Long, Double) +T1, @specialized(Int, Long, Double) +T2] extends Any with Product { /** The arity of this product. * @return 2 */ override def productArity = 2 - + /** Returns the n-th projection of this product if 0 < n <= productArity, * otherwise throws an `IndexOutOfBoundsException`. * @@ -33,7 +33,7 @@ trait Product2[@specialized(Int, Long, Double) +T1, @specialized(Int, Long, Doub */ @throws(classOf[IndexOutOfBoundsException]) - override def productElement(n: Int) = n match { + override def productElement(n: Int) = n match { case 0 => _1 case 1 => _2 case _ => throw new IndexOutOfBoundsException(n.toString()) diff --git a/src/library/scala/Product20.scala b/src/library/scala/Product20.scala index b094e09aca..80f63f1bb4 100644 --- a/src/library/scala/Product20.scala +++ b/src/library/scala/Product20.scala @@ -17,13 +17,13 @@ object Product20 { /** Product20 is a cartesian product of 20 components. * @since 2.3 */ -trait Product20[+T1, +T2, +T3, +T4, +T5, +T6, +T7, +T8, +T9, +T10, +T11, +T12, +T13, +T14, +T15, +T16, +T17, +T18, +T19, +T20] extends Product { +trait Product20[+T1, +T2, +T3, +T4, +T5, +T6, +T7, +T8, +T9, +T10, +T11, +T12, +T13, +T14, +T15, +T16, +T17, +T18, +T19, +T20] extends Any with Product { /** The arity of this product. * @return 20 */ override def productArity = 20 - + /** Returns the n-th projection of this product if 0 < n <= productArity, * otherwise throws an `IndexOutOfBoundsException`. * @@ -33,7 +33,7 @@ trait Product20[+T1, +T2, +T3, +T4, +T5, +T6, +T7, +T8, +T9, +T10, +T11, +T12, + */ @throws(classOf[IndexOutOfBoundsException]) - override def productElement(n: Int) = n match { + override def productElement(n: Int) = n match { case 0 => _1 case 1 => _2 case 2 => _3 diff --git a/src/library/scala/Product21.scala b/src/library/scala/Product21.scala index fa06cfb438..7056844271 100644 --- a/src/library/scala/Product21.scala +++ b/src/library/scala/Product21.scala @@ -17,13 +17,13 @@ object Product21 { /** Product21 is a cartesian product of 21 components. * @since 2.3 */ -trait Product21[+T1, +T2, +T3, +T4, +T5, +T6, +T7, +T8, +T9, +T10, +T11, +T12, +T13, +T14, +T15, +T16, +T17, +T18, +T19, +T20, +T21] extends Product { +trait Product21[+T1, +T2, +T3, +T4, +T5, +T6, +T7, +T8, +T9, +T10, +T11, +T12, +T13, +T14, +T15, +T16, +T17, +T18, +T19, +T20, +T21] extends Any with Product { /** The arity of this product. * @return 21 */ override def productArity = 21 - + /** Returns the n-th projection of this product if 0 < n <= productArity, * otherwise throws an `IndexOutOfBoundsException`. * @@ -33,7 +33,7 @@ trait Product21[+T1, +T2, +T3, +T4, +T5, +T6, +T7, +T8, +T9, +T10, +T11, +T12, + */ @throws(classOf[IndexOutOfBoundsException]) - override def productElement(n: Int) = n match { + override def productElement(n: Int) = n match { case 0 => _1 case 1 => _2 case 2 => _3 diff --git a/src/library/scala/Product22.scala b/src/library/scala/Product22.scala index 46038bf1a2..05e95f92dd 100644 --- a/src/library/scala/Product22.scala +++ b/src/library/scala/Product22.scala @@ -17,13 +17,13 @@ object Product22 { /** Product22 is a cartesian product of 22 components. * @since 2.3 */ -trait Product22[+T1, +T2, +T3, +T4, +T5, +T6, +T7, +T8, +T9, +T10, +T11, +T12, +T13, +T14, +T15, +T16, +T17, +T18, +T19, +T20, +T21, +T22] extends Product { +trait Product22[+T1, +T2, +T3, +T4, +T5, +T6, +T7, +T8, +T9, +T10, +T11, +T12, +T13, +T14, +T15, +T16, +T17, +T18, +T19, +T20, +T21, +T22] extends Any with Product { /** The arity of this product. * @return 22 */ override def productArity = 22 - + /** Returns the n-th projection of this product if 0 < n <= productArity, * otherwise throws an `IndexOutOfBoundsException`. * @@ -33,7 +33,7 @@ trait Product22[+T1, +T2, +T3, +T4, +T5, +T6, +T7, +T8, +T9, +T10, +T11, +T12, + */ @throws(classOf[IndexOutOfBoundsException]) - override def productElement(n: Int) = n match { + override def productElement(n: Int) = n match { case 0 => _1 case 1 => _2 case 2 => _3 diff --git a/src/library/scala/Product3.scala b/src/library/scala/Product3.scala index 3a4cd8fc5e..91556bb962 100644 --- a/src/library/scala/Product3.scala +++ b/src/library/scala/Product3.scala @@ -17,13 +17,13 @@ object Product3 { /** Product3 is a cartesian product of 3 components. * @since 2.3 */ -trait Product3[+T1, +T2, +T3] extends Product { +trait Product3[+T1, +T2, +T3] extends Any with Product { /** The arity of this product. * @return 3 */ override def productArity = 3 - + /** Returns the n-th projection of this product if 0 < n <= productArity, * otherwise throws an `IndexOutOfBoundsException`. * @@ -33,7 +33,7 @@ trait Product3[+T1, +T2, +T3] extends Product { */ @throws(classOf[IndexOutOfBoundsException]) - override def productElement(n: Int) = n match { + override def productElement(n: Int) = n match { case 0 => _1 case 1 => _2 case 2 => _3 diff --git a/src/library/scala/Product4.scala b/src/library/scala/Product4.scala index a4d47457fa..1f9070c155 100644 --- a/src/library/scala/Product4.scala +++ b/src/library/scala/Product4.scala @@ -17,13 +17,13 @@ object Product4 { /** Product4 is a cartesian product of 4 components. * @since 2.3 */ -trait Product4[+T1, +T2, +T3, +T4] extends Product { +trait Product4[+T1, +T2, +T3, +T4] extends Any with Product { /** The arity of this product. * @return 4 */ override def productArity = 4 - + /** Returns the n-th projection of this product if 0 < n <= productArity, * otherwise throws an `IndexOutOfBoundsException`. * @@ -33,7 +33,7 @@ trait Product4[+T1, +T2, +T3, +T4] extends Product { */ @throws(classOf[IndexOutOfBoundsException]) - override def productElement(n: Int) = n match { + override def productElement(n: Int) = n match { case 0 => _1 case 1 => _2 case 2 => _3 diff --git a/src/library/scala/Product5.scala b/src/library/scala/Product5.scala index 9f25e70af0..52dd284f55 100644 --- a/src/library/scala/Product5.scala +++ b/src/library/scala/Product5.scala @@ -17,13 +17,13 @@ object Product5 { /** Product5 is a cartesian product of 5 components. * @since 2.3 */ -trait Product5[+T1, +T2, +T3, +T4, +T5] extends Product { +trait Product5[+T1, +T2, +T3, +T4, +T5] extends Any with Product { /** The arity of this product. * @return 5 */ override def productArity = 5 - + /** Returns the n-th projection of this product if 0 < n <= productArity, * otherwise throws an `IndexOutOfBoundsException`. * @@ -33,7 +33,7 @@ trait Product5[+T1, +T2, +T3, +T4, +T5] extends Product { */ @throws(classOf[IndexOutOfBoundsException]) - override def productElement(n: Int) = n match { + override def productElement(n: Int) = n match { case 0 => _1 case 1 => _2 case 2 => _3 diff --git a/src/library/scala/Product6.scala b/src/library/scala/Product6.scala index 87fd318c68..9624bdbe3e 100644 --- a/src/library/scala/Product6.scala +++ b/src/library/scala/Product6.scala @@ -17,13 +17,13 @@ object Product6 { /** Product6 is a cartesian product of 6 components. * @since 2.3 */ -trait Product6[+T1, +T2, +T3, +T4, +T5, +T6] extends Product { +trait Product6[+T1, +T2, +T3, +T4, +T5, +T6] extends Any with Product { /** The arity of this product. * @return 6 */ override def productArity = 6 - + /** Returns the n-th projection of this product if 0 < n <= productArity, * otherwise throws an `IndexOutOfBoundsException`. * @@ -33,7 +33,7 @@ trait Product6[+T1, +T2, +T3, +T4, +T5, +T6] extends Product { */ @throws(classOf[IndexOutOfBoundsException]) - override def productElement(n: Int) = n match { + override def productElement(n: Int) = n match { case 0 => _1 case 1 => _2 case 2 => _3 diff --git a/src/library/scala/Product7.scala b/src/library/scala/Product7.scala index d074503315..36d4b149db 100644 --- a/src/library/scala/Product7.scala +++ b/src/library/scala/Product7.scala @@ -17,13 +17,13 @@ object Product7 { /** Product7 is a cartesian product of 7 components. * @since 2.3 */ -trait Product7[+T1, +T2, +T3, +T4, +T5, +T6, +T7] extends Product { +trait Product7[+T1, +T2, +T3, +T4, +T5, +T6, +T7] extends Any with Product { /** The arity of this product. * @return 7 */ override def productArity = 7 - + /** Returns the n-th projection of this product if 0 < n <= productArity, * otherwise throws an `IndexOutOfBoundsException`. * @@ -33,7 +33,7 @@ trait Product7[+T1, +T2, +T3, +T4, +T5, +T6, +T7] extends Product { */ @throws(classOf[IndexOutOfBoundsException]) - override def productElement(n: Int) = n match { + override def productElement(n: Int) = n match { case 0 => _1 case 1 => _2 case 2 => _3 diff --git a/src/library/scala/Product8.scala b/src/library/scala/Product8.scala index bd6150c235..28c78f9c89 100644 --- a/src/library/scala/Product8.scala +++ b/src/library/scala/Product8.scala @@ -17,13 +17,13 @@ object Product8 { /** Product8 is a cartesian product of 8 components. * @since 2.3 */ -trait Product8[+T1, +T2, +T3, +T4, +T5, +T6, +T7, +T8] extends Product { +trait Product8[+T1, +T2, +T3, +T4, +T5, +T6, +T7, +T8] extends Any with Product { /** The arity of this product. * @return 8 */ override def productArity = 8 - + /** Returns the n-th projection of this product if 0 < n <= productArity, * otherwise throws an `IndexOutOfBoundsException`. * @@ -33,7 +33,7 @@ trait Product8[+T1, +T2, +T3, +T4, +T5, +T6, +T7, +T8] extends Product { */ @throws(classOf[IndexOutOfBoundsException]) - override def productElement(n: Int) = n match { + override def productElement(n: Int) = n match { case 0 => _1 case 1 => _2 case 2 => _3 diff --git a/src/library/scala/Product9.scala b/src/library/scala/Product9.scala index 1f042944cc..d69c550abe 100644 --- a/src/library/scala/Product9.scala +++ b/src/library/scala/Product9.scala @@ -17,13 +17,13 @@ object Product9 { /** Product9 is a cartesian product of 9 components. * @since 2.3 */ -trait Product9[+T1, +T2, +T3, +T4, +T5, +T6, +T7, +T8, +T9] extends Product { +trait Product9[+T1, +T2, +T3, +T4, +T5, +T6, +T7, +T8, +T9] extends Any with Product { /** The arity of this product. * @return 9 */ override def productArity = 9 - + /** Returns the n-th projection of this product if 0 < n <= productArity, * otherwise throws an `IndexOutOfBoundsException`. * @@ -33,7 +33,7 @@ trait Product9[+T1, +T2, +T3, +T4, +T5, +T6, +T7, +T8, +T9] extends Product { */ @throws(classOf[IndexOutOfBoundsException]) - override def productElement(n: Int) = n match { + override def productElement(n: Int) = n match { case 0 => _1 case 1 => _2 case 2 => _3 diff --git a/src/library/scala/Tuple1.scala b/src/library/scala/Tuple1.scala index 6d31d35e51..02fdd0cba5 100644 --- a/src/library/scala/Tuple1.scala +++ b/src/library/scala/Tuple1.scala @@ -19,5 +19,5 @@ case class Tuple1[@specialized(Int, Long, Double) +T1](_1: T1) extends Product1[T1] { override def toString() = "(" + _1 + ")" - + } diff --git a/src/library/scala/Tuple10.scala b/src/library/scala/Tuple10.scala index 10d554d467..ba2a02a8b2 100644 --- a/src/library/scala/Tuple10.scala +++ b/src/library/scala/Tuple10.scala @@ -28,5 +28,5 @@ case class Tuple10[+T1, +T2, +T3, +T4, +T5, +T6, +T7, +T8, +T9, +T10](_1: T1, _2 extends Product10[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10] { override def toString() = "(" + _1 + "," + _2 + "," + _3 + "," + _4 + "," + _5 + "," + _6 + "," + _7 + "," + _8 + "," + _9 + "," + _10 + ")" - + } diff --git a/src/library/scala/Tuple11.scala b/src/library/scala/Tuple11.scala index 2065e4f017..7f51d172d4 100644 --- a/src/library/scala/Tuple11.scala +++ b/src/library/scala/Tuple11.scala @@ -29,5 +29,5 @@ case class Tuple11[+T1, +T2, +T3, +T4, +T5, +T6, +T7, +T8, +T9, +T10, +T11](_1: extends Product11[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11] { override def toString() = "(" + _1 + "," + _2 + "," + _3 + "," + _4 + "," + _5 + "," + _6 + "," + _7 + "," + _8 + "," + _9 + "," + _10 + "," + _11 + ")" - + } diff --git a/src/library/scala/Tuple12.scala b/src/library/scala/Tuple12.scala index a463986752..4bbc6a0eab 100644 --- a/src/library/scala/Tuple12.scala +++ b/src/library/scala/Tuple12.scala @@ -31,5 +31,5 @@ case class Tuple12[+T1, +T2, +T3, +T4, +T5, +T6, +T7, +T8, +T9, +T10, +T11, +T12 { override def toString() = "(" + _1 + "," + _2 + "," + _3 + "," + _4 + "," + _5 + "," + _6 + "," + _7 + "," + _8 + "," + _9 + "," + _10 + "," + _11 + "," + _12 + ")" - + } diff --git a/src/library/scala/Tuple13.scala b/src/library/scala/Tuple13.scala index 2bee0d69ad..77bd59bf2e 100644 --- a/src/library/scala/Tuple13.scala +++ b/src/library/scala/Tuple13.scala @@ -32,5 +32,5 @@ case class Tuple13[+T1, +T2, +T3, +T4, +T5, +T6, +T7, +T8, +T9, +T10, +T11, +T12 { override def toString() = "(" + _1 + "," + _2 + "," + _3 + "," + _4 + "," + _5 + "," + _6 + "," + _7 + "," + _8 + "," + _9 + "," + _10 + "," + _11 + "," + _12 + "," + _13 + ")" - + } diff --git a/src/library/scala/Tuple14.scala b/src/library/scala/Tuple14.scala index 60f7c51e64..bf7a4ce016 100644 --- a/src/library/scala/Tuple14.scala +++ b/src/library/scala/Tuple14.scala @@ -33,5 +33,5 @@ case class Tuple14[+T1, +T2, +T3, +T4, +T5, +T6, +T7, +T8, +T9, +T10, +T11, +T12 { override def toString() = "(" + _1 + "," + _2 + "," + _3 + "," + _4 + "," + _5 + "," + _6 + "," + _7 + "," + _8 + "," + _9 + "," + _10 + "," + _11 + "," + _12 + "," + _13 + "," + _14 + ")" - + } diff --git a/src/library/scala/Tuple15.scala b/src/library/scala/Tuple15.scala index fc8e30580b..582c359bc6 100644 --- a/src/library/scala/Tuple15.scala +++ b/src/library/scala/Tuple15.scala @@ -34,5 +34,5 @@ case class Tuple15[+T1, +T2, +T3, +T4, +T5, +T6, +T7, +T8, +T9, +T10, +T11, +T12 { override def toString() = "(" + _1 + "," + _2 + "," + _3 + "," + _4 + "," + _5 + "," + _6 + "," + _7 + "," + _8 + "," + _9 + "," + _10 + "," + _11 + "," + _12 + "," + _13 + "," + _14 + "," + _15 + ")" - + } diff --git a/src/library/scala/Tuple16.scala b/src/library/scala/Tuple16.scala index 80181f6648..a1e9a790ff 100644 --- a/src/library/scala/Tuple16.scala +++ b/src/library/scala/Tuple16.scala @@ -35,5 +35,5 @@ case class Tuple16[+T1, +T2, +T3, +T4, +T5, +T6, +T7, +T8, +T9, +T10, +T11, +T12 { override def toString() = "(" + _1 + "," + _2 + "," + _3 + "," + _4 + "," + _5 + "," + _6 + "," + _7 + "," + _8 + "," + _9 + "," + _10 + "," + _11 + "," + _12 + "," + _13 + "," + _14 + "," + _15 + "," + _16 + ")" - + } diff --git a/src/library/scala/Tuple17.scala b/src/library/scala/Tuple17.scala index 6236122be2..f531766c18 100644 --- a/src/library/scala/Tuple17.scala +++ b/src/library/scala/Tuple17.scala @@ -36,5 +36,5 @@ case class Tuple17[+T1, +T2, +T3, +T4, +T5, +T6, +T7, +T8, +T9, +T10, +T11, +T12 { override def toString() = "(" + _1 + "," + _2 + "," + _3 + "," + _4 + "," + _5 + "," + _6 + "," + _7 + "," + _8 + "," + _9 + "," + _10 + "," + _11 + "," + _12 + "," + _13 + "," + _14 + "," + _15 + "," + _16 + "," + _17 + ")" - + } diff --git a/src/library/scala/Tuple18.scala b/src/library/scala/Tuple18.scala index dd6a819ac5..a96db25e4b 100644 --- a/src/library/scala/Tuple18.scala +++ b/src/library/scala/Tuple18.scala @@ -37,5 +37,5 @@ case class Tuple18[+T1, +T2, +T3, +T4, +T5, +T6, +T7, +T8, +T9, +T10, +T11, +T12 { override def toString() = "(" + _1 + "," + _2 + "," + _3 + "," + _4 + "," + _5 + "," + _6 + "," + _7 + "," + _8 + "," + _9 + "," + _10 + "," + _11 + "," + _12 + "," + _13 + "," + _14 + "," + _15 + "," + _16 + "," + _17 + "," + _18 + ")" - + } diff --git a/src/library/scala/Tuple19.scala b/src/library/scala/Tuple19.scala index 65f0fd22cf..718280d68a 100644 --- a/src/library/scala/Tuple19.scala +++ b/src/library/scala/Tuple19.scala @@ -38,5 +38,5 @@ case class Tuple19[+T1, +T2, +T3, +T4, +T5, +T6, +T7, +T8, +T9, +T10, +T11, +T12 { override def toString() = "(" + _1 + "," + _2 + "," + _3 + "," + _4 + "," + _5 + "," + _6 + "," + _7 + "," + _8 + "," + _9 + "," + _10 + "," + _11 + "," + _12 + "," + _13 + "," + _14 + "," + _15 + "," + _16 + "," + _17 + "," + _18 + "," + _19 + ")" - + } diff --git a/src/library/scala/Tuple2.scala b/src/library/scala/Tuple2.scala index dd6ac0cfd2..ad3f7df697 100644 --- a/src/library/scala/Tuple2.scala +++ b/src/library/scala/Tuple2.scala @@ -23,7 +23,7 @@ case class Tuple2[@specialized(Int, Long, Double) +T1, @specialized(Int, Long, D extends Product2[T1, T2] { override def toString() = "(" + _1 + "," + _2 + ")" - + /** Swaps the elements of this `Tuple`. * @return a new Tuple where the first element is the second element of this Tuple and the * second element is the first element of this Tuple. diff --git a/src/library/scala/Tuple20.scala b/src/library/scala/Tuple20.scala index cf3626909d..4a44c0bb89 100644 --- a/src/library/scala/Tuple20.scala +++ b/src/library/scala/Tuple20.scala @@ -39,5 +39,5 @@ case class Tuple20[+T1, +T2, +T3, +T4, +T5, +T6, +T7, +T8, +T9, +T10, +T11, +T12 { override def toString() = "(" + _1 + "," + _2 + "," + _3 + "," + _4 + "," + _5 + "," + _6 + "," + _7 + "," + _8 + "," + _9 + "," + _10 + "," + _11 + "," + _12 + "," + _13 + "," + _14 + "," + _15 + "," + _16 + "," + _17 + "," + _18 + "," + _19 + "," + _20 + ")" - + } diff --git a/src/library/scala/Tuple21.scala b/src/library/scala/Tuple21.scala index 78b9c585c6..580a169e39 100644 --- a/src/library/scala/Tuple21.scala +++ b/src/library/scala/Tuple21.scala @@ -40,5 +40,5 @@ case class Tuple21[+T1, +T2, +T3, +T4, +T5, +T6, +T7, +T8, +T9, +T10, +T11, +T12 { override def toString() = "(" + _1 + "," + _2 + "," + _3 + "," + _4 + "," + _5 + "," + _6 + "," + _7 + "," + _8 + "," + _9 + "," + _10 + "," + _11 + "," + _12 + "," + _13 + "," + _14 + "," + _15 + "," + _16 + "," + _17 + "," + _18 + "," + _19 + "," + _20 + "," + _21 + ")" - + } diff --git a/src/library/scala/Tuple22.scala b/src/library/scala/Tuple22.scala index 0993dfbbc3..fd3392ddea 100644 --- a/src/library/scala/Tuple22.scala +++ b/src/library/scala/Tuple22.scala @@ -41,5 +41,5 @@ case class Tuple22[+T1, +T2, +T3, +T4, +T5, +T6, +T7, +T8, +T9, +T10, +T11, +T12 { override def toString() = "(" + _1 + "," + _2 + "," + _3 + "," + _4 + "," + _5 + "," + _6 + "," + _7 + "," + _8 + "," + _9 + "," + _10 + "," + _11 + "," + _12 + "," + _13 + "," + _14 + "," + _15 + "," + _16 + "," + _17 + "," + _18 + "," + _19 + "," + _20 + "," + _21 + "," + _22 + ")" - + } diff --git a/src/library/scala/Tuple3.scala b/src/library/scala/Tuple3.scala index dfa0c962a2..0d5399308b 100644 --- a/src/library/scala/Tuple3.scala +++ b/src/library/scala/Tuple3.scala @@ -24,7 +24,7 @@ case class Tuple3[+T1, +T2, +T3](_1: T1, _2: T2, _3: T3) extends Product3[T1, T2, T3] { override def toString() = "(" + _1 + "," + _2 + "," + _3 + ")" - + @deprecated("Use `zipped` instead.", "2.9.0") def zip[Repr1, El1, El2, El3, To](implicit w1: T1 => TLike[El1, Repr1], diff --git a/src/library/scala/Tuple4.scala b/src/library/scala/Tuple4.scala index a919072c88..a859078bcf 100644 --- a/src/library/scala/Tuple4.scala +++ b/src/library/scala/Tuple4.scala @@ -22,5 +22,5 @@ case class Tuple4[+T1, +T2, +T3, +T4](_1: T1, _2: T2, _3: T3, _4: T4) extends Product4[T1, T2, T3, T4] { override def toString() = "(" + _1 + "," + _2 + "," + _3 + "," + _4 + ")" - + } diff --git a/src/library/scala/Tuple5.scala b/src/library/scala/Tuple5.scala index 6a94f48ab4..1edfb673ee 100644 --- a/src/library/scala/Tuple5.scala +++ b/src/library/scala/Tuple5.scala @@ -23,5 +23,5 @@ case class Tuple5[+T1, +T2, +T3, +T4, +T5](_1: T1, _2: T2, _3: T3, _4: T4, _5: T extends Product5[T1, T2, T3, T4, T5] { override def toString() = "(" + _1 + "," + _2 + "," + _3 + "," + _4 + "," + _5 + ")" - + } diff --git a/src/library/scala/Tuple6.scala b/src/library/scala/Tuple6.scala index 34f8224627..5b74937e58 100644 --- a/src/library/scala/Tuple6.scala +++ b/src/library/scala/Tuple6.scala @@ -24,5 +24,5 @@ case class Tuple6[+T1, +T2, +T3, +T4, +T5, +T6](_1: T1, _2: T2, _3: T3, _4: T4, extends Product6[T1, T2, T3, T4, T5, T6] { override def toString() = "(" + _1 + "," + _2 + "," + _3 + "," + _4 + "," + _5 + "," + _6 + ")" - + } diff --git a/src/library/scala/Tuple7.scala b/src/library/scala/Tuple7.scala index 6fc3477ba2..a7f572e9f0 100644 --- a/src/library/scala/Tuple7.scala +++ b/src/library/scala/Tuple7.scala @@ -25,5 +25,5 @@ case class Tuple7[+T1, +T2, +T3, +T4, +T5, +T6, +T7](_1: T1, _2: T2, _3: T3, _4: extends Product7[T1, T2, T3, T4, T5, T6, T7] { override def toString() = "(" + _1 + "," + _2 + "," + _3 + "," + _4 + "," + _5 + "," + _6 + "," + _7 + ")" - + } diff --git a/src/library/scala/Tuple8.scala b/src/library/scala/Tuple8.scala index 1e21b684fc..9bb427d689 100644 --- a/src/library/scala/Tuple8.scala +++ b/src/library/scala/Tuple8.scala @@ -26,5 +26,5 @@ case class Tuple8[+T1, +T2, +T3, +T4, +T5, +T6, +T7, +T8](_1: T1, _2: T2, _3: T3 extends Product8[T1, T2, T3, T4, T5, T6, T7, T8] { override def toString() = "(" + _1 + "," + _2 + "," + _3 + "," + _4 + "," + _5 + "," + _6 + "," + _7 + "," + _8 + ")" - + } diff --git a/src/library/scala/Tuple9.scala b/src/library/scala/Tuple9.scala index 453cea31a1..4d50539e0c 100644 --- a/src/library/scala/Tuple9.scala +++ b/src/library/scala/Tuple9.scala @@ -27,5 +27,5 @@ case class Tuple9[+T1, +T2, +T3, +T4, +T5, +T6, +T7, +T8, +T9](_1: T1, _2: T2, _ extends Product9[T1, T2, T3, T4, T5, T6, T7, T8, T9] { override def toString() = "(" + _1 + "," + _2 + "," + _3 + "," + _4 + "," + _5 + "," + _6 + "," + _7 + "," + _8 + "," + _9 + ")" - + } diff --git a/test/files/neg/anyval-anyref-parent.check b/test/files/neg/anyval-anyref-parent.check index e1903f5fcc..fe20e5de81 100644 --- a/test/files/neg/anyval-anyref-parent.check +++ b/test/files/neg/anyval-anyref-parent.check @@ -1,10 +1,10 @@ -anyval-anyref-parent.scala:2: error: Only classes (not traits) are allowed to extend AnyVal +anyval-anyref-parent.scala:2: error: only classes (not traits) are allowed to extend AnyVal trait Foo2 extends AnyVal // fail ^ anyval-anyref-parent.scala:5: error: Any does not have a constructor class Bar1 extends Any // fail ^ -anyval-anyref-parent.scala:6: error: Value class needs to have exactly one public val parameter +anyval-anyref-parent.scala:6: error: value class needs to have exactly one public val parameter class Bar2(x: Int) extends AnyVal // fail ^ anyval-anyref-parent.scala:10: error: illegal inheritance; superclass Any @@ -17,7 +17,7 @@ anyval-anyref-parent.scala:11: error: illegal inheritance; superclass AnyVal of the mixin trait Immutable trait Foo5 extends AnyVal with Immutable // fail ^ -anyval-anyref-parent.scala:11: error: Only classes (not traits) are allowed to extend AnyVal +anyval-anyref-parent.scala:11: error: only classes (not traits) are allowed to extend AnyVal trait Foo5 extends AnyVal with Immutable // fail ^ 6 errors found diff --git a/test/files/neg/valueclasses-doubledefs.check b/test/files/neg/valueclasses-doubledefs.check new file mode 100644 index 0000000000..556d7a0900 --- /dev/null +++ b/test/files/neg/valueclasses-doubledefs.check @@ -0,0 +1,7 @@ +valueclasses-doubledefs.scala:5: error: double definition: +method apply:(x: Meter)String and +method apply:(x: Double)String at line 4 +have same type after erasure: (x: Double)String + def apply(x: Meter) = x.toString + ^ +one error found diff --git a/test/files/neg/valueclasses.check b/test/files/neg/valueclasses.check index 30ee689511..756a0474fa 100644 --- a/test/files/neg/valueclasses.check +++ b/test/files/neg/valueclasses.check @@ -1,43 +1,46 @@ -valueclasses.scala:3: error: Only classes (not traits) are allowed to extend AnyVal +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 +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 +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 +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 +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 +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 +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 +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 +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: 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 +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: this statement is not allowed in value class: private[this] val y: Int = V9.this.x val y = x // 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 +valueclasses.scala:31: error: value class needs to have exactly one public val parameter class V13(x: Int) extends AnyVal // fail ^ -14 errors found +valueclasses.scala:45: error: value class must have public primary constructor +final class TOD private (val secondsOfDay: Int) extends AnyVal { // should fail with private constructor + ^ +15 errors found diff --git a/test/files/run/valueclasses-constr.check b/test/files/run/valueclasses-constr.check new file mode 100644 index 0000000000..df37fbc723 --- /dev/null +++ b/test/files/run/valueclasses-constr.check @@ -0,0 +1,2 @@ +0 +00:16:40 diff --git a/test/files/run/valueclasses-constr.scala b/test/files/run/valueclasses-constr.scala new file mode 100644 index 0000000000..7a10299386 --- /dev/null +++ b/test/files/run/valueclasses-constr.scala @@ -0,0 +1,25 @@ +object TOD { + final val SecondsPerDay = 86400 + + def apply(seconds: Int) = { + val n = seconds % SecondsPerDay + new TOD(if (n >= 0) n else n + SecondsPerDay) + } +} + +final class TOD (val secondsOfDay: Int) extends AnyVal { + def hours = secondsOfDay / 3600 + def minutes = (secondsOfDay / 60) % 60 + def seconds = secondsOfDay % 60 + + override def toString = "%02d:%02d:%02d".format(hours, minutes, seconds) +} + +object Test extends App { + + val y: TOD = new TOD(1000) + val x: TOD = TOD(1000) + println(x.hours) + println(x) +} + -- cgit v1.2.3 From 54e284d669418ebc6445bd0ec66804b9067f6dd3 Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Wed, 7 Mar 2012 14:13:03 +0100 Subject: Allows case classes as value classes --- .../tools/nsc/typechecker/SyntheticMethods.scala | 26 +++--- src/library/scala/Serializable.scala | 2 +- test/files/pos/t715/meredith_1.scala | 2 +- test/files/run/MeterCaseClass.check | 21 +++++ test/files/run/MeterCaseClass.scala | 99 ++++++++++++++++++++++ 5 files changed, 138 insertions(+), 12 deletions(-) create mode 100644 test/files/run/MeterCaseClass.check create mode 100644 test/files/run/MeterCaseClass.scala (limited to 'test/files') diff --git a/src/compiler/scala/tools/nsc/typechecker/SyntheticMethods.scala b/src/compiler/scala/tools/nsc/typechecker/SyntheticMethods.scala index 9bee731e1e..1c78426c20 100644 --- a/src/compiler/scala/tools/nsc/typechecker/SyntheticMethods.scala +++ b/src/compiler/scala/tools/nsc/typechecker/SyntheticMethods.scala @@ -217,7 +217,7 @@ trait SyntheticMethods extends ast.TreeDSL { List( Product_productPrefix -> (() => constantNullary(nme.productPrefix, clazz.name.decode)), Product_productArity -> (() => constantNullary(nme.productArity, arity)), - Product_productElement -> (() => perElementMethod(nme.productElement, accessorLub)(Ident)), + Product_productElement -> (() => perElementMethod(nme.productElement, accessorLub)(Select(This(clazz), _))), Product_iterator -> (() => productIteratorMethod), Product_canEqual -> (() => canEqualMethod) // This is disabled pending a reimplementation which doesn't add any @@ -226,12 +226,21 @@ trait SyntheticMethods extends ast.TreeDSL { ) } + def valueClassMethods = List( + Any_hashCode -> (() => hashCodeDerivedValueClassMethod), + Any_equals -> (() => equalsDerivedValueClassMethod) + ) + def caseClassMethods = productMethods ++ productNMethods ++ Seq( Object_hashCode -> (() => forwardToRuntime(Object_hashCode)), Object_toString -> (() => forwardToRuntime(Object_toString)), Object_equals -> (() => equalsCaseClassMethod) ) + def valueCaseClassMethods = productMethods ++ productNMethods ++ valueClassMethods ++ Seq( + Any_toString -> (() => forwardToRuntime(Object_toString)) + ) + def caseObjectMethods = productMethods ++ Seq( Object_hashCode -> (() => constantMethod(nme.hashCode_, clazz.name.decode.hashCode)), Object_toString -> (() => constantMethod(nme.toString_, clazz.name.decode)) @@ -239,11 +248,6 @@ trait SyntheticMethods extends ast.TreeDSL { // Object_equals -> (() => createMethod(Object_equals)(m => This(clazz) ANY_EQ Ident(m.firstParam))) ) - def inlineClassMethods = List( - Any_hashCode -> (() => hashCodeDerivedValueClassMethod), - Any_equals -> (() => equalsDerivedValueClassMethod) - ) - /** If you serialize a singleton and then deserialize it twice, * you will have two instances of your singleton unless you implement * readResolve. Here it is implemented for all objects which have @@ -258,10 +262,12 @@ trait SyntheticMethods extends ast.TreeDSL { def synthesize(): List[Tree] = { val methods = ( - if (clazz.isDerivedValueClass) inlineClassMethods - else if (!clazz.isCase) Nil - else if (clazz.isModuleClass) caseObjectMethods - else caseClassMethods + if (clazz.isCase) + if (clazz.isDerivedValueClass) valueCaseClassMethods + else if (clazz.isModuleClass) caseObjectMethods + else caseClassMethods + else if (clazz.isDerivedValueClass) valueClassMethods + else Nil ) def impls = for ((m, impl) <- methods ; if !hasOverridingImplementation(m)) yield impl() diff --git a/src/library/scala/Serializable.scala b/src/library/scala/Serializable.scala index 9be258bb83..9b9456e0a0 100644 --- a/src/library/scala/Serializable.scala +++ b/src/library/scala/Serializable.scala @@ -11,4 +11,4 @@ package scala /** * Classes extending this trait are serializable across platforms (Java, .NET). */ -trait Serializable extends java.io.Serializable +trait Serializable extends Any with java.io.Serializable diff --git a/test/files/pos/t715/meredith_1.scala b/test/files/pos/t715/meredith_1.scala index 3ed2e57d7a..8261b9881a 100644 --- a/test/files/pos/t715/meredith_1.scala +++ b/test/files/pos/t715/meredith_1.scala @@ -3,7 +3,7 @@ package com.sap.dspace.model.othello; import scala.xml._ trait XMLRenderer { - type T <: {def getClass() : java.lang.Class[_]} + type T <: Any {def getClass() : java.lang.Class[_]} val valueTypes = List( classOf[java.lang.Boolean], diff --git a/test/files/run/MeterCaseClass.check b/test/files/run/MeterCaseClass.check new file mode 100644 index 0000000000..08370d2097 --- /dev/null +++ b/test/files/run/MeterCaseClass.check @@ -0,0 +1,21 @@ +2.0 +Meter(4.0) +false +x.isInstanceOf[Meter]: true +x.hashCode: 1072693248 +x == 1: false +x == y: true +a == b: true +testing native arrays +Array(Meter(1.0), Meter(2.0)) +Meter(1.0) +>>>Meter(1.0)<<< Meter(1.0) +>>>Meter(2.0)<<< Meter(2.0) +testing wrapped arrays +FlatArray(Meter(1.0), Meter(2.0)) +Meter(1.0) +>>>Meter(1.0)<<< Meter(1.0) +>>>Meter(2.0)<<< Meter(2.0) +FlatArray(Meter(2.0), Meter(3.0)) +ArrayBuffer(1.0, 2.0) +FlatArray(0.3048ft, 0.6096ft) diff --git a/test/files/run/MeterCaseClass.scala b/test/files/run/MeterCaseClass.scala new file mode 100644 index 0000000000..4f082b5252 --- /dev/null +++ b/test/files/run/MeterCaseClass.scala @@ -0,0 +1,99 @@ +package a { + case class Meter(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 } + } + + object Meter extends (Double => Meter) { + + implicit val boxings = new BoxingConversions[Meter, Double] { + def box(x: Double) = new Meter(x) + def unbox(m: Meter) = m.underlying + } + } + + 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 { + + { + val x: Meter = new Meter(1) + val a: Object = x.asInstanceOf[Object] + val y: Meter = a.asInstanceOf[Meter] + + val u: Double = 1 + val b: Object = u.asInstanceOf[Object] + val v: Double = b.asInstanceOf[Double] + } + + val x = new Meter(1) + val y = x + println((x + x) / x) + println((x + x) / 0.5) + println((x < x).toString) + println("x.isInstanceOf[Meter]: "+x.isInstanceOf[Meter]) + + + println("x.hashCode: "+x.hashCode) + println("x == 1: "+(x == 1)) + println("x == y: "+(x == y)) + assert(x.hashCode == (1.0).hashCode) + + val a: Any = x + val b: Any = y + println("a == b: "+(a == b)) + + { println("testing native arrays") + val arr = Array(x, y + x) + println(arr.deep) + def foo[T <: Printable](x: Array[T]) { + for (i <- 0 until x.length) { x(i).print; println(" "+x(i)) } + } + val m = arr(0) + println(m) + foo(arr) + } + + { println("testing wrapped arrays") + import collection.mutable.FlatArray + val arr = FlatArray(x, y + x) + println(arr) + def foo(x: FlatArray[Meter]) { + for (i <- 0 until x.length) { x(i).print; println(" "+x(i)) } + } + val m = arr(0) + println(m) + foo(arr) + val ys: Seq[Meter] = arr map (_ + new Meter(1)) + println(ys) + val zs = arr map (_ / Meter(1)) + println(zs) + val fs = arr map (_.toFoot) + println(fs) + } + +} -- cgit v1.2.3