summaryrefslogtreecommitdiff
path: root/test/files/run/t8549.scala
Commit message (Collapse)AuthorAgeFilesLines
* SD-194 Tweak module initialization to comply with JVM specJason Zaugg2016-08-181-10/+10
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Top level modules in Scala currently desugar as: ``` class C; object O extends C { toString } ``` ``` public final class O$ extends C { public static final O$ MODULE$; public static {}; Code: 0: new #2 // class O$ 3: invokespecial #12 // Method "<init>":()V 6: return private O$(); Code: 0: aload_0 1: invokespecial #13 // Method C."<init>":()V 4: aload_0 5: putstatic #15 // Field MODULE$:LO$; 8: aload_0 9: invokevirtual #21 // Method java/lang/Object.toString:()Ljava/lang/String; 12: pop 13: return } ``` The static initalizer `<clinit>` calls the constructor `<init>`, which invokes superclass constructor, assigns `MODULE$= this`, and then runs the remainder of the object's constructor (`toString` in the example above.) It turns out that this relies on a bug in the JVM's verifier: assignment to a static final must occur lexically within the <clinit>, not from within `<init>` (even if the latter is happens to be called by the former). I'd like to move the assignment to <clinit> but that would change behaviour of "benign" cyclic references between modules. Example: ``` package p1; class CC { def foo = O.bar}; object O {new CC().foo; def bar = println(1)}; // Exiting paste mode, now interpreting. scala> p1.O 1 ``` This relies on the way that we assign MODULE$ field after the super class constructors are finished, but before the rest of the module constructor is called. Instead, this commit removes the ACC_FINAL bit from the field. It actually wasn't behaving as final at all, precisely the issue that the stricter verifier now alerts us to. ``` scala> :paste -raw // Entering paste mode (ctrl-D to finish) package p1; object O // Exiting paste mode, now interpreting. scala> val O1 = p1.O O1: p1.O.type = p1.O$@ee7d9f1 scala> scala.reflect.ensureAccessible(p1.O.getClass.getDeclaredConstructor()).newInstance() res0: p1.O.type = p1.O$@64cee07 scala> O1 eq p1.O res1: Boolean = false ``` We will still achieve safe publication of the assignment to other threads by virtue of the fact that `<clinit>` is executed within the scope of an initlization lock, as specified by: https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-5.html#jvms-5.5 Fixes scala/scala-dev#SD-194
* Fields phaseAdriaan Moors2016-08-111-3/+3
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | One step towards teasing apart the mixin phase, making each phase that adds members to traits responsible for mixing in those members into subclasses of said traits. Another design tenet is to not emit symbols or trees only to later remove them. Therefore, we model a val in a trait as its accessor. The underlying field is an implementation detail. It must be mixed into subclasses, but has no business in a trait (an interface). Also trying to reduce tree creation by changing less in subtrees during tree transforms. A lot of nice fixes fall out from this rework: - Correct bridges and more precise generic signatures for mixed in accessors, since they are now created before erasure. - Correct enclosing method attribute for classes nested in trait fields. Trait fields are now created as MethodSymbol (no longer TermSymbol). This symbol shows up in the `originalOwner` chain of a class declared within the field initializer. This promoted the field getter to being the enclosing method of the nested class, which it is not (the EnclosingMethod attribute is a source-level property). - Signature inference is now more similar between vals and defs - No more field for constant-typed vals, or mixed in accessors for subclasses. A constant val can be fully implemented in a trait. TODO: - give same treatment to trait lazy vals (only accessors, no fields) - remove support for presuper vals in traits (they don't have the right init semantics in traits anyway) - lambdalift should emit accessors for captured vals in traits, not a field Assorted notes from the full git history before squashing below. Unit-typed vals: don't suppress field it affects the memory model -- even a write of unit to a field is relevant... unit-typed lazy vals should never receive a field this need was unmasked by test/files/run/t7843-jsr223-service.scala, which no longer printed the output expected from the `0 to 10 foreach` Use getter.referenced to track traitsetter reify's toolbox compiler changes the name of the trait that owns the accessor between fields and constructors (`$` suffix), so that the trait setter cannot be found when doing mkAssign in constructors this could be solved by creating the mkAssign tree immediately during fields anyway, first experiment: use `referenced` now that fields runs closer to the constructors phase (I tried this before and something broke) Infer result type for `val`s, like we do for `def`s The lack of result type inference caused pos/t6780 to fail in the new field encoding for traits, as there is no separate accessor, and method synthesis computes the type signature based on the ValDef tree. This caused a cyclic error in implicit search, because now the implicit val's result type was not inferred from the super member, and inferring it from the RHS would cause implicit search to consider the member in question, so that a cycle is detected and type checking fails... Regardless of the new encoding, we should consistently infer result types for `def`s and `val`s. Removed test/files/run/t4287inferredMethodTypes.scala and test/files/presentation/t4287c, since they were relying on inferring argument types from "overridden" constructors in a test for range positions of default arguments. Constructors don't override, so that was a mis-feature of -Yinfer-argument-types. Had to slightly refactor test/files/presentation/doc, as it was relying on scalac inferring a big intersection type to approximate the anonymous class that's instantiated for `override lazy val analyzer`. Now that we infer `Global` as the expected type based on the overridden val, we make `getComment` private in navigating between good old Skylla and Charybdis. I'm not sure why we need this restriction for anonymous classes though; only structural calls are restricted in the way that we're trying to avoid. The old behavior is maintained nder -Xsource:2.11. Tests: - test/files/{pos,neg}/val_infer.scala - test/files/neg/val_sig_infer_match.scala - test/files/neg/val_sig_infer_struct.scala need NMT when inferring sig for accessor Q: why are we calling valDefSig and not methodSig? A: traits use defs for vals, but still use valDefSig... keep accessor and field info in synch
* Deprecated and rename Some#x to Some#valueDale Wijnand2016-07-151-4/+4
|
* SI-8561 named subclasses for known Manifest / ClassTag instancesLukas Rytz2016-07-061-22/+15
| | | | | | This helps keeping ClassTag serialization stable under accidental changes (like changing the order of definitions, which would change the name of the anonymous classes).
* Add SerialVersionUID to ListSetRui Gonçalves2016-05-171-1/+3
|
* Target FunctionN, not scala/runtime/java8/JFunction.Adriaan Moors2016-03-281-2/+2
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | We compile FunctionN to Java 8's idea of a function now, so no need to target the artisanal JFunction and friends, except when the function is specialized, as I don't yet see how we can use LMF with the way specialization handles FunctionN: First, the working status quo -- the hand-crafted specialized versions of JFunction0. Notice how `apply$mcB$sp` is looking pretty SAMmy: ``` @FunctionalInterface public interface JFunction0$mcB$sp extends JFunction0 { @Override public byte apply$mcB$sp(); @Override default public Object apply() { return BoxesRunTime.boxToByte(this.apply$mcB$sp()); } } ``` Contrast this with our specialized standard FunctionN: ``` public interface Function0<R> { public R apply(); default public byte apply$mcB$sp() { return BoxesRunTime.unboxToByte(this.apply()); } } public interface Function0$mcB$sp extends Function0<Object> { } ``` The single abstract method in `Function0$mcB$sp` is `apply`, and the method that would let us avoid boxing, if it were abstract, is `apply$mcB$sp`... TODO (after M4): - do same for specialized functions (issues with boxing?) - remove scala/runtime/java8/JFunction* (need new STARR?)
* Remove manual mixins in JFunctionN.v2.12.0-M3-dc9effeJason Zaugg2016-03-181-14/+21
| | | | | | | | | | | | | | | | | | | These manual mixins were forwarding to the impl classes have just been removed. We can now rely on default methods instead. Update Tests: - Fix test/files/pos/t1237.scala, we can't have an outer field in an interface, always use the outer method. - Don't crash on meaningless trait early init fields test/files/neg/t2796.scala - Remove impl class relate parts of inner class test - Remove impl class relate parts of elidable test - Remove impl class related reflection test. - Remove test solely about trait impl classes renaming - Update check file with additional stub symbol error - Disable unstable parts of serialization test. - TODO explain, and reset the expectation
* Make AnyRefMap serializableJason Zaugg2015-09-251-2/+3
|
* SI-6938 Use mutable red-black tree in TreeSetRui Gonçalves2015-07-281-1/+4
| | | | | | | | The previous implementation of `mutable.TreeSet` uses a mutable reference to an immutable red-black tree as its underlying data structure. That leads to unnecessary objects being created, which can be a problem in systems with limited resources. It also has reduced performance when compared with common mutable implementations. In this commit `mutable.TreeSet` is changed so that it uses the recently created `mutable.RedBlackTree` as its underlying data structure. Specialized red-black tree methods were created for working with keys for efficiency reasons. The new implementation is source-compatible with the previous one, although its serialized representation obviously changes. Closes [SI-6938](https://issues.scala-lang.org/browse/SI-6938).
* SI-8911 scala.collection.convert.Wrappers$MapWrapper not serializableRex Kerr2015-07-191-1/+14
| | | | | | | | Added `with Serializable` to `MapWrapper` and `SetWrapper`. Test verifies that serialization works in the simplest case. Also updated tests in t8549 to check that serialization works and doesn't change.
* SI-4147 Add an implementation of `mutable.TreeMap`Rui Gonçalves2015-05-301-1/+4
| | | | | | | | | | This commit contains an implementation of a mutable red-black tree with focus on performance. It also contains a new `mutable.TreeMap` Scala collection that is backed by the aforementioned tree. The common generic factories and traits related to mutable sorted maps didn't exist yet, so this commit also adds them. Regarding performance, `TreeMap` overrides (from `MapLike` and `SortedMapLike`) all of the most common methods for maps and also those whose default implementations are asymptotically worse than direct red-black tree algorithms (e.g. `last`, `clear`). The `rangeImpl` method of `TreeMap` returns an instance of `TreeMapView`, an inner class of `TreeMap`. This view is backed by the same `RedBlackTree.Tree` instance, and therefore changes to the original map are reflected in the view and vice-versa. The semantics of mutating a view by adding and removing keys outside the view's range are the same of the current `mutable.TreeSet`. A bit less focus was given on the performance of views - in particular, getting the `size` of a `TreeMapView` is O(n) on the number of elements inside the view bounds. That can be improved in the future. In a future commit, `mutable.TreeSet` can be changed to be backed by this red-black tree implementation.
* Fix t8549 under -Ydelambdafy:methodLukas Rytz2014-10-101-1/+4
| | | | | | | | | | | | | | | | | | the structure of Option.class generated by delambdafy:method is slightly different. For example, lambdas declared within Option are not emitted as nested classes, so under delambdafy:method there's no inner class entry for anonfun classes. The test failed because serializing a ClassTag involves serializing an Option. Option did not have a `@SerialVersionUID`, and the classfile generated by delambdafy:method has a different value. The annotation is required on the parent class (Option) as well as the subclasses (Some / None). De-serializing a Some will fail if Option has a different SerialVersionUID. Relates to SI-8576. We should probably have more SVUID annotations in the library.
* SI-8576 Temporarily disable part of serialization testJason Zaugg2014-05-101-23/+34
| | | | | | | | | | | | | | | | | Parts of this test fail if testing a library built with -Xcheckinit. The failures seem to be in two categories: - A component of the serialized structure does not have a declared SerialVersionUID, meaning that the extra field added to track initialization results in a different ID. This manifests as a `java.io.InvalidClassException` when deserializing the blobs of data saved in the test case. - Spurious `UnitializedFieldErrors` when calling methods on the object that has been serialized and then deserialized. Until we figure out the right course of action (more @SerialVersionUID annotations / weaker tests / ...), this commit disabled those tests.
* SI-8549 Enforce serialization stability for selected collectionsJason Zaugg2014-05-051-0/+175
To date, we've been hesidant to offer any guarantees about Java serialization of standard library types among heteregenous Scala versions. Nonetheless, we have added `SerialVersionUID` annotations to parts of the standard library, to offer some stability. This protects against two winds of change: automatic calculation of this UID might differ between JVM versions, or it might differ due to otherwise immaterial changes to the library in Scala releases. With this commit, we strengthen the guarantees. Classes marked with `SerialVersionUID` will be serialization compatible within minor releases of Scala. This is backed up by the enclosed test. After major releases, we reserve the right to break this. But the test will serve to avoid *accidental* changes. Specifically, the test case checks: - deserialize(serialize(x)) == x - serialize(x) is stable over time I have included values of all types marked with `@SerialVersionUID` in the library. For some types, I've added variations in the values to exercise different subclasses, such as `Set1` / `Set2`. This found that that the serialized form of predefined `ClassTags` included the cached identity hash code and failed the stability test. This wasn't an issue for correctness as they also provide `readResolve`, but I marked those fields as `@transient` in any case to comply with the test expectations. That whole area is good example of a serialization worst-practice: using anonymous classes in code like: val Object: Manifest[java.lang.Object] = new PhantomManifest[...](...) { private def readResolve(): Any = Manifest.AnyVal } ... will lead to instability if these declarations are shifted around in the file. Named classes would be preferred. I've noted this in a TODO comment for 2.12.