diff options
author | Antonio Cunei <antonio.cunei@epfl.ch> | 2011-05-02 10:18:52 +0000 |
---|---|---|
committer | Antonio Cunei <antonio.cunei@epfl.ch> | 2011-05-02 10:18:52 +0000 |
commit | cb6a345a2f35f2f85832c9bf2f509c6f98a40d01 (patch) | |
tree | de8db551cbe7fd2d89c4885d670ac896f9d1c3dc /test | |
parent | 960edcd25172b6cc98b573379ef8d4cc960ddec2 (diff) | |
download | scala-cb6a345a2f35f2f85832c9bf2f509c6f98a40d01.tar.gz scala-cb6a345a2f35f2f85832c9bf2f509c6f98a40d01.tar.bz2 scala-cb6a345a2f35f2f85832c9bf2f509c6f98a40d01.zip |
Merged revisions 24830-24831,24834-24862 via sv...
Merged revisions 24830-24831,24834-24862 via svnmerge from
https://lampsvn.epfl.ch/svn-repos/scala/scala/trunk
........
r24830 | extempore | 2011-04-26 21:00:24 +0200 (Tue, 26 Apr 2011) | 1 line
Some solid progress on the pattern matcher, no review. ........ r24831
| odersky | 2011-04-27 12:26:39 +0200 (Wed, 27 Apr 2011) | 1 line
More bridges in collections. Review by prokopec.
........
r24834 | extempore | 2011-04-27 20:35:47 +0200 (Wed, 27 Apr 2011) | 1 line
Fixed inversion of fsc's exit code, closes #4519 no review. ........
r24835 | extempore | 2011-04-27 20:36:04 +0200 (Wed, 27 Apr 2011) | 2
lines
Fixed a booch I made in io.Position's positioning. Closes #4498, no
review. ........ r24836 | extempore | 2011-04-27 20:36:16 +0200 (Wed, 27
Apr 2011) | 1 line
A little cleanup on a repl command, no review.
........
r24837 | extempore | 2011-04-27 20:36:32 +0200 (Wed, 27 Apr 2011) | 5 lines
Trying to fix the pattern matcher took me into the lambda lifter,
and I made some changes which seemed sensible to me. I'm going to be a
stickler about eliminating mutable maps which hold mutable listbuffers.
I could use some confirmation that I didn't somehow break the world:
review by dragos. ........ r24838 | extempore | 2011-04-27 20:36:47
+0200 (Wed, 27 Apr 2011) | 4 lines
Trying out a different strategy for restoring terminal settings so we
don't have a list of hardcoded terminal types. Now it saves the terminal
settings on script start and restores those on exit. Closes #4170,
review by rytz. ........ r24839 | extempore | 2011-04-28 01:49:27 +0200
(Thu, 28 Apr 2011) | 1 line
Cleaned up some hopelessly atrophied documentation, no review.
........ r24840 | extempore | 2011-04-28 03:10:22 +0200 (Thu, 28 Apr
2011) | 4 lines
Upgraded -d so you can output classes directly to a jar. Very (very)
loosely based on a patch from dmharrah. Like dmharrah before me, I
see little if any change in compile times, which I find difficult to
explain. Closes #27, review by dmharrah. ........ r24841 | extempore |
2011-04-28 17:12:42 +0200 (Thu, 28 Apr 2011) | 5 lines
Improvements to the AST browser contributed by Yuvi Masory. Uses
Nimbus LAF when available and improves readability by padding
components. Adds menu items and key bindings for expanding and
contracting nodes, closing the browser and continuing compilation, and
closing the browser and aborting. No review. ........ r24842 | extempore
| 2011-04-28 18:23:45 +0200 (Thu, 28 Apr 2011) | 15 lines
Improved the error message for another of the most common situations
I hear about in newbieland. It could be taken further. If compilation
fails due to an unimplemented abstract method, and there is a concrete
method of the same name and arity, it will do a pairwise analysis of
the parameters and attempt to further explain where you went off the
beam if it feels it can do so sensibly. Such as in the test case:
% scalac S.scala
S.scala:1: error: class S needs to be abstract, since method g in class J of type (y: Int,z: java.util.List)Int is not defined
(Note that java.util.List does not match java.util.List[String]. To implement a raw type, use java.util.List[_])
class S extends J {
^
one error found
No review.
........
r24843 | extempore | 2011-04-28 18:26:05 +0200 (Thu, 28 Apr 2011) | 11 lines
I wrote a warning when nullary methods return Unit. I wimped out of
including it in this patch because we had about 200 of them, and
that's what is fixed in this patch. I will add the warning to some
kind of "-Xlint" feature after 2.9.
This is motivated at least partly by the resolution of #4506, which
indicates the distinction between "def foo()" and "def foo" will
continue to jab its pointy stick into our eyes, so I believe we have a
minimal duty of at least following our own advice about what they mean
and not making a semirandom choice as to whether a method has parens
or not. Review by community. ........ r24844 | odersky | 2011-04-29
13:07:56 +0200 (Fri, 29 Apr 2011) | 1 line
Fixes #4525. No review.
........
r24845 | plocinic | 2011-04-29 16:27:35 +0200 (Fri, 29 Apr 2011) | 1 line
remove now redundant check (see #4426). review by extempore ........
r24846 | plocinic | 2011-04-29 16:27:40 +0200 (Fri, 29 Apr 2011) | 1
line
Closes #4457. Review by odersky
........
r24847 | odersky | 2011-04-29 17:35:37 +0200 (Fri, 29 Apr 2011) | 1 line
Ignore type errors raised in later phases that are due to mismatching
existentials. Quick fix to address lift build failures. Review by
dragos. ........ r24848 | odersky | 2011-04-29 18:02:53 +0200 (Fri, 29
Apr 2011) | 1 line
Second version of trying to avoid the lift crasher bug. ........
r24849 | odersky | 2011-04-29 18:13:31 +0200 (Fri, 29 Apr 2011) | 1 line
Issuing warnings with detailed info when we encounter the lift crasher
case. ........ r24850 | michelou | 2011-04-29 21:41:12 +0200 (Fri, 29
Apr 2011) | 2 lines
removed legacy library code (package scala.mobile) ........ r24851 |
extempore | 2011-04-29 22:13:10 +0200 (Fri, 29 Apr 2011) | 4 lines
Fixing the pattern matcher regression I introduced between rc1 and
rc2. Not done with this situation but at least I managed to boil out
the big problem and keep my five closed pattern matcher tickets to
boot. Closes #4523, no review. ........ r24852 | extempore | 2011-04-30
00:40:03 +0200 (Sat, 30 Apr 2011) | 1 line
Making further unapply regressions less likely, no review. ........
r24853 | extempore | 2011-04-30 22:00:39 +0200 (Sat, 30 Apr 2011) | 3
lines
After having to update the code for someone else, ran damarau
levenshtein on trunk again. Patchwise, I guess correcting spelling
errors in comments is about as safe as it gets. No review. ........
r24854 | extempore | 2011-04-30 22:01:00 +0200 (Sat, 30 Apr 2011) | 1
line
Don't crash the pickler with erroneous types. Review by odersky.
........ r24855 | extempore | 2011-04-30 22:01:25 +0200 (Sat, 30 Apr
2011) | 4 lines
Completely to my surprise, found that fixing all those sequence issues
revealed that the pattern matcher can catch a lot more inexhaustive
cases than it has been catching. Fixed most of the inexhaustive matches
in the compiler, which had become a bit warnier. No review. ........
r24856 | extempore | 2011-04-30 22:01:48 +0200 (Sat, 30 Apr 2011) | 2
lines
A few minor cleanups involving logging messages, assertion messages,
compiler warnings, and other innocuous matters. No review. ........
r24857 | extempore | 2011-05-01 07:10:09 +0200 (Sun, 01 May 2011) | 2
lines
Don't issue a deprecation warning if the deprecated method is being
called from a bridge method. No review. ........ r24858 | extempore |
2011-05-01 07:10:58 +0200 (Sun, 01 May 2011) | 4 lines
Since I don't want to commit anything "interesting" until we ship 2.9,
a few uninteresting cleanups involving how types are printed, getting
some debugging code in shape to prepare for the long winter ahead, etc.
No review. ........ r24859 | extempore | 2011-05-01 07:43:05 +0200 (Sun,
01 May 2011) | 2 lines
Realized how noisy the @deprecated-takes-two-arguments message was and
quieted it down. Oh, and documented the arguments. No review. ........
r24860 | extempore | 2011-05-01 20:15:49 +0200 (Sun, 01 May 2011) | 7
lines
Reducing the sbt launcher footprint by eliminating val references
which go through the scala package object, since they lead to
otherwise unnecessary classes becoming required at startup. Mostly
this means library files with constructors like "Iterator.empty" or
"Stream.continually" receive a direct import of that companion. The one
slightly less than cosmetic change was moving the strange xml value
"$scope" back into Predef, because otherwise I have to touch the xml
code generation. No review. ........ r24861 | extempore | 2011-05-01
21:58:44 +0200 (Sun, 01 May 2011) | 2 lines
Added a @bridge'd $scope back to scala package object for binary
compat. No review. ........ r24862 | extempore | 2011-05-02 05:28:58
+0200 (Mon, 02 May 2011) | 4 lines
Figuring it couldn't hurt if more people had a command of some of
our binary compatibility impacting code, I went over the ModuleDef
elimination with my clarify stick and made the machinery more
transparent, to me anyway. Review by plocinic. ........
Diffstat (limited to 'test')
43 files changed, 830 insertions, 85 deletions
diff --git a/test/files/buildmanager/t2649/t2649.check b/test/files/buildmanager/t2649/t2649.check index 5b698ec03f..390f284fd3 100644 --- a/test/files/buildmanager/t2649/t2649.check +++ b/test/files/buildmanager/t2649/t2649.check @@ -3,7 +3,7 @@ compiling Set(A.scala, B.scala) Changes: Map() builder > A.scala compiling Set(A.scala) -Changes: Map(object A -> List(Changed(Definition(A.x))[method x changed from (zz: Int,yy: Int)Int to (yy: Int,zz: Int)Int flags: <method>])) -invalidate B.scala because it references changed definition [Changed(Definition(A.x))[method x changed from (zz: Int,yy: Int)Int to (yy: Int,zz: Int)Int flags: <method>]] +Changes: Map(object A -> List(Changed(Definition(A.x))[method x changed from (zz: Int, yy: Int)Int to (yy: Int, zz: Int)Int flags: <method>])) +invalidate B.scala because it references changed definition [Changed(Definition(A.x))[method x changed from (zz: Int, yy: Int)Int to (yy: Int, zz: Int)Int flags: <method>]] compiling Set(B.scala) Changes: Map(object B -> List()) diff --git a/test/files/buildmanager/t2790/t2790.check b/test/files/buildmanager/t2790/t2790.check index 3a57d28817..9d37ccea29 100644 --- a/test/files/buildmanager/t2790/t2790.check +++ b/test/files/buildmanager/t2790/t2790.check @@ -3,8 +3,8 @@ compiling Set(A.scala, B.scala) Changes: Map() builder > A.scala compiling Set(A.scala) -Changes: Map(object A -> List(Added(Definition(A.x)), Changed(Definition(A.x))[value x changed from (f: java.lang.String,g: Int)Int to (f: java.lang.String,g: Int)Int <and> (f: Int,g: Int)Int flags: <method>])) -invalidate B.scala because it references changed definition [Changed(Definition(A.x))[value x changed from (f: java.lang.String,g: Int)Int to (f: java.lang.String,g: Int)Int <and> (f: Int,g: Int)Int flags: <method>]] +Changes: Map(object A -> List(Added(Definition(A.x)), Changed(Definition(A.x))[value x changed from (f: java.lang.String, g: Int)Int to (f: java.lang.String, g: Int)Int <and> (f: Int, g: Int)Int flags: <method>])) +invalidate B.scala because it references changed definition [Changed(Definition(A.x))[value x changed from (f: java.lang.String, g: Int)Int to (f: java.lang.String, g: Int)Int <and> (f: Int, g: Int)Int flags: <method>]] compiling Set(B.scala) B.scala:2: error: type mismatch; found : Int(5) diff --git a/test/files/buildmanager/t3054/foo/Foo.scala b/test/files/buildmanager/t3054/foo/Foo.scala index c4838b9958..c0fcd97390 100644 --- a/test/files/buildmanager/t3054/foo/Foo.scala +++ b/test/files/buildmanager/t3054/foo/Foo.scala @@ -1,5 +1,5 @@ package foo class Foo { - def foo = println("foo") + def foo() = println("foo") } diff --git a/test/files/buildmanager/t4215/A.scala b/test/files/buildmanager/t4215/A.scala index fbddd93afc..9db40b0fee 100644 --- a/test/files/buildmanager/t4215/A.scala +++ b/test/files/buildmanager/t4215/A.scala @@ -1,5 +1,5 @@ class A { - def B { + def B() { object C } } diff --git a/test/files/continuations-neg/lazy.check b/test/files/continuations-neg/lazy.check index bfa44c59a4..b8c6887409 100644 --- a/test/files/continuations-neg/lazy.check +++ b/test/files/continuations-neg/lazy.check @@ -1,6 +1,6 @@ lazy.scala:5: error: type mismatch; found : Unit @scala.util.continuations.cpsParam[Unit,Unit] required: Unit - def foo = { - ^ + def foo() = { + ^ one error found diff --git a/test/files/continuations-neg/lazy.scala b/test/files/continuations-neg/lazy.scala index dffc57ffa0..3c8169dd46 100644 --- a/test/files/continuations-neg/lazy.scala +++ b/test/files/continuations-neg/lazy.scala @@ -2,14 +2,14 @@ import scala.util.continuations._ object Test { - def foo = { + def foo() = { lazy val x = shift((k:Unit=>Unit)=>k()) println(x) } def main(args: Array[String]) { reset { - foo + foo() } } diff --git a/test/files/neg/abstract-class-2.check b/test/files/neg/abstract-class-2.check new file mode 100644 index 0000000000..ca79dd8293 --- /dev/null +++ b/test/files/neg/abstract-class-2.check @@ -0,0 +1,5 @@ +abstract-class-2.scala:11: error: object creation impossible, since method f in trait S2 of type (x: P2.this.p.S1)Int is not defined +(Note that P.this.p.S1 does not match P2.this.S1: their prefixes (i.e. enclosing instances) differ) + object O2 extends S2 { + ^ +one error found diff --git a/test/files/neg/abstract-class-2.scala b/test/files/neg/abstract-class-2.scala new file mode 100644 index 0000000000..19f74f3da6 --- /dev/null +++ b/test/files/neg/abstract-class-2.scala @@ -0,0 +1,14 @@ +class P { + trait S1 + val p = new P + + trait S2 { + def f(x: p.S1): Int + } +} + +class P2 extends P { + object O2 extends S2 { + def f(x: S1) = 5 + } +} diff --git a/test/files/neg/abstract-class-error.check b/test/files/neg/abstract-class-error.check new file mode 100644 index 0000000000..87d148ecc5 --- /dev/null +++ b/test/files/neg/abstract-class-error.check @@ -0,0 +1,5 @@ +S.scala:1: error: class S needs to be abstract, since method g in class J of type (y: Int, z: java.util.List)Int is not defined +(Note that java.util.List does not match java.util.List[String]. To implement a raw type, use java.util.List[_]) +class S extends J { + ^ +one error found diff --git a/test/files/neg/abstract-class-error/J.java b/test/files/neg/abstract-class-error/J.java new file mode 100644 index 0000000000..5877f5cc5b --- /dev/null +++ b/test/files/neg/abstract-class-error/J.java @@ -0,0 +1,4 @@ +public abstract class J { + public abstract int f(); + public abstract int g(int y, java.util.List z); +}
\ No newline at end of file diff --git a/test/files/neg/abstract-class-error/S.scala b/test/files/neg/abstract-class-error/S.scala new file mode 100644 index 0000000000..67f6d8593e --- /dev/null +++ b/test/files/neg/abstract-class-error/S.scala @@ -0,0 +1,4 @@ +class S extends J { + def f() = 55 + def g(y: Int, z: java.util.List[String]) = 11 +} diff --git a/test/files/neg/accesses.check b/test/files/neg/accesses.check index 94fcd615bc..db58af12ce 100644 --- a/test/files/neg/accesses.check +++ b/test/files/neg/accesses.check @@ -1,17 +1,17 @@ -accesses.scala:23: error: overriding method f2 in class A of type => Unit; +accesses.scala:23: error: overriding method f2 in class A of type ()Unit; method f2 has weaker access privileges; it should not be private - private def f2: Unit = () + private def f2(): Unit = () ^ -accesses.scala:24: error: overriding method f3 in class A of type => Unit; +accesses.scala:24: error: overriding method f3 in class A of type ()Unit; method f3 has weaker access privileges; it should be at least protected - private[p2] def f3: Unit = () + private[p2] def f3(): Unit = () ^ -accesses.scala:25: error: overriding method f4 in class A of type => Unit; +accesses.scala:25: error: overriding method f4 in class A of type ()Unit; method f4 has weaker access privileges; it should be at least private[p1] - private[p2] def f4: Unit + private[p2] def f4(): Unit ^ -accesses.scala:26: error: overriding method f5 in class A of type => Unit; +accesses.scala:26: error: overriding method f5 in class A of type ()Unit; method f5 has weaker access privileges; it should be at least protected[p1] - protected[p2] def f5: Unit + protected[p2] def f5(): Unit ^ four errors found diff --git a/test/files/neg/accesses.scala b/test/files/neg/accesses.scala index 2a6b45c35b..b1df6c0e6c 100644 --- a/test/files/neg/accesses.scala +++ b/test/files/neg/accesses.scala @@ -1,27 +1,27 @@ package test.p1.p2 abstract class A { - private[p2] def f2: Unit - protected def f3: Unit - private[p1] def f4: Unit - protected[p1] def f5: Unit + private[p2] def f2(): Unit + protected def f3(): Unit + private[p1] def f4(): Unit + protected[p1] def f5(): Unit } abstract class OK1 extends A { - private[p1] def f2: Unit - protected[p2] def f3: Unit - private[test] def f4: Unit - protected[test] def f5: Unit + private[p1] def f2(): Unit + protected[p2] def f3(): Unit + private[test] def f4(): Unit + protected[test] def f5(): Unit } abstract class OK2 extends A { - protected[p1] def f2: Unit - def f3: Unit - protected[p1] def f4: Unit - def f5: Unit + protected[p1] def f2(): Unit + def f3(): Unit + protected[p1] def f4(): Unit + def f5(): Unit } abstract class Err1 extends A { - private def f2: Unit = () - private[p2] def f3: Unit = () - private[p2] def f4: Unit - protected[p2] def f5: Unit + private def f2(): Unit = () + private[p2] def f3(): Unit = () + private[p2] def f4(): Unit + protected[p2] def f5(): Unit } diff --git a/test/files/neg/bug1960.check b/test/files/neg/bug1960.check index 6615d90036..8e19f31ef5 100644 --- a/test/files/neg/bug1960.check +++ b/test/files/neg/bug1960.check @@ -1,4 +1,4 @@ bug1960.scala:5: error: parameter 'p' requires field but conflicts with p in 'TBase' -class Aclass (p: Int) extends TBase { def g{ f(p) } } +class Aclass (p: Int) extends TBase { def g() { f(p) } } ^ one error found diff --git a/test/files/neg/bug1960.scala b/test/files/neg/bug1960.scala index af7f270356..5311940b5a 100644 --- a/test/files/neg/bug1960.scala +++ b/test/files/neg/bug1960.scala @@ -2,4 +2,4 @@ object ClassFormatErrorExample extends App { new Aclass(1) } trait TBase { var p:Int = 0; def f(p1: Int) {} } -class Aclass (p: Int) extends TBase { def g{ f(p) } } +class Aclass (p: Int) extends TBase { def g() { f(p) } } diff --git a/test/files/neg/bug4533.check b/test/files/neg/bug4533.check new file mode 100644 index 0000000000..e1b60aa820 --- /dev/null +++ b/test/files/neg/bug4533.check @@ -0,0 +1,4 @@ +bug4533.scala:6: error: erroneous or inaccessible type + def statusByAlarms(alarms: GenTraversableOnce[FooAlarm]) = println("hello") + ^ +one error found diff --git a/test/files/neg/bug4533.scala b/test/files/neg/bug4533.scala new file mode 100644 index 0000000000..0346b5d1d5 --- /dev/null +++ b/test/files/neg/bug4533.scala @@ -0,0 +1,8 @@ +package demo + +import scala.collection._ + +class CrashDemo { + def statusByAlarms(alarms: GenTraversableOnce[FooAlarm]) = println("hello") +} +class FooAlarm { } diff --git a/test/files/neg/bug630.scala b/test/files/neg/bug630.scala index d236b51ffd..8a073963b0 100644 --- a/test/files/neg/bug630.scala +++ b/test/files/neg/bug630.scala @@ -1,7 +1,7 @@ trait Req1 trait Req2 { - def test = Console.println("Test") + def test() = Console.println("Test") } trait Foo { @@ -10,7 +10,7 @@ trait Foo { trait Bar { val foo : Req2 - def test = foo.test + def test() = foo.test } object Test diff --git a/test/files/neg/exhausting.check b/test/files/neg/exhausting.check index d3f2251f79..0bef21e077 100644 --- a/test/files/neg/exhausting.check +++ b/test/files/neg/exhausting.check @@ -2,7 +2,7 @@ exhausting.scala:20: error: match is not exhaustive! missing combination * Nil def fail1[T](xs: List[T]) = xs match { - ^ + ^ exhausting.scala:24: error: match is not exhaustive! missing combination Nil @@ -17,7 +17,7 @@ exhausting.scala:31: error: match is not exhaustive! missing combination Bar2 Bar2 def fail4[T <: AnyRef](xx: (Foo[T], Foo[T])) = xx match { - ^ + ^ exhausting.scala:36: error: match is not exhaustive! missing combination Bar1 Bar2 missing combination Bar1 Bar3 @@ -25,5 +25,5 @@ missing combination Bar2 Bar1 missing combination Bar2 Bar2 def fail5[T](xx: (Foo[T], Foo[T])) = xx match { - ^ + ^ 5 errors found diff --git a/test/files/neg/names-defaults-neg.check b/test/files/neg/names-defaults-neg.check index 5d409f18a8..d2bd2d123b 100644 --- a/test/files/neg/names-defaults-neg.check +++ b/test/files/neg/names-defaults-neg.check @@ -1,4 +1,4 @@ -names-defaults-neg.scala:65: error: not enough arguments for method apply: (a: Int,b: String)(c: Int*)Fact in object Fact. +names-defaults-neg.scala:65: error: not enough arguments for method apply: (a: Int, b: String)(c: Int*)Fact in object Fact. Unspecified value parameter b. val fac = Fact(1)(2, 3) ^ @@ -40,8 +40,8 @@ names-defaults-neg.scala:26: error: Int does not take parameters test3(b = 3, a = 1)(3) ^ names-defaults-neg.scala:35: error: ambiguous reference to overloaded definition, -both method f in object t1 of type (b: String,a: Int)java.lang.String -and method f in object t1 of type (a: Int,b: String)java.lang.String +both method f in object t1 of type (b: String, a: Int)java.lang.String +and method f in object t1 of type (a: Int, b: String)java.lang.String match argument types (b: java.lang.String,a: Int) t1.f(b = "dkljf", a = 1) ^ @@ -59,7 +59,7 @@ match argument types (Int) ^ names-defaults-neg.scala:49: error: ambiguous reference to overloaded definition, both method g in object t7 of type (a: B)java.lang.String -and method g in object t7 of type (a: C,b: Int*)java.lang.String +and method g in object t7 of type (a: C, b: Int*)java.lang.String match argument types (C) t7.g(new C()) // ambigous reference ^ @@ -73,19 +73,19 @@ names-defaults-neg.scala:55: error: when using named arguments, the vararg param test5(b = "dlkj") ^ names-defaults-neg.scala:61: error: ambiguous reference to overloaded definition, -both method f in object t8 of type (b: String,a: Int)java.lang.String -and method f in object t8 of type (a: Int,b: java.lang.Object)java.lang.String +both method f in object t8 of type (b: String, a: Int)java.lang.String +and method f in object t8 of type (a: Int, b: java.lang.Object)java.lang.String match argument types (a: Int,b: java.lang.String) and expected result type Any println(t8.f(a = 0, b = "1")) // ambigous reference ^ -names-defaults-neg.scala:69: error: wrong number of arguments for <none>: (x: Int,y: String)A1 +names-defaults-neg.scala:69: error: wrong number of arguments for <none>: (x: Int, y: String)A1 A1() match { case A1(_) => () } ^ names-defaults-neg.scala:76: error: no type parameters for method test4: (x: T[T[List[T[X forSome { type X }]]]])T[T[List[T[X forSome { type X }]]]] exist so that it can be applied to arguments (List[Int]) --- because --- argument expression's type is not compatible with formal parameter type; found : List[Int] - required: ?T[ ?T[ List[?T[ X forSome { type X } ]] ] ] + required: ?T[?T[List[?T[X forSome { type X }]]]] Error occurred in an application involving default arguments. test4() ^ diff --git a/test/files/neg/patmatexhaust.check b/test/files/neg/patmatexhaust.check index 83c4279b0a..8aa9238d2e 100644 --- a/test/files/neg/patmatexhaust.check +++ b/test/files/neg/patmatexhaust.check @@ -1,37 +1,38 @@ -patmatexhaust.scala:7: warning: match is not exhaustive! +patmatexhaust.scala:7: error: match is not exhaustive! missing combination Baz def ma1(x:Foo) = x match { ^ -patmatexhaust.scala:11: warning: match is not exhaustive! +patmatexhaust.scala:11: error: match is not exhaustive! missing combination Bar def ma2(x:Foo) = x match { ^ -patmatexhaust.scala:23: warning: match is not exhaustive! +patmatexhaust.scala:23: error: match is not exhaustive! missing combination Kult Kult missing combination Qult Qult def ma3(x:Mult) = (x,x) match { // not exhaustive - ^ -patmatexhaust.scala:49: warning: match is not exhaustive! + ^ +patmatexhaust.scala:49: error: match is not exhaustive! missing combination Gp missing combination Gu def ma4(x:Deep) = x match { // missing cases: Gu, Gp ^ -patmatexhaust.scala:53: warning: match is not exhaustive! +patmatexhaust.scala:53: error: match is not exhaustive! missing combination Gp def ma5(x:Deep) = x match { // Gp ^ -patmatexhaust.scala:75: warning: match is not exhaustive! +patmatexhaust.scala:59: error: match is not exhaustive! +missing combination Nil + + def ma6() = List(1,2) match { // give up + ^ +patmatexhaust.scala:75: error: match is not exhaustive! missing combination B def ma9(x: B) = x match { ^ -patmatexhaust.scala:92: error: unreachable code - case 1 => - ^ -6 warnings found -one error found +7 errors found diff --git a/test/files/neg/patmatexhaust.flags b/test/files/neg/patmatexhaust.flags new file mode 100644 index 0000000000..e8fb65d50c --- /dev/null +++ b/test/files/neg/patmatexhaust.flags @@ -0,0 +1 @@ +-Xfatal-warnings
\ No newline at end of file diff --git a/test/files/neg/patmatexhaust.scala b/test/files/neg/patmatexhaust.scala index b172df8740..d49c4b207b 100644 --- a/test/files/neg/patmatexhaust.scala +++ b/test/files/neg/patmatexhaust.scala @@ -56,12 +56,12 @@ class TestSealedExhaustive { // compile only case Ga => } - def ma6 = List(1,2) match { // give up + def ma6() = List(1,2) match { // give up case List(1,2) => case x :: xs => } - def ma7 = List(1,2) match { //exhaustive + def ma7() = List(1,2) match { //exhaustive case 1::2::Nil => case _ => } @@ -86,10 +86,4 @@ class TestSealedExhaustive { // compile only case C4() => true case C2 | C6 => true } - - def redundant = 1 match { // include this otherwise script won't test this in files/neg - case 1 => - case 1 => - } - } diff --git a/test/files/neg/t2910.check b/test/files/neg/t2910.check index afff73ec08..ff190122d6 100644 --- a/test/files/neg/t2910.check +++ b/test/files/neg/t2910.check @@ -13,4 +13,4 @@ t2910.scala:30: error: forward reference extends over definition of value x t2910.scala:34: error: forward reference extends over definition of variable x lazy val f: Int = g ^ -5 errors found
\ No newline at end of file +5 errors found diff --git a/test/files/neg/t2910.scala b/test/files/neg/t2910.scala index 1c7ba54971..b772ee4d43 100644 --- a/test/files/neg/t2910.scala +++ b/test/files/neg/t2910.scala @@ -5,13 +5,13 @@ object Junk { ret } - def test2 { + def test2() { println(s.length) val z = 0 lazy val s = "abc" } - def test4 { + def test4() { lazy val x = { x val z = 0 diff --git a/test/files/neg/t3115.check b/test/files/neg/t3115.check index 3da8c8d1c6..c128ff5f3f 100644 --- a/test/files/neg/t3115.check +++ b/test/files/neg/t3115.check @@ -1,11 +1,11 @@ t3115.scala:6: error: object Math in object sc is deprecated: println(sc.Math) ^ -t3115.scala:7: error: object Math in package scala is deprecated: use the scala.math package object instead. +t3115.scala:7: error: object Math is deprecated: use the scala.math package object instead. (Example package object usage: scala.math.Pi ) println(scala.Math) ^ -t3115.scala:8: error: object Math in package scala is deprecated: use the scala.math package object instead. +t3115.scala:8: error: object Math is deprecated: use the scala.math package object instead. (Example package object usage: scala.math.Pi ) scala.Math.Pi ^ diff --git a/test/files/neg/t3774.check b/test/files/neg/t3774.check index ea35c50541..cce2d7076c 100644 --- a/test/files/neg/t3774.check +++ b/test/files/neg/t3774.check @@ -1,6 +1,6 @@ t3774.scala:4: error: overloaded method value ++ with alternatives: [B1 >: List[Int]](xs: scala.collection.GenTraversableOnce[((Int, Int), B1)])scala.collection.immutable.Map[(Int, Int),B1] <and> - [B >: ((Int, Int), List[Int]),That](that: scala.collection.GenTraversableOnce[B])(implicit bf: scala.collection.generic.CanBuildFrom[scala.collection.immutable.Map[(Int, Int),List[Int]],B,That])That + [B >: ((Int, Int), List[Int]), That](that: scala.collection.GenTraversableOnce[B])(implicit bf: scala.collection.generic.CanBuildFrom[scala.collection.immutable.Map[(Int, Int),List[Int]],B,That])That cannot be applied to (scala.collection.immutable.IndexedSeq[((Int, Int), scala.collection.immutable.Range.Inclusive)]) Map[(Int,Int),List[Int]]() ++ (for(x <- 0 to 1 ; y <- 0 to 1) yield {(x,y)-> (0 to 1)}) ^ diff --git a/test/files/neg/t4457_1.check b/test/files/neg/t4457_1.check new file mode 100644 index 0000000000..c6b83c6ce5 --- /dev/null +++ b/test/files/neg/t4457_1.check @@ -0,0 +1,7 @@ +t4457_1.scala:27: error: ambiguous reference to overloaded definition, +both method aFunc in object ImplicitConvAmbiguity2 of type [A](a: ImplicitConvAmbiguity2.NZ[A])ImplicitConvAmbiguity2.AA[Float] +and method aFunc in object ImplicitConvAmbiguity2 of type [A](a: ImplicitConvAmbiguity2.NE[A])ImplicitConvAmbiguity2.AA[A] +match argument types (Float) + val x = aFunc(4F) + ^ +one error found diff --git a/test/files/neg/t4457_1.scala b/test/files/neg/t4457_1.scala new file mode 100644 index 0000000000..11f12379f6 --- /dev/null +++ b/test/files/neg/t4457_1.scala @@ -0,0 +1,33 @@ +object ImplicitConvAmbiguity2 { + + class N[T] + class NE[T] extends N[T] + class NN[T] extends N[T] + class NQ[T] extends N[T] + class NZ[T] extends N[T] + class AA[A] + class BB[A] + + implicit def conv1(i: Float) = new NE[Float] + implicit def conv3(op: AA[java.util.TooManyListenersException]) = new N[java.util.TooManyListenersException] + implicit def conv4(op: AA[Float]) = new N[Float] + implicit def conv7(i: Float) = new NZ[Float] + implicit def conv5(e: BB[java.util.GregorianCalendar]) = new N[java.util.GregorianCalendar] + + // These two will be in conflict in typeMe1 + def aFunc[A](a: NE[A]) = new AA[A] + def aFunc[A](a: NZ[A]) = new AA[Float] + + def aFunc[A](a: NN[A]) = new BB[A] + def aFunc[A](a: NQ[A]) = new BB[A] + + def bFunc[T](e1: N[T]) = {} + + def typeMe1 { + val x = aFunc(4F) + bFunc(x) + } + def typeMe2 { + bFunc(aFunc(4F)) + } +} diff --git a/test/files/neg/t4457_2.check b/test/files/neg/t4457_2.check new file mode 100644 index 0000000000..770a355395 --- /dev/null +++ b/test/files/neg/t4457_2.check @@ -0,0 +1,13 @@ +t4457_2.scala:27: error: ambiguous reference to overloaded definition, +both method aFunc in object ImplicitConvAmbiguity2 of type [A](a: ImplicitConvAmbiguity2.NZ[A])ImplicitConvAmbiguity2.AA[A] +and method aFunc in object ImplicitConvAmbiguity2 of type [A](a: ImplicitConvAmbiguity2.NE[A])ImplicitConvAmbiguity2.AA[A] +match argument types (Float) + val x = aFunc(4F) + ^ +t4457_2.scala:31: error: ambiguous reference to overloaded definition, +both method aFunc in object ImplicitConvAmbiguity2 of type [A](a: ImplicitConvAmbiguity2.NZ[A])ImplicitConvAmbiguity2.AA[A] +and method aFunc in object ImplicitConvAmbiguity2 of type [A](a: ImplicitConvAmbiguity2.NE[A])ImplicitConvAmbiguity2.AA[A] +match argument types (Float) + bFunc(aFunc(4F)) + ^ +two errors found diff --git a/test/files/neg/t4457_2.scala b/test/files/neg/t4457_2.scala new file mode 100644 index 0000000000..f3a170f1f2 --- /dev/null +++ b/test/files/neg/t4457_2.scala @@ -0,0 +1,33 @@ +object ImplicitConvAmbiguity2 { + + class N[T] + class NE[T] extends N[T] + class NN[T] extends N[T] + class NQ[T] extends N[T] + class NZ[T] extends N[T] + class AA[A] + class BB[A] + + implicit def conv1(i: Float) = new NE[Float] + implicit def conv3(op: AA[java.util.TooManyListenersException]) = new N[java.util.TooManyListenersException] + implicit def conv4(op: AA[Float]) = new N[Float] + implicit def conv7(i: Float) = new NZ[Float] + implicit def conv5(e: BB[java.util.GregorianCalendar]) = new N[java.util.GregorianCalendar] + + def aFunc[A](a: NE[A]) = new AA[A] + def aFunc[A](a: NZ[A]) = new AA[A] + + def aFunc[A](a: NN[A]) = new BB[A] + + def aFunc[A](a: NQ[A]) = new BB[A] + + def bFunc[T](e1: N[T]) = {} + + def typeMe2 { + val x = aFunc(4F) + bFunc(x) + } + def typeMe1 { + bFunc(aFunc(4F)) + } +} diff --git a/test/files/neg/tailrec.scala b/test/files/neg/tailrec.scala index a77f439cfe..e0ebde9863 100644 --- a/test/files/neg/tailrec.scala +++ b/test/files/neg/tailrec.scala @@ -10,7 +10,7 @@ object Winners { @tailrec def loopsucc1(x: Int): Int = loopsucc1(x - 1) @tailrec def loopsucc2[T](x: Int): Int = loopsucc2[T](x - 1) - def ding { + def ding() { object dong { @tailrec def loopsucc3(x: Int): Int = loopsucc3(x) } diff --git a/test/files/neg/tcpoly_infer_ticket1162.check b/test/files/neg/tcpoly_infer_ticket1162.check index 03334222c1..67b79e7f3c 100644 --- a/test/files/neg/tcpoly_infer_ticket1162.check +++ b/test/files/neg/tcpoly_infer_ticket1162.check @@ -1,4 +1,4 @@ -tcpoly_infer_ticket1162.scala:6: error: wrong number of type parameters for method apply: [A,B,F[_]]()Test.Lift[A,B,F] in object Lift +tcpoly_infer_ticket1162.scala:6: error: wrong number of type parameters for method apply: [A, B, F[_]]()Test.Lift[A,B,F] in object Lift def simplify[A,B]: Expression[A,B] = Lift[A,B]() ^ one error found diff --git a/test/files/neg/varargs.check b/test/files/neg/varargs.check index 1352dd968c..676a611341 100644 --- a/test/files/neg/varargs.check +++ b/test/files/neg/varargs.check @@ -1,10 +1,10 @@ -varargs.scala:16: error: A method with a varargs annotation produces a forwarder method with the same signature (a: Int,b: Array[java.lang.String])Int as an existing method. +varargs.scala:16: error: A method with a varargs annotation produces a forwarder method with the same signature (a: Int, b: Array[java.lang.String])Int as an existing method. @varargs def v1(a: Int, b: String*) = a + b.length ^ varargs.scala:19: error: A method without repeated parameters cannot be annotated with the `varargs` annotation. @varargs def nov(a: Int) = 0 ^ -varargs.scala:21: error: A method with a varargs annotation produces a forwarder method with the same signature (a: Int,b: Array[java.lang.String])Int as an existing method. +varargs.scala:21: error: A method with a varargs annotation produces a forwarder method with the same signature (a: Int, b: Array[java.lang.String])Int as an existing method. @varargs def v2(a: Int, b: String*) = 0 ^ -three errors found
\ No newline at end of file +three errors found diff --git a/test/files/pos/t4457_1.scala b/test/files/pos/t4457_1.scala new file mode 100644 index 0000000000..32edd6cfdc --- /dev/null +++ b/test/files/pos/t4457_1.scala @@ -0,0 +1,26 @@ +object ImplicitConvAmbiguity2 { + + class N[T] + class NE[T] extends N[T] + class NN[T] extends N[T] + class AA[A] + class BB[A] + + implicit def conv1(i: Float) = new NE[Float] + implicit def conv3(op: AA[java.util.TooManyListenersException]) = new N[java.util.TooManyListenersException] + implicit def conv4(op: AA[Float]) = new N[Float] + implicit def conv5(e: BB[java.util.GregorianCalendar]) = new N[java.util.GregorianCalendar] + + def aFunc[A](a: NE[A]) = new AA[A] + def aFunc[A](a: NN[A]) = new BB[A] + + def bFunc[T](e1: N[T]) = {} + + def typeMe1 { + val x = aFunc(4F) + bFunc(x) + } + def typeMe2 { + bFunc(aFunc(4F)) + } +} diff --git a/test/files/res/bug722/Parser.scala b/test/files/res/bug722/Parser.scala index 6d9739ed04..7f84cb2b63 100644 --- a/test/files/res/bug722/Parser.scala +++ b/test/files/res/bug722/Parser.scala @@ -2,7 +2,7 @@ package bug722; trait Parser { trait Link { - def foo = {} + def foo() = {} } } diff --git a/test/files/res/bug722/ScanBased.scala b/test/files/res/bug722/ScanBased.scala index fcb853f96d..4793a04914 100644 --- a/test/files/res/bug722/ScanBased.scala +++ b/test/files/res/bug722/ScanBased.scala @@ -1,10 +1,10 @@ package bug722; trait ScanBased extends Parser { trait AdjacentLink extends Link { - override def foo = super.foo; + override def foo() = super.foo; } trait WhitespaceLink extends AdjacentLink { - override def foo = super.foo; + override def foo() = super.foo; } } diff --git a/test/files/res/bug785/ScalaNewTyper.scala b/test/files/res/bug785/ScalaNewTyper.scala index fb955572ed..d55d60a8d0 100644 --- a/test/files/res/bug785/ScalaNewTyper.scala +++ b/test/files/res/bug785/ScalaNewTyper.scala @@ -2,7 +2,7 @@ package bug785; trait ScalaNewTyper { private var typed : String = null; trait HasSymbol { - protected def foo : Unit = {} + protected def foo() : Unit = {} } trait HasArgsTypeParametersImpl extends HasSymbol { private var argss : List[List[String]] = Nil; diff --git a/test/files/run/io-position.check b/test/files/run/io-position.check Binary files differnew file mode 100644 index 0000000000..09f743d750 --- /dev/null +++ b/test/files/run/io-position.check diff --git a/test/files/run/io-position.scala b/test/files/run/io-position.scala new file mode 100644 index 0000000000..7e570ea29e --- /dev/null +++ b/test/files/run/io-position.scala @@ -0,0 +1,13 @@ +object Test { + Console.setErr(Console.out) + + def main(args: Array[String]): Unit = { + try { + xml.parsing.ConstructingParser.fromSource(io.Source.fromString("<foo>"), false).document() + } catch { + case e:Exception => println(e.getMessage) + } + } + +} + diff --git a/test/files/run/patmat-exprs.check b/test/files/run/patmat-exprs.check new file mode 100644 index 0000000000..b6df9385fa --- /dev/null +++ b/test/files/run/patmat-exprs.check @@ -0,0 +1 @@ +((5 + 10) + 300) diff --git a/test/files/run/patmat-exprs.scala b/test/files/run/patmat-exprs.scala new file mode 100644 index 0000000000..f502a14832 --- /dev/null +++ b/test/files/run/patmat-exprs.scala @@ -0,0 +1,579 @@ +import runtime.ScalaRunTime + +object Test { + val p = new Pattern { } + import p._ + implicit object IntOps extends NumericOps[Int] { + def zero = 0 + def one = 1 + + def add(a: Int, b: Int): Int = a + b + def sub(a: Int, b: Int): Int = a - b + def mul(a: Int, b: Int): Int = a * b + def mul(a: Int, b: Double): Int = (a * b).toInt + def div(a: Int, b: Int): Int = a / b + def div(a: Int, b: Double): Int = (a / b).toInt + def similar(a: Int, b: Int): Boolean = a == b + def abs(a: Int): Double = math.abs(a).toDouble + def sqr(a: Int): Int = a * a + def sqrt(a: Int): Int = math.sqrt(a).toInt + def log(a: Int): Int = math.log(a).toInt + def exp(a: Int): Int = math.exp(a).toInt + def sin(a: Int): Int = math.sin(a).toInt + def cos(a: Int): Int = math.cos(a).toInt + + def fromDouble(a: Double): Int = a.toInt + def fromInt(a: Int): Int = a + } + + def main(args: Array[String]): Unit = { + println((5: Expr[Int]) + 10 + 15 * 20) + } +} + + +trait Pattern { + // For trying out 2.7.7 + // + // type Numeric[T] + // import java.io.Serializable + // + // implicit def compat27a[T](x: Iterable[T]) = new { + // def iterator: Iterator[T] = x.elements + // def sum: Int = 5 + // def collect[U](pf: PartialFunction[T, U]): Iterable[U] = x map pf + // } + + /** Function that returns object of the same type it was passed */ + trait EndoFunction[-A] { + def apply[B <: A](x: B): B + } + + /** Allows for smart construction of EndoFunction from an ordinary function */ + object EndoFunction { + def apply[A](f: A => A): EndoFunction[A] = new EndoFunction[A] { + def apply[B <: A](x: B): B = f(x).asInstanceOf[B] + } + } + + trait NumericOps[T] extends Serializable { + def zero: T + def one: T + def two = add(one, one) + def three = add(two, one) + + def add(a: T, b: T): T + def add(a: T, b: T, c: T): T = add(a, add(b, c)) + def sub(a: T, b: T): T + def mul(a: T, b: T): T + def mul(a: T, b: Double): T + def div(a: T, b: T): T + def div(a: T, b: Double): T + def similar(a: T, b: T): Boolean + def neg(a: T) = sub(zero, a) + def abs(a: T): Double + def sqr(a: T): T + def sqrt(a: T): T + def log(a: T): T + def exp(a: T): T + def sin(a: T): T + def cos(a: T): T + def tan(a: T): T = div(sin(a), cos(a)) + + def fromDouble(a: Double): T + def fromInt(a: Int): T + + def sum(terms: Iterable[T]) = terms.foldLeft(zero)(add) + def sum(terms: Iterator[T]) = terms.foldLeft(zero)(add) + def product(terms: Iterable[T]) = terms.foldLeft(one)(mul) + def product(terms: Iterator[T]) = terms.foldLeft(one)(mul) + + + def similar(a: Iterable[T], b: Iterable[T]): Boolean = { + val i1 = a.iterator + val i2 = b.iterator + while (i1.hasNext && i2.hasNext) + if (!similar(i1.next, i2.next)) + return false; + true; + } + } + + /** + * Simple expression interpreter with some basic symbolic manipulation. + * Able to evaluate derivatives. + */ + + trait Expr[T] { + + import Expr._ + + /** Evaluates value of the expression. */ + def eval(context: Any => Any): T + + /** Symbolically calculates derivative of this expression. Does not simplify it. */ + def derivative(variable: Var[T]): Expr[T] + + /** Returns arguments of this operator */ + def args: Iterable[Expr[_]] + + /** Transforms arguments of this operator by applying given function. */ + def mapArgs(f: EndoFunction[Expr[_]]): Expr[T] + + /** Transforms this operator and its arguments by applying given function */ + def map(f: EndoFunction[Expr[_]]): Expr[T] = + f(mapArgs(EndoFunction[Expr[_]](x => x.map(f)))) + + /** Folds all subexpressions in this expression in depth-first order */ + def fold[A](v: A)(f: (A, Expr[_]) => A): A = + f(args.foldLeft(v) { (a, b) => b.fold(a)(f) }, this) + + /** Replaces all occurrences of one subexpression with another one */ + def replace(from: Expr[_], to: Expr[_]): Expr[T] = + map(EndoFunction[Expr[_]](x => if (x == from) to else x)) + + /** Returns true if this expression contains given subexpression */ + def contains(s: Expr[_]): Boolean = + this == s || args.exists(_ contains s) + + /** Counts number of occurrences of the given subexpression. */ + def count(condition: Expr[_] => Boolean): Int = + (if (condition(this)) 1 else 0) + args.map(_.count(condition)).sum + + /** Executes some code for every subexpression in the depth-first order */ + def foreach[U](block: Expr[_] => U): Unit = { + args.foreach(_.foreach(block)) + block(this) + } + + /** Collects subexpressions successfully transformed by the given partial function, in depth-first order. */ + def collect[U](f: PartialFunction[Expr[_], U]): List[U] = { + val a = args.flatMap(_.collect(f)).toList + if (f.isDefinedAt(this)) (f(this) :: a) else a + } + + def leaves: List[Leaf[T]] = collect { case l: Leaf[T] => l } + + def + (other: Expr[T])(implicit n: NumericOps[T]) = Add(List(this, other)) + def - (other: Expr[T])(implicit n: NumericOps[T]) = Sub(this, other) + def * (other: Expr[T])(implicit n: NumericOps[T]) = Mul(this, other) + def / (other: Expr[T])(implicit n: NumericOps[T]) = Div(this, other) + + def unary_- (implicit n: NumericOps[T]) = Neg(this) + def sqr(implicit n: NumericOps[T]) = Sqr(this) + + def < (other: Expr[T])(implicit n: NumericOps[T], o: Ordering[T]) = LT(this, other) + def <= (other: Expr[T])(implicit n: NumericOps[T], o: Ordering[T]) = LE(this, other) + def > (other: Expr[T])(implicit n: NumericOps[T], o: Ordering[T]) = GT(this, other) + def >= (other: Expr[T])(implicit n: NumericOps[T], o: Ordering[T]) = GE(this, other) + + private def generalize(implicit num: NumericOps[T]): Expr[T] = { + this match { + case Add2(a, b) => Add(a :: b :: Nil) + case Add3(a, b, c) => Add(a :: b :: c :: Nil) + case Sub(a, b) => Add(a :: Neg(b) :: Nil) + case Add(x) => Add(x flatMap { + case Neg(Add(y)) => y.map(Neg(_)) + case Add(y) => y + case y => y :: Nil + }) + case x => x + } + } + + private def specialize(implicit num: NumericOps[T]): Expr[T] = { + this match { + case Add(Seq(a, b)) => Add2(a, b) + case Add(Seq(a, b, c)) => Add3(a, b, c) + case x => x + } + } + + /** Eliminates common negated components of a sum */ + private def reduceComponents(components: List[Expr[T]])(implicit num: NumericOps[T]): List[Expr[T]] = { + val pairs = + for (a <- components; b <- components if Neg(a) == b || a == Neg(b)) + yield (a, b) + pairs.foldLeft(components) { (c, pair) => + if (c.contains(pair._1) && c.contains(pair._2)) + c.diff(pair._1 :: pair._2 :: Nil) + else + c + } + } + + + /** Simplifies this expression to make evaluation faster and more accurate. + * Performs only one pass. */ + private def reduce(implicit num: NumericOps[T]): Expr[T] = { + this match { + case Add(Seq(Neg(x), Neg(y), Neg(z))) => Neg(Add(List(x, y, z))) + case Add(Seq(Mul(x, y), z)) if (x == z) => Mul(x, Add(List(y, One[T]))) + case Add(Seq(Mul(x, y), z)) if (y == z) => Mul(y, Add(List(z, One[T]))) + case Add(Seq(Mul(x, y), Mul(u, w))) if (x == u) => Mul(x, Add(List(y, w))) + case Add(Seq(Mul(x, y), Mul(u, w))) if (y == w) => Mul(y, Add(List(x, u))) + case Add(Seq(Add(x), Add(y))) => Add(x.toList ::: y.toList).simplify + case Add(Seq(Add(x), y)) => Add(y :: x.toList).simplify + case Add(Seq(x, Add(y))) => Add(x :: y.toList).simplify + case Add(x) => { + val noZeros = x.filter(_ != Zero[T]) + val noOnes = noZeros.map { case y: One[_] => Const(num.one); case y => y } + val constant = num.sum(noOnes.collect { case c: Const[T] => c.value }) + val rest = noOnes.filter(x => !x.isInstanceOf[Const[_]]).toList + val reduced = reduceComponents(rest) + val args = if (num.similar(constant, num.zero)) reduced else reduced ::: Const(constant) :: Nil + args.size match { + case 0 => Zero[T] + case 1 => args.head + case 2 => Add2(args(0), args(1)) + case 3 => Add3(args(0), args(1), args(2)) + case _ => Add(args) + } + } + case Sub(x: Zero[_], y) => Neg(y) + case Sub(x, y: Zero[_]) => x + case Sub(x, y) if x == y => Zero[T] + case Sub(Mul(x, y), z) if (x == z) => Mul(x, Sub(y, One[T])) + case Sub(Mul(x, y), z) if (y == z) => Mul(y, Sub(z, One[T])) + case Sub(Mul(x, y), Mul(u, w)) if (x == u) => Mul(x, Sub(y, w)) + case Sub(Mul(x, y), Mul(u, w)) if (y == w) => Mul(y, Sub(x, u)) + case Mul(x: Zero[_], y) => Zero[T] + case Mul(x, y: Zero[_]) => Zero[T] + case Mul(x: One[_], y) => y + case Mul(x, y: One[_]) => x + case Mul(Neg(x: One[_]), y) => Neg(y) + case Mul(x, Neg(y: One[_])) => Neg(x) + + case Mul(x, y) if (x == y) => Sqr(x) + case Div(x: Zero[_], y) => Zero[T] // warning: possibly extends domain + case Div(x, y: One[_]) => x + case Div(Sqr(x), y) if x == y => x + case Div(Mul(x, y), z) if (x == z) => y + case Div(Mul(x, y), z) if (y == z) => y + case Div(Mul(Mul(x, y), z), w) if (x == w) => Mul(y, z) + case Div(Mul(Mul(x, y), z), w) if (y == w) => Mul(x, z) + case Div(Mul(z, Mul(x, y)), w) if (x == w) => Mul(y, z) + case Div(Mul(z, Mul(x, y)), w) if (y == w) => Mul(x, z) + case Div(Mul(x, y), Mul(u, w)) if (x == u) => Div(y, w) + case Div(Mul(x, y), Mul(u, w)) if (y == w) => Div(x, u) + case Div(x: One[_], y) => Inv(y) + case Div(x, Sqr(y)) if x == y => Inv(y) + case Div(Mul(x, y), Sqr(Mul(u, w))) if x == u && y == w => Inv(Mul(x, y)) + case Div(x, y) if x == y => One[T] + + case Mul(Neg(a), Neg(b)) => Mul(a, b) + case Div(Neg(a), Neg(b)) => Div(a, b) + + case Neg(x: Zero[_]) => Zero[T] + case Neg(x: One[_]) => Const(num.neg(num.one)) + case Sub(Const(x), Const(y)) => const(num.sub(x, y)) + case Mul(Const(x), Const(y)) => const(num.mul(x, y)) + case Div(Const(x), Const(y)) => const(num.div(x, y)) + case Neg(Const(x)) => const(num.neg(x)) + case Sqr(Const(x)) => const(num.sqr(x)) + + case Mul(Const(x), Mul(Const(y), z)) => Mul(const(num.mul(x, y)), z) + case Mul(Const(x), Mul(y, Const(z))) => Mul(const(num.mul(x, z)), y) + case Mul(Mul(Const(y), z), Const(x)) => Mul(const(num.mul(x, y)), z) + case Mul(Mul(y, Const(z)), Const(x)) => Mul(const(num.mul(x, z)), y) + + case Const(x) if x == num.one => One[T] + case Const(x) if x == num.zero => Zero[T] + + case Sub(x, Neg(y)) => Add(List(x, y)) + case Sub(Neg(x), y) => Neg(Add(List(x, y))) + case Neg(Neg(x)) => x + case Neg(Mul(a: Const[T], x)) => Mul(const(num.neg(a.value)), x) + case Neg(Mul(x, a: Const[T])) => Mul(const(num.neg(a.value)), x) + case Neg(Div(Neg(a), b)) => Div(a, b) + case Neg(Div(a, Neg(b))) => Div(a, b) + case Neg(Mul(Neg(a), b)) => Mul(a, b) + case Neg(Mul(a, Neg(b))) => Mul(a, b) + + case Log(Exp(x)) => x + case x => x + } + } + + private def optimizeWith(f: Expr[T] => Expr[T]): Expr[T] = { + f(mapArgs(EndoFunction[Expr[_]]( + a => a match { case x: Expr[T] => x.optimizeWith(f) } + ))) + } + + /** Simplifies this expression to make evaluation faster and more accurate.*/ + def simplify(implicit num: NumericOps[T]): Expr[T] = { + val a1 = optimizeWith(_.generalize) + val a2 = a1.optimizeWith(_.generalize) + val b = a2.optimizeWith(_.reduce) + val c = b.optimizeWith(_.reduce) + val d = c.optimizeWith(_.specialize) + d + } + } + + + trait Leaf[T] extends Expr[T] { + val args = List[Expr[T]]() + def mapArgs(f: EndoFunction[Expr[_]]) = this + } + + trait OneArg[T] extends Expr[T] { + val expr: Expr[T] + val args = List(expr) + } + + + trait TwoArg[T] extends Expr[T] { + val left: Expr[T] + val right: Expr[T] + val args = List(left, right) + } + + trait ManyArg[T] extends Expr[T] + + /** Marker trait for specifying that you can safely divide by this */ + trait NonZero[T] extends Expr[T] + + case class Const[T](value: T)(implicit num: NumericOps[T]) extends Leaf[T] with NonZero[T] { + def derivative(variable: Var[T]) = Zero[T] + def eval(f: Any => Any) = value + override def toString = value.toString + } + + + case class Zero[T] (implicit num: NumericOps[T]) extends Leaf[T] { + def derivative(variable: Var[T]) = Zero[T] + def eval(f: Any => Any) = num.zero + override def toString = "0" + } + + case class One[T] (implicit num: NumericOps[T]) extends Leaf[T] { + def derivative(variable: Var[T]) = Zero[T] + def eval(f: Any => Any) = num.one + override def toString = "1" + } + + abstract class Var[T](implicit num: NumericOps[T]) extends Leaf[T] { + def derivative(variable: Var[T]) = if (variable == this) One[T] else Zero[T] + def eval(f: Any => Any) = f(this).asInstanceOf[T] + } + + case class NamedVar[T](name: String)(implicit num: NumericOps[T]) extends Var[T] { + override lazy val hashCode = ScalaRunTime._hashCode(this) + override def toString = name + } + + case class Add[T](args: Iterable[Expr[T]])(implicit num: NumericOps[T]) extends ManyArg[T] { + def eval(f: Any => Any) = num.sum(for (i <- args.iterator) yield i.eval(f)) + def derivative(v: Var[T]) = Add(args.map(_.derivative(v))) + def mapArgs(f: EndoFunction[Expr[_]]) = Add(args map (x => f(x))) + override def toString = "(" + args.mkString(" + ") + ")" + override lazy val hashCode = ScalaRunTime._hashCode(this); + } + + + case class Add2[T](left: Expr[T], right: Expr[T]) + (implicit num: NumericOps[T]) extends TwoArg[T] { + def eval(f: Any => Any) = num.add(left.eval(f), right.eval(f)) + def derivative(v: Var[T]) = Add2(left.derivative(v), right.derivative(v)) + def mapArgs(f: EndoFunction[Expr[_]]) = Add2(f(left), f(right)) + override def toString = "(" + left + " + " + right + ")" + override lazy val hashCode = ScalaRunTime._hashCode(this); + } + + case class Add3[T](a1: Expr[T], a2: Expr[T], a3: Expr[T]) + (implicit num: NumericOps[T]) extends ManyArg[T] { + val args = List(a1, a2, a3) + def eval(f: Any => Any) = num.add(a1.eval(f), a2.eval(f), a3.eval(f)) + def derivative(v: Var[T]) = Add3(a1.derivative(v), a2.derivative(v), a3.derivative(v)) + def mapArgs(f: EndoFunction[Expr[_]]) = Add3(f(a1), f(a2), f(a3)) + override def toString = "(" + a1 + " + " + a2 + " + " + a3 + ")" + override lazy val hashCode = ScalaRunTime._hashCode(this); + } + + + case class Sub[T](left: Expr[T], right: Expr[T]) + (implicit num: NumericOps[T]) extends TwoArg[T] { + def derivative(v: Var[T]) = Sub(left.derivative(v), right.derivative(v)) + def eval(f: Any => Any) = num.sub(left.eval(f), right.eval(f)) + def mapArgs(f: EndoFunction[Expr[_]]) = Sub(f(left), f(right)) + override def toString = "(" + left + " - " + right + ")" + override lazy val hashCode = ScalaRunTime._hashCode(this); + } + + case class Neg[T](expr: Expr[T]) + (implicit num: NumericOps[T]) extends OneArg[T] { + def derivative(v: Var[T]) = Neg(expr.derivative(v)) + def eval(f: Any => Any) = num.neg(expr.eval(f)) + def mapArgs(f: EndoFunction[Expr[_]]) = Neg(f(expr)) + override def toString = "(-" + expr + ")" + override lazy val hashCode = ScalaRunTime._hashCode(this); + + } + + case class Mul[T](left: Expr[T], right: Expr[T]) + (implicit num: NumericOps[T]) extends TwoArg[T] { + def derivative(v: Var[T]) = + Add(List( + Mul(left, right.derivative(v)), + Mul(right, left.derivative(v)))) + + def eval(f: Any => Any) = num.mul(left.eval(f), right.eval(f)) + def mapArgs(f: EndoFunction[Expr[_]]) = Mul(f(left), f(right)) + override def toString = "(" + left + " * " + right + ")" + override lazy val hashCode = ScalaRunTime._hashCode(this); + } + + case class Div[T](left: Expr[T], right: Expr[T]) + (implicit num: NumericOps[T]) extends TwoArg[T] { + + // [f(x) / g(x)]' = [f(x) * 1 / g(x)]' = f'(x) * 1 / g(x) + f(x) * [1 / g(x)]' = + // f'(x) / g(x) + f(x) * [-1 / g(x) ^ 2] * g'(x) = (f'(x) * g(x) - f(x) * g'(x)) / g(x)^2 + def derivative(v: Var[T]) = + Div( + Sub( + Mul(left.derivative(v), right), + Mul(left, right.derivative(v))), + Sqr(right) + ) + + def eval(f: Any => Any) = num.div(left.eval(f), right.eval(f)) + def mapArgs(f: EndoFunction[Expr[_]]) = + Div(f(left), f(right)) + override def toString = "(" + left + " / " + right + ")" + override lazy val hashCode = ScalaRunTime._hashCode(this); + } + + case class Inv[T](expr: Expr[T])(implicit num: NumericOps[T]) extends OneArg[T] { + + // [1 / f(x)]' = - f'(x) / f(x) ^ 2 + def derivative(v: Var[T]) = Neg(Div(expr.derivative(v), Sqr(expr))) + def eval(f: Any => Any) = num.div(num.one, expr.eval(f)) + def mapArgs(f: EndoFunction[Expr[_]]) = Inv(f(expr)) + override def toString = "(1 / " + expr + ")" + override lazy val hashCode = ScalaRunTime._hashCode(this); + } + + case class Sqr[T](expr: Expr[T])(implicit num: NumericOps[T]) extends OneArg[T] { + // [f(x) ^ 2]' = 2 * f(x) * f'(x) + def derivative(v: Var[T]) = Mul(Mul(Const(num.two), expr), expr.derivative(v)) + def eval(f: Any => Any) = num.sqr(expr.eval(f)) + def mapArgs(f: EndoFunction[Expr[_]]) = Sqr(f(expr)) + override def toString = expr + " ^ 2" + override lazy val hashCode = ScalaRunTime._hashCode(this); + } + + + case class Log[T](expr: Expr[T])(implicit num: NumericOps[T]) extends OneArg[T] { + def derivative(v: Var[T]) = Div(expr.derivative(v), expr) + def eval(f: Any => Any) = num.log(expr.eval(f)) + def mapArgs(f: EndoFunction[Expr[_]]) = Log(f(expr)) + override def toString = "log(" + expr + ")" + override lazy val hashCode = ScalaRunTime._hashCode(this); + } + + + case class Exp[T](expr: Expr[T])(implicit num: NumericOps[T]) extends OneArg[T] { + def derivative(v: Var[T]) = Mul(expr.derivative(v), Exp(expr)) + def eval(f: Any => Any) = num.exp(expr.eval(f)) + def mapArgs(f: EndoFunction[Expr[_]]) = Exp(f(expr)) + override def toString = "exp(" + expr + ")" + override lazy val hashCode = ScalaRunTime._hashCode(this); + } + + case class Sqrt[T](expr: Expr[T])(implicit num: NumericOps[T]) extends OneArg[T] { + def derivative(v: Var[T]) = Neg(Div(expr.derivative(v), Sqrt(expr))) + def eval(f: Any => Any) = num.sqrt(expr.eval(f)) + def mapArgs(f: EndoFunction[Expr[_]]) = Sqrt(f(expr)) + override def toString = "sqrt(" + expr + ")" + override lazy val hashCode = ScalaRunTime._hashCode(this); + } + + + case class Sin[T](expr: Expr[T])(implicit num: NumericOps[T]) extends OneArg[T] { + def derivative(v: Var[T]) = Mul(expr.derivative(v), Cos(expr)) + def eval(f: Any => Any) = num.sin(expr.eval(f)) + def mapArgs(f: EndoFunction[Expr[_]]) = Sin(f(expr)) + override def toString = "sin(" + expr + ")" + override lazy val hashCode = ScalaRunTime._hashCode(this); + } + + + case class Cos[T](expr: Expr[T])(implicit num: NumericOps[T]) extends OneArg[T] { + def derivative(v: Var[T]) = Neg(Mul(expr.derivative(v), Sin(expr))) + def eval(f: Any => Any) = num.cos(expr.eval(f)) + def mapArgs(f: EndoFunction[Expr[_]]) = Cos(f(expr)) + override def toString = "cos(" + expr + ")" + override lazy val hashCode = ScalaRunTime._hashCode(this); + } + + + abstract class Compare[T](left: Expr[T], right: Expr[T], cmp: (T, T) => Boolean)(implicit num: NumericOps[T]) + extends Expr[Boolean] { + def derivative(v: Var[Boolean]) = throw new IllegalStateException("Derivative of Boolean not allowed") + def eval(f: Any => Any) = cmp(left.eval(f), right.eval(f)) + val args = List(left, right) + } + + case class LE[T](left: Expr[T], right: Expr[T])(implicit num: NumericOps[T], ord: Ordering[T]) + extends Compare[T](left, right, ord.compare(_, _) <= 0) { + def mapArgs(f: EndoFunction[Expr[_]]) = LE( + f(left), f(right)) + override def toString = left.toString + " <= " + right.toString + } + + case class LT[T](left: Expr[T], right: Expr[T])(implicit num: NumericOps[T], ord: Ordering[T]) + extends Compare[T](left, right, ord.compare(_, _) < 0) { + def mapArgs(f: EndoFunction[Expr[_]]) = LT( + f(left), f(right)) + override def toString = left.toString + " < " + right.toString + } + + case class GE[T](left: Expr[T], right: Expr[T])(implicit num: NumericOps[T], ord: Ordering[T]) + extends Compare[T](left, right, ord.compare(_, _) >= 0) { + def mapArgs(f: EndoFunction[Expr[_]]) = GE( + f(left), f(right)) + override def toString = left.toString + " >= " + right.toString + } + + case class GT[T](left: Expr[T], right: Expr[T])(implicit num: NumericOps[T], ord: Ordering[T]) + extends Compare[T](left, right, ord.compare(_, _) > 0) { + def mapArgs(f: EndoFunction[Expr[_]]) = GT( + f(left), f(right)) + override def toString = left.toString + " > " + right.toString + } + + case class IfElse[T <: Numeric[T]] + (condition: Expr[Boolean], left: Expr[T], right: Expr[T])(implicit num: NumericOps[T]) extends Expr[T] { + + val args = List(condition, left, right) + def derivative(v: Var[T]) = IfElse(condition, left.derivative(v), right.derivative(v)) + def eval(f: Any => Any) = if (condition.eval(f)) left.eval(f) else right.eval(f) + def mapArgs(f: EndoFunction[Expr[_]]) = IfElse( + f(condition).asInstanceOf[Expr[Boolean]], + f(left), + f(right)) + override def toString = "if (" + condition + ")(" + left + ") else (" + right + ")" + override lazy val hashCode = ScalaRunTime._hashCode(this); + } + + object Expr { + /** Creates a constant expression */ + def const[T](value: T)(implicit num: NumericOps[T]): Leaf[T] = + if (num.zero == value) Zero[T] + else Const(value) + + implicit def double2Constant[T](d: Double)(implicit num: NumericOps[T]): Leaf[T] = + const(num.fromDouble(d)) + + implicit def float2Constant[T](f: Float)(implicit num: NumericOps[T]): Leaf[T] = + const(num.fromDouble(f.toDouble)) + + implicit def int2Constant[T](i: Int)(implicit num: NumericOps[T]): Leaf[T] = + const(num.fromDouble(i.toDouble)) + + implicit def long2Constant[T](l: Long)(implicit num: NumericOps[T]): Leaf[T] = + const(num.fromDouble(l.toDouble)) + } +}
\ No newline at end of file diff --git a/test/files/run/t1500.check b/test/files/run/t1500.check index 1032649f20..94a169333b 100644 --- a/test/files/run/t1500.check +++ b/test/files/run/t1500.check @@ -1,3 +1,3 @@ defined class posingAs -resolve: [A,B](x: A @posingAs[B])B +resolve: [A, B](x: A @posingAs[B])B x: Any = 7 |