summaryrefslogtreecommitdiff
path: root/src/reflect
Commit message (Collapse)AuthorAgeFilesLines
* Fix typo in Quasiquote doc that was confusingJean-Rémi Desjardins2015-04-101-1/+1
|
* Merge pull request #4373 from retronym/topic/indylambda-permutations-2Lukas Rytz2015-04-101-0/+1
|\ | | | | SI-8359 Adjust parameter order of accessor method in Delambdafy
| * SI-8359 Adjust parameter order of accessor method in DelambdafyJason Zaugg2015-03-241-0/+1
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Under `-Ydelambdafy:method`, a public, static accessor method is created to expose the private method containing the body of the lambda. Currently this accessor method has its parameters in the same order structure as those of the lambda body method. What is this order? There are three categories of parameters: 1. lambda parameters 2. captured parameters (added by lambdalift) 3. self parameters (added to lambda bodies that end up in trait impl classes by mixin, and added unconditionally to the static accessor method.) These are currently emitted in order #3, #1, #2. Here are examples of the current behaviour: BEFORE (trait): ``` % cat sandbox/test.scala && scalac-hash v2.11.5 -Ydelambdafy:method sandbox/test.scala && javap -private -classpath . 'Test$class' trait Member; class Capture; trait LambdaParam trait Test { def member: Member def foo { val local = new Capture (arg: LambdaParam) => "" + arg + member + local } } Compiled from "test.scala" public abstract class Test$class { public static void foo(Test); private static final java.lang.String $anonfun$1(Test, LambdaParam, Capture); public static void $init$(Test); public static final java.lang.String accessor$1(Test, LambdaParam, Capture); } ``` BEFORE (class): ``` % cat sandbox/test.scala && scalac-hash v2.11.5 -Ydelambdafy:method sandbox/test.scala && javap -private -classpath . Test trait Member; class Capture; trait LambdaParam abstract class Test { def member: Member def foo { val local = new Capture (arg: LambdaParam) => "" + arg + member + local } } Compiled from "test.scala" public abstract class Test { public abstract Member member(); public void foo(); private final java.lang.String $anonfun$1(LambdaParam, Capture); public Test(); public static final java.lang.String accessor$1(Test, LambdaParam, Capture); } ``` Contrasting the class case with Java: ``` % cat sandbox/Test.java && javac -d . sandbox/Test.java && javap -private -classpath . Test public abstract class Test { public static class Member {}; public static class Capture {}; public static class LambaParam {}; public static interface I { public abstract Object c(LambaParam arg); } public abstract Member member(); public void test() { Capture local = new Capture(); I i1 = (LambaParam arg) -> "" + member() + local; } } Compiled from "Test.java" public abstract class Test { public Test(); public abstract Test$Member member(); public void test(); private java.lang.Object lambda$test$0(Test$Capture, Test$LambaParam); } ``` We can see that in Java 8 lambda parameters come after captures. If we want to use Java's LambdaMetafactory to spin up our anoymous FunctionN subclasses on the fly, our ordering must change. I can see three options for change: 1. Adjust `LambdaLift` to always prepend captured parameters, rather than appending them. I think we could leave `Mixin` as it is, it already prepends the self parameter. This would result a parameter ordering, in terms of the list above: #3, #2, #1. 2. More conservatively, do this just for methods known to hold lambda bodies. This might avoid needlessly breaking code that has come to depend on our binary encoding. 3. Adjust the parameters of the accessor method only. The body of this method can permute params before calling the lambda body method. This commit implements option #2. In also prototyped #1, and found it worked so long as I limited it to non-constructors, to sidestep the need to make corresponding changes elsewhere in the compiler to avoid the crasher shown in the enclosed test case, which was minimized from a bootstrap failure from an earlier a version of this patch. We would need to defer option #1 to 2.12 in any case, as some of these lifted methods are publicied by the optimizer, and we must leave the signatures alone to comply with MiMa. I've included a test that shows this in all in action. However, that is currently disabled, as we don't have a partest category for tests that require Java 8.
* | Merge pull request #4411 from xeno-by/ticket/9252Lukas Rytz2015-04-091-5/+1
|\ \ | | | | | | SI-9252 gets rid of custom logic for jArrayClass in runtime reflection
| * | SI-9252 gets rid of custom logic for jArrayClass in runtime reflectionEugene Burmako2015-03-271-5/+1
| | | | | | | | | | | | | | | Apparently, I've already fixed a very similar issue two years ago. That was a fun surprise! (https://issues.scala-lang.org/browse/SI-5680)
* | | Merge pull request #4318 from soc/topic/remove-deprecation-warningsLukas Rytz2015-03-2813-44/+42
|\ \ \ | |/ / |/| | Remove deprecation warnings
| * | Removed warningsEECOLOR2015-03-266-7/+6
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | - Added `since` to deprecation statement - Added unit to parameter list - Removed usage of deprecated method polyType - Replaced deprecated `debugwarn` with `devWarning` - Changed switch statement to if else in order to remove a warning - Switched implementation of `init` and `processOptions` to prevent warning - Replaced deprecated `Console.readLine` with `scala.io.StdIn.readLine` - Replaced deprecated `startOrPoint` with `start` - Replaced deprecated `tpe_=` with `setType` - Replaced deprecated `typeCheck` with `typecheck` - Replaced deprecated `CompilationUnit.warning` with `typer.context.warning` - Replaced deprecated `scala.tools.nsc.util.ScalaClassLoader` with `scala.reflect.internal.util.ScalaClassLoader` - Replaced deprecated `scala.tools.ListOfNil` with `scala.reflect.internal.util.ListOfNil` - Replaced deprecated `scala.tools.utils.ScalaClassLoader` with `scala.reflect.internal.util.ScalaClassLoader` - Replaced deprecated `emptyValDef` with `noSelfType` - In `BoxesRunTime` removed unused method and commented out unused values. Did not delete to keep a reference to the values. If they are deleted people might wonder why `1` and `2` are not used. - Replaced deprecated `scala.tools.nsc.util.AbstractFileClassLoader` with `scala.reflect.internal.util.AbstractFileClassLoader`
| * | new{Term,Type}Name→{Term,Type}Name, tpename/nme→{type,term}NamesSimon Ochsenreither2015-03-267-21/+22
| | |
| * | Deprecations: Use of isPackage, hasSymbol, getter, setter...Simon Ochsenreither2015-03-263-17/+15
| | | | | | | | | | | | ... replaced by hasPackageFlag, hasSymbolIn, getterIn, setterIn.
* | | Merge pull request #4361 from retronym/ticket/9182Lukas Rytz2015-03-261-1/+2
|\ \ \ | |/ / |/| | SI-9182 Fix runtime reflection with package object, overloads
| * | SI-9182 Fix runtime reflection with package object, overloadsJason Zaugg2015-02-251-1/+2
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Eponymous modules and methods should be allowed to live in the same package scope. This can happen when using a module and and implicit class, or when defining the overloads manually. This commit tones back an assertion that was added for sanity checking runtime reflection thread safety to only fire when we are sure that neither the existing and current symbol of the given name are methods.
* | | Merge pull request #4378 from som-snytt/issue/9102Jason Zaugg2015-03-241-3/+6
|\ \ \ | | | | | | | | SI-9102: Reflect method invoke with mixed args
| * | | SI-9102: Improve testSom Snytt2015-03-111-4/+4
| | | | | | | | | | | | | | | | | | | | | | | | | | | | Cover the second use case reported on the ML (ctors). Improve formatting per the review. And it really does look a lot better.
| * | | SI-9102: Reflect method invoke with mixed argsSom Snytt2015-03-111-3/+6
| |/ / | | | | | | | | | | | | | | | A missing default branch when a method had value class or by-name params caused other args to present as null under reflective invocation.
* / / Reuse the same compiler instance for all tests in a JUnit classLukas Rytz2015-03-111-0/+8
|/ / | | | | | | | | | | | | | | | | | | Note that JUnit creates a new instance of the test class for running each test method. So the compiler instance is added to the companion. However, the JVM would quickly run out of memory when running multiple tests, as the compilers cannot be GCd. So we make it a `var`, and set it to null when a class is done. For that we use JUnit's `@AfterClass` which is required to be on a static method. Therefore we add a Java class with such a static method that we can extend from Scala.
* | Merge pull request #4340 from retronym/topic/infix-completionAdriaan Moors2015-02-192-0/+4
|\ \ | | | | | | SI-9153 More complete and stable results for completions
| * | SI-9153 More complete and stable results for completionsJason Zaugg2015-02-171-0/+3
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Three items of background are needed to understand this bug. 1. When typechecking an application like `qual.m({stats; expr})`, the argument is typechecked using the formal parameter type of `m` as the expected type. If this fails with a type error located within in `expr`, the typer instead re-typechecks under `ContextMode.ReTyping` without an expected type, and then searches for an implicit adaptation to enable `view(qual).m(args)`. Under this mode, `Typer#typed1` clears the type of incoming trees. 2. The presentation compiler performs targetted operations like type completions by: - typechecking the enclosing tree, registering all typechecker `Context`s created in the process (`registerContext`) - finding the smallest enclosing `Context` around the target position (`doLocateContext`) - Using this context to perform implicit search, which can contribute members to the completion. (`applicableViews` within `interactive.Global#typeMembers`) 3. When verifiying whether or not a candidate implicit is applicable as a view from `F => T`, implicit search typechecks a dummy call of the form `q"candiate(${Ident("<argument>").setType(typeOf[F])})". Now, picture yourself at the nexus of these three storms. In the enclosed test case, we search for completions at: x + 1.<caret> 1. Because the code is incomplete, the application of `Int#+` doesn't typecheck, and the typer also tries to adapt `x` to a method applicable to the re-typechecked argument. 2. This process registers a context with `retypechecking` set to true. (If multiple contexts at the same position are registered, the last one wins.) 3. Implicit search uses this context to typecheck `Predef.Ensuring(<argument>.setType(Int))`, but the argument is promptly stripped of its type and retypechecking fails as there is no definition named `<argument>` in scope. As such, we missed out on extension methods, like `ensuring` in the list of completions. This commit changes the presentation compiler to turn off retyping mode in the context before starting to work with it. (Are the other modes that might cause similar bugs?) Once I made that change, I noticed that the results the enclosed test was not stable. I tracked this down to the use of a `HashMap` to carry the applicable implicit views, together with the way that the presentation compiler removes duplicates. This commit switched to a `LinkedHashMap`.
| * | Cache name for dummy argument used in implicit searchJason Zaugg2015-02-171-0/+1
| | | | | | | | | | | | | | | | | | This avoids a minor inefficiency of interning the name on each implicit candidate. Instead, we follow the usual practice and use a pre-baked name from `StdNames`.
* | | SI-9157 Avoid exponential blowup with chained type projectionsJason Zaugg2015-02-181-5/+5
|/ / | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Calling `findMember` in the enclosed test was calling into `NonClassTypeRef#relativeInfo` an exponentially-increasing number of times, with respect to the length of the chained type projections. The numbers of calls increased as: 26, 326, 3336, 33446, 334556. Can any pattern spotters in the crowd that can identify the sequence? (I can't.) Tracing the calls saw we were computing the same `memberType` repeatedly. This part of the method was not guarded by the cache. I have changed the method to use the standard idiom of using the current period for cache invalidation. The enclosed test now compiles promptly, rather than in geological time.
* | Merge pull request #4296 from lrytz/t9105Adriaan Moors2015-02-132-1/+23
|\ \ | | | | | | Fixes and tests for InnerClass / EnclsoingMethod classfile attributes
| * | Fix InnerClass / EnclosingMethod for closures nested in value classesLukas Rytz2015-02-071-1/+6
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Members of value classes are moved over to the companion object early. This change ensures that closure classes nested in value classes appear that way to Java reflection. This commit also changes the EnclosingMethod attribute for classes (and anonymous functions) nested in anonymous function bodies. Before, the enclosing method was in some cases the function's apply method. Not always though: () => { class C ... val a = { class D ...} } The class C used to be nested in the function's apply method, but not D, because the value definition for a was lifted out of the apply. After this commit, we uniformly set the enclosing method of classes nested in function bodies to `null`. This is consistent with the source-level view of the code. Note that under delambdafy:method, closures never appear as enclosing classes (this didn't change in this commit).
| * | SI-9105 Fix EnclosingMethod for classes defined in lambdasLukas Rytz2015-02-071-0/+17
| |/ | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | This change fixes both GenASM and GenBCode, except for the change to renaming in LamdaLift mentioned below. The reason for an inconsistent EnclosingMethod attribute was the symbol owner chain. Initially, closure class symbols don't exist, they are only created in UnCurry (delambdafy:inline). So walking the originalOwner of a definition does not yield closure classes. The commit also fixes uses of isAnonymousClass, isAnonymousFunction and isDelambdafyFunction in two ways: 1. by phase-travelling to an early phase. after flatten, the name includes the name of outer classes, so the properties may become accidentally true (they check for a substring in the name) 2. by ensuring that the (destructive) renames during LambdaLift don't make the above properties accidentally true. This was in fact the cause for SI-8900.
* / SI-8818 FreshName extractor forgives suffixSom Snytt2015-02-091-10/+14
|/ | | | | | The test is corrected (inverted) and the extractor is made more succinct. Succinctness isn't enforced by the test, but I checked it manually.
* SI-9135 Fix NPE, a regression in the pattern matcherJason Zaugg2015-02-051-1/+1
| | | | | | | | The community build discovered that #4252 introduced the possibility for a NullPointerException. The tree with a null type was a synthetic `Apply(<<matchEnd>>)` created by the pattern matcher. This commit adds a null check.
* Merge pull request #4252 from retronym/ticket/9050Lukas Rytz2015-02-031-1/+19
|\ | | | | SI-9050 Fix crasher with value classes, recursion
| * SI-9050 Fix crasher with value classes, recursionJason Zaugg2015-01-161-1/+19
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | From the "Substitution is hard to do" department. In 7babdab9a, TreeSymSubstitutor was modified to mutate the info of symbols defined in the tree, if that symbol's info referred to one of the `from` symbols in the substitution. It would have been more principled to create a cloned symbol with the updated info, and add that to the substitution. But I wasn't able implement that correctly (let alone efficiently.) The in-place mutation of the info of a symbol led to the crasher in this bug: a singleton type over that symbol ends up with a stale cached value of 'underlying'. In the enclosed test case, this leads to a type error in the `SubstituteRecursion` of the extension methods phase. This commit performs a cleanup job at the end of `substituteSymbols` by invalidating the cache of any `SingleType`-s in the tree that refer to one of the mutated symbols.
* | SI-9133 Harden against infinite loop in NoSymbol.ownerJason Zaugg2015-02-031-1/+5
|/ | | | | | | | | | | | | | | The available evidence gathered in an IDE hang suggests that while editing erronenous code, a call to `Erasure#javaSig` by the IDE's structure builder triggered the `ExplicitOuter` info transformer on a symbol with some sort of incoherent owner chain, which led to an infinite loop in `NoSymbol#outerClass`. This commit hardens that method to work in the same manner as a call to `NoSymbol.owner`: log the error under -Xdev or -Ydebug and return return `NoSymbol` to soldier on without crashing / hanging. I haven't formulated a theory about how we might have ended up with the corrupt owner chain.
* Merge pull request #4201 from mpociecha/fix-typos-in-docs-and-commentsGrzegorz Kossakowski2015-01-1424-45/+45
|\ | | | | Fix many typos in docs and comments
| * Fix many typos in docs and commentsmpociecha2014-12-1424-45/+45
| | | | | | | | | | | | | | | | | | | | | | | | | | This commit corrects many typos found in scaladocs, comments and documentation. It should reduce a bit number of PRs which fix one typo. There are no changes in the 'real' code except one corrected name of a JUnit test method and some error messages in exceptions. In the case of typos in other method or field names etc., I just skipped them. Obviously this commit doesn't fix all existing typos. I just generated in IntelliJ the list of potential typos and looked through it quickly.
* | SI-9057 - fix `showCode` to put backticks around names including dotsJan Bessai2015-01-071-1/+2
| | | | | | | | | | | | | | Missing backticks cause the parser to treat names as paths, which is obviously invalid. A unit test is included.
* | Merge pull request #4139 from retronym/ticket/7965Adriaan Moors2014-12-233-0/+7
|\ \ | | | | | | SI-7965 Support calls to MethodHandle.{invoke,invokeExact}
| * | SI-7965 Support calls to MethodHandle.{invoke,invokeExact}Jason Zaugg2014-12-033-0/+7
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | These methods are "signature polymorphic", which means that compiler should not: 1. adapt the arguments to `Object` 2. wrap the repeated parameters in an array 3. adapt the result type to `Object`, but instead treat it as it it already conforms to the expected type. Dispiritingly, my initial attempt to implement this touched the type checker, uncurry, erasure, and the backend. However, I realized we could centralize handling of this in the typer if at each application we substituted the signature polymorphic symbol with a clone that carried its implied signature, which is derived from the types of the arguments (typechecked without an expected type) and position within and enclosing cast or block. The test case requires Java 7+ to compile so is currently embedded in a conditionally compiled block of code in a run test. We ought to create a partest category for modern JVMs so we can write such tests in a more natural style. Here's how this looks in bytecode. Note the `bipush` / `istore` before/after the invocation of `invokeExact`, and the descriptor `(LO$;I)I`. ``` % cat sandbox/poly-sig.scala && qscala Test && echo ':javap Test$#main' | qscala import java.lang.invoke._ object O { def bar(x: Int): Int = -x } object Test { def main(args: Array[String]): Unit = { def lookup(name: String, params: Array[Class[_]], ret: Class[_]) = { val lookup = java.lang.invoke.MethodHandles.lookup val mt = MethodType.methodType(ret, params) lookup.findVirtual(O.getClass, name, mt) } def lookupBar = lookup("bar", Array(classOf[Int]), classOf[Int]) val barResult: Int = lookupBar.invokeExact(O, 42) () } } scala> :javap Test$#main public void main(java.lang.String[]); descriptor: ([Ljava/lang/String;)V flags: ACC_PUBLIC Code: stack=3, locals=3, args_size=2 0: aload_0 1: invokespecial #18 // Method lookupBar$1:()Ljava/lang/invoke/MethodHandle; 4: getstatic #23 // Field O$.MODULE$:LO$; 7: bipush 42 9: invokevirtual #29 // Method java/lang/invoke/MethodHandle.invokeExact:(LO$;I)I 12: istore_2 13: return LocalVariableTable: Start Length Slot Name Signature 0 14 0 this LTest$; 0 14 1 args [Ljava/lang/String; 13 0 2 barResult I LineNumberTable: line 16: 0 } ``` I've run this test across our active JVMs: ``` % for v in 1.6 1.7 1.8; do java_use $v; pt --terse test/files/run/t7965.scala || break; done java version "1.6.0_65" Java(TM) SE Runtime Environment (build 1.6.0_65-b14-466.1-11M4716) Java HotSpot(TM) 64-Bit Server VM (build 20.65-b04-466.1, mixed mode) Selected 1 tests drawn from specified tests . 1/1 passed (elapsed time: 00:00:02) Test Run PASSED java version "1.7.0_71" Java(TM) SE Runtime Environment (build 1.7.0_71-b14) Java HotSpot(TM) 64-Bit Server VM (build 24.71-b01, mixed mode) Selected 1 tests drawn from specified tests . 1/1 passed (elapsed time: 00:00:07) Test Run PASSED java version "1.8.0_25" Java(TM) SE Runtime Environment (build 1.8.0_25-b17) Java HotSpot(TM) 64-Bit Server VM (build 25.25-b02, mixed mode) Selected 1 tests drawn from specified tests . 1/1 passed (elapsed time: 00:00:05) Test Run PASSED ```
* | | fix ByteCodecs scaladocxuwei-k2014-12-141-2/+2
| |/ |/|
* | Merge pull request #4176 from mpociecha/flat-classpath2Grzegorz Kossakowski2014-12-055-26/+21
|\ \ | | | | | | The alternative, flat representation of classpath elements
| * | Cleanup and refactoring - semicolons, unused or commented out codempociecha2014-12-055-20/+14
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | This commit contains some minor changes made by the way when implementing flat classpath. Sample JUnit test that shows that all pieces of JUnit infrastructure work correctly now uses assert method form JUnit as it should do from the beginning. I removed commented out lines which were obvious to me. In the case of less obvious commented out lines I added TODOs as someone should look at such places some day and clean them up. I removed also some unnecessary semicolons and unused imports. Many string concatenations using + have been changed to string interpolation. There's removed unused, private walkIterator method from ZipArchive. It seems that it was unused since this commit: https://github.com/scala/scala/commit/9d4994b96c77d914687433586eb6d1f9e49c520f However, I had to add an exception for the compatibility checker because it was complaining about this change. I made some trivial corrections/optimisations like use 'findClassFile' method instead of 'findClass' in combination with 'binary' to find the class file.
| * | Add flat classpath implementation for zip and jar filesmpociecha2014-11-301-6/+7
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | This commit adds an implementation of flat classpath which can handle both jar and vanilla zip files. In fact there are two versions - for a class- and a sourcepath. Both extend ZipArchiveFileLookup which provides common logic. They use FileZipArchive. @gkossakowski made a comparison of different ways of handling zips and jars (e.g. using javac's ZipFileIndex). He stated that general efficiency of FileZipArchive, taking into account various parameters, is the best. FileZipArchive is slightly changed. From now it allows to find the entry for directory in all directory entries without iterating all entries regardless of a type. Thanks to that we can simply find a directory for a package - like in the case of DirectoryFileLookup. There's also added possibility to cache classpath representation of classpath elements from jar and zip files across compiler instances. The cache is just a map AbstractFile -> FlatClassPath. It should reduce the number of created classpath and file instances e.g. in the case of many ScalaPresentationCompilers in Scala IDE. To prevent the possibility to avoid a cache, caches are created as a part of factories responsible for the creation of these types of the flat classpath.
* | | Merge pull request #4178 from retronym/ticket/9018Jason Zaugg2014-12-031-2/+14
|\ \ \ | | | | | | | | SI-9018 Fix regression: cycle in LUBs
| * | | SI-9018 Fix regression: cycle in LUBsJason Zaugg2014-12-031-2/+14
| |/ / | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Regressed in 4412a92d, which admirably sought to impose some structure on the domain of depths, but failed to preserve an imporatnt part of said structure. When calculating LUBs and GLBs, the recursion depth is limited by propagating a decreasing depth parameter. Its initial value is the recursion limit, and is calcluated from the maximum depth of the types fed into the calculation. Here are a few examples that give a flavour of this calculation: ``` scala> class M[A] defined class M scala> class N extends M[M[M[M[A]]]] <console>:34: error: not found: type A class N extends M[M[M[M[A]]]] ^ scala> class N extends M[M[M[M[Int]]]] defined class N scala> lubDepth(typeOf[N] :: Nil) res5: scala.reflect.internal.Depth = Depth(4) scala> type T = M[Int] with M[M[Int]] defined type alias T scala> lubDepth(typeOf[T] :: Nil) res7: scala.reflect.internal.Depth = Depth(3) ``` One parts of the LUB calculation, `lub0`, truncates the lub to `Any` when the depth dives below zero. Before 4412a92d: ------------------ value decr incr ------------------ -3 -3 -2 (= AnyDepth) -2 -3 -1 -1 -2 0 0 -1 1 1 0 2 ... After 4412a92d: ----------------------- value decr incr ----------------------- -MaxInt -MaxInt -MaxInt (= AnyDepth) 0 -MaxInt 1 1 0 2 ... The crucial difference that triggered the regression is that decrementing a depth of zero now goes to the sentinel value, `AnyDepth`, rather than to `-1`. This commit modifies `Depth` to allow it to represent any negative depth. It also switches the sentinel value for `AnyDepth`. Even though I don't believe it is needed, I have also allowed for `Depth.Zero.decr.decr.decr == Depth.AnyVal`, which was historically the case in 2.10.4. To better understand what was happening, I added tracing to the calculation and diffed the before and after: https://gist.github.com/retronym/ec59608eecc52bb497fa Notice that when `elimSub(ts, depth = 0)` recursively calls `lub`, it does so with the variant that caluculates the allowable depth from the shape of the given types. We can then infinitely recurse. Before 4412a92d: ``` |-- elimSub(depth = 0, ts = List(Comparable[_ >: TestObject.E.Value with String <: Comparable[_ >: TestObject.E.Valu | |-- lub(depth = -1, ts = List(TestObject.E.Value with String, TestObject.C)) | | |-- lub0(depth = -1, ts0 = List(TestObject.E.Value with String, TestObject.C)) | | | |-- elimSub(depth = -1, ts = List(TestObject.E.Value with String, TestObject.C)) | | | |== List(TestObject.E.Value with String, TestObject.C) | | | |-- Truncating LUB to | | | |== Any | | |== Any | |== Any |== List(Comparable[_ >: TestObject.E.Value with String <: Comparable[_ >: TestObject.E.Value with String <: java.io |-- lub(depth = 0, ts = List(java.lang.type, java.lang.type)) | |-- lub0(depth = 0, ts0 = List(java.lang.type, java.lang.type)) | | |-- elimSub(depth = 0, ts = List(java.lang.type, java.lang.type)) | | |== List(java.lang.type) | |== java.lang.type |== java.lang.type |-- elimSub(depth = 0, ts = List(Object, Object)) |== List(Object) |-- elimSub(depth = 0, ts = List(Any, Any)) |== List(Any) ``` After 4412a92d: ``` |-- elimSub(depth = 0, ts = List(Comparable[_ >: TestObject.E.Value with String <: Comparable[_ >: TestObject.E.Valu | |-- lub(depth = _, ts = List(TestObject.E.Value with String, TestObject.C)) | | |-- lub(depth = 3, ts = List(TestObject.E.Value with String, TestObject.C)) | | | |-- lub0(depth = 3, ts0 = List(TestObject.E.Value with String, TestObject.C)) | | | | |-- elimSub(depth = 3, ts = List(TestObject.E.Value with String, TestObject.C)) | | | | |== List(TestObject.E.Value with String, TestObject.C) | | | | |-- lub1(depth = 3, ts = List(TestObject.E.Value with String, TestObject.C)) | | | | | |-- elimSub(depth = 3, ts = List(scala.math.Ordered[TestObject.E.Value], scala.math.Orde | | | | | |== List(scala.math.Ordered[TestObject.E.Value], scala.math.Ordered[TestObject.C]) ```
* | | Merge pull request #4166 from lpiepiora/update-scaladoc-examplesAdriaan Moors2014-12-0110-35/+35
|\ \ \ | |/ / |/| | Update ScalaDoc code examples not to use deprecated constructs
| * | Update ScalaDoc code examples not to use deprecated constructsLukasz Piepiora2014-11-2610-35/+35
| | | | | | | | | | | | | | | - Replace newTermName in favour of TermName - Replace newTypeName in favour of TypeName
* | | SI-8502 Improve resiliance to absent packagesJason Zaugg2014-11-282-6/+22
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | When unpickling a class, we create stub symbols for references to classes absent from the current classpath. If these references only appear in method signatures that aren't called, we can proceed with compilation. This is in line with javac. We're getting better at this, but there are still some gaps. This bug is about the behaviour when a package is completely missing, rather than just a single class within that package. To make this work we have to add two special cases to the unpickler: - When unpickling a `ThisType`, convert a `StubTermSymbol` into a `StubTypeSymbol`. We hit this when unpickling `ThisType(missingPackage)`. - When unpickling a reference to `<owner>.name` where `<owner>` is a stub symbol, don't call info on that owner, but rather allow the enclosing code in `readSymbol` fall through to create a stub for the member. The test case was distilled from an a problem that a Spray user encountered when Akka was missing from the classpath. Two existing test cases have progressed, and the checkfiles are accordingly updated.
* | | Fixes memory leak when using reflectionTim Harper2014-11-221-2/+6
|/ / | | | | | | | | | | References to Threads would be retained long after their termination if reflection is used in them. This led to a steady, long memory leak in applications using reflection in thread pools.
* | Merge pull request #4099 from retronym/ticket/7596Grzegorz Kossakowski2014-11-211-1/+1
|\ \ | | | | | | SI-7596 Curtail overloaded symbols during unpickling
| * | SI-7596 Curtail overloaded symbols during unpicklingJason Zaugg2014-11-061-1/+1
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | In code like: object O { val x = A; def x(a: Any) = ... } object P extends O.x.A The unpickler was using an overloaded symbol for `x` in the parent type of `P`. This led to compilation failures under separate compilation. The code that leads to this is in `Unpicklers`: def fromName(name: Name) = name.toTermName match { case nme.ROOT => loadingMirror.RootClass case nme.ROOTPKG => loadingMirror.RootPackage case _ => adjust(owner.info.decl(name)) } This commit filters the overloaded symbol based its stability unpickling a singleton type. That seemed a slightly safer place than in `fromName`.
* | | Merge pull request #4115 from retronym/ticket/8597Grzegorz Kossakowski2014-11-211-0/+4
|\ \ \ | |_|/ |/| | SI-8597 Improved pattern unchecked warnings
| * | SI-8597 Improved pattern unchecked warningsJason Zaugg2014-11-091-0/+4
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | The spec says that `case _: List[Int]` should be always issue an unchecked warning: > Types which are not of one of the forms described above are > also accepted as type patterns. However, such type patterns > will be translated to their erasure (§3.7). The Scala compiler > will issue an “unchecked” warning for these patterns to flag > the possible loss of type-safety. But the implementation goes a little further to omit warnings based on the static type of the scrutinee. As a trivial example: def foo(s: Seq[Int]) = s match { case _: List[Int] => } need not issue this warning. These discriminating unchecked warnings are domain of `CheckabilityChecker`. Let's deconstruct the reported bug: def nowarn[T] = (null: Any) match { case _: Some[T] => } We used to determine that if the first case matched, the scrutinee type would be `Some[Any]` (`Some` is covariant). If this statically matches `Some[T]` in a pattern context, we don't need to issue an unchecked warning. But, our blanket use of `existentialAbstraction` in `matchesPattern` loosened the pattern type to `Some[Any]`, and the scrutinee type was deemed compatible. I've added a new method, `scrutConformsToPatternType` which replaces pattern type variables by wildcards, but leaves other abstract types intact in the pattern type. We have to use this inside `CheckabilityChecker` only. If we were to make `matchesPattern` stricter in the same way, tests like `pos/t2486.scala` would fail. I have introduced a new symbol test to (try to) identify pattern type variables introduced by `typedBind`. Its not pretty, and it might be cleaner to reserve a new flag for these. I've also included a test variation exercising with nested matches. The pattern type of the inner case can't, syntactically, refer to the pattern type variable of the enclosing case. If it could, we would have to be more selective in our wildcarding in `ptMatchesPatternType` by restricting ourselves to type variables associated with the closest enclosing `CaseDef`. As some further validation of the correctness of this patch, four stray warnings have been teased out of neg/unchecked-abstract.scala I also had to changes `typeArgsInTopLevelType` to extract the type arguments of `Array[T]` if `T` is an abstract type. This avoids the "Checkability checker says 'Uncheckable', but uncheckable type cannot be found" warning and consequent overly lenient analysis. Without this change, the warning was suppressed for: def warnArray[T] = (null: Any) match { case _: Array[T] => }
* | | Merge pull request #4123 from retronym/ticket/8253Jason Zaugg2014-11-201-0/+2
|\ \ \ | | | | | | | | SI-8253 Fix incorrect parsing of <elem xmlns={f("a")}/>
| * | | SI-8253 Fix incorrect parsing of <elem xmlns={f("a")}/>Jason Zaugg2014-11-101-0/+2
| |/ / | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | The spliced application was placed in the `attrMap` in `SymbolicXMLBuilder` and later incorrectly matched by a pattern intended only to match: xml.Text(s) That attribute value is generated by parsing: <elem xmlns='a'/> So the net effect was that the two fragments of XML were identical! This commit sharpens up the match to really look for a syntactic `_root_.scala.xml.Text("...")`. The test just prints the parse trees of a variety of cases, as we we should not test the modularized XML library in scala/scala.
* | | Merge pull request #4051 from heathermiller/repl-cp-fix2Jason Zaugg2014-11-181-7/+9
|\ \ \ | | | | | | | | SI-6502 Reenables loading jars into the running REPL (regression in 2.10)
| * | | SI-6502 Refactorings suggested by reviewHeather Miller2014-11-101-7/+9
| | |/ | |/| | | | | | | | | | - Moves mergeUrlsIntoClassPath from Global into ClassPath - Revises and documents AbstractFile.getURL