| Commit message (Collapse) | Author | Age | Files | Lines |
... | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | | |
scalap didn't support really big class files. It was returning an
empty String for such files. The reason was that there were only
ScalaSignatures taken into account.
This commit adds support for ScalaLongSignature. We try to get such
an attribute when we didn't find ScalaSignature. Also there's added
an additional case to the logic retrieving bytes for a signature.
Since ScalaLongSignature can contain many parts, we have to merge
their byte arrays.
Changes are tested by a new partest-based test. These two files are
really big, but it was required (t8679.scala is a reduced version of
BigScalaClass - an example attached to JIRA).
There are also added TODOs with a JIRA ticket: We have three places,
where we process Scala signatures. In the future it would be better to
reuse some common logic, if it's possible.
|
|\ \ \
| |/ /
|/| | |
Use LambdaMetafactory where possible for lambda creation.
|
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | | |
Suitable lambdas are identified in Delambdafy and marked with
such with a tree annotation that includes the
data needed by the backend to emit an invokedynamic instruction.
GenBCode to rewrite instantiation of such anonymous
function classes with an invokedynamic instruction. At this
stage, I don't plan to merge the support for this into GenASM.
Between these points, the lambda capture is represented as an
application of a dummy factory symbol:
```
<dummy>(captures...) : FunctionN
```
Demo:
```
% wget http://central.maven.org/maven2/org/scala-lang/modules/scala-java8-compat_2.11/0.3.0/scala-java8-compat_2.11-0.3.0.jar
% qscala -classpath scala-java8-compat_2.11-0.3.0.jar -Ydelambdafy:method -target:jvm-1.8 -Ybackend:GenBCode
Welcome to Scala version 2.11.6-20150309-144147-c91c978c81 (Java HotSpot(TM) 64-Bit Server VM, Java 1.8.0_25).
Type in expressions to have them evaluated.
Type :help for more information.
scala> (() => "").getClass
res0: Class[_ <: () => String] = class $$Lambda$1/871790326
```
I have also corrected an error in a previous commit. The newly added
symbol test, `isDelambdafyTarget`, needs to check for the `ARTIFACT`
flag, as that is what is added to the method by `Uncurry`.
|
| | |
| | |
| | |
| | |
| | | |
This commit corrects many typos found in scaladocs and comments.
There's also fixed the name of a private method in ICodeCheckers.
|
|/ / |
|
|\ \
| | |
| | | |
SI-8359 Adjust parameter order of accessor method in Delambdafy
|
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | | |
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.
|
|\ \ \
| | | |
| | | | |
SI-9252 gets rid of custom logic for jArrayClass in runtime reflection
|
| | | |
| | | |
| | | |
| | | |
| | | | |
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)
|
|\ \ \ \
| |/ / /
|/| | | |
Remove deprecation warnings
|
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | | |
- 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`
|
| | | | |
|
| | | |
| | | |
| | | |
| | | | |
... replaced by hasPackageFlag, hasSymbolIn, getterIn, setterIn.
|
|\ \ \ \
| |/ / /
|/| | | |
SI-9182 Fix runtime reflection with package object, overloads
|
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | | |
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.
|
|\ \ \ \
| | | | |
| | | | | |
SI-9102: Reflect method invoke with mixed args
|
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | | |
Cover the second use case reported on the ML (ctors).
Improve formatting per the review. And it really does look
a lot better.
|
| |/ / /
| | | |
| | | |
| | | |
| | | |
| | | | |
A missing default branch when a method had value class
or by-name params caused other args to present as null
under reflective invocation.
|
|/ / /
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | | |
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.
|
|\ \ \
| | | |
| | | | |
SI-9153 More complete and stable results for completions
|
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | | |
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`.
|
| | | |
| | | |
| | | |
| | | |
| | | |
| | | | |
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`.
|
|/ / /
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | | |
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.
|
|\ \ \
| | | |
| | | | |
Fixes and tests for InnerClass / EnclsoingMethod classfile attributes
|
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | | |
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).
|
| |/ /
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | | |
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.
|
|/ /
| |
| |
| |
| |
| | |
The test is corrected (inverted) and the extractor is made
more succinct. Succinctness isn't enforced by the test,
but I checked it manually.
|
| |
| |
| |
| |
| |
| |
| |
| | |
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.
|
|\ \
| | |
| | | |
SI-9050 Fix crasher with value classes, recursion
|
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | | |
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.
|
|/ /
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| | |
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.
|
|\ \
| | |
| | | |
Fix many typos in docs and comments
|
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | | |
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.
|
| | |
| | |
| | |
| | |
| | |
| | |
| | | |
Missing backticks cause the parser to treat names as paths, which is
obviously invalid.
A unit test is included.
|
|\ \ \
| | | |
| | | | |
SI-7965 Support calls to MethodHandle.{invoke,invokeExact}
|
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | | |
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
```
|
| |/ /
|/| | |
|
|\ \ \
| | | |
| | | | |
The alternative, flat representation of classpath elements
|
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | | |
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.
|
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | | |
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.
|
|\ \ \ \
| | | | |
| | | | | |
SI-9018 Fix regression: cycle in LUBs
|
| |/ / /
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | | |
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])
```
|
|\ \ \ \
| |/ / /
|/| | | |
Update ScalaDoc code examples not to use deprecated constructs
|
| | | |
| | | |
| | | |
| | | |
| | | | |
- Replace newTermName in favour of TermName
- Replace newTypeName in favour of TypeName
|
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | | |
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.
|
|/ / /
| | |
| | |
| | |
| | |
| | | |
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.
|
|\ \ \
| | | |
| | | | |
SI-7596 Curtail overloaded symbols during unpickling
|
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | | |
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`.
|
|\ \ \ \
| |_|/ /
|/| | | |
SI-8597 Improved pattern unchecked warnings
|
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | | |
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] => }
|