summaryrefslogtreecommitdiff
path: root/test
Commit message (Collapse)AuthorAgeFilesLines
* Merge pull request #5388 from adriaanm/issue-219Adriaan Moors2016-09-283-2/+13
|\ | | | | Avoid mismatched symbols in fields phase
| * Cast more pro-actively in synthetic accessor trees.Adriaan Moors2016-09-262-2/+2
| | | | | | | | Also narrow scope of afterOwnPhase.
| * Avoid mismatched symbols in fields phaseAdriaan Moors2016-09-261-0/+11
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | The info of the var that stores a trait's lazy val's computed value is expressed in terms of symbols that exist before the fields phase. When we're implementing the lazy val in a subclass of that trait, we now see symbols created by the fields phase, which results in mismatches between the types of the lhs and rhs in the assignment of `lazyVar = super.lazyImpl`. So, type check the super-call to the trait's lazy accessor before our own phase. If the lazy var's info depends on a val that is now implemented by an accessor synthesize by our info transformer, we'll get a mismatch when assigning `rhs` to `lazyVarOf(getter)`, unless we also run before our own phase (like when we were creating the info for the lazy var). This was revealed by Hanns Holger Rutz's efforts in compiling scala-refactoring's test suite (reported on scala-internals). Fixes scala/scala-dev#219
* | SD-233 synchronized blocks are JIT-friendly againJason Zaugg2016-09-271-0/+8
|/ | | | | | | | | | | | | | | | GenBCode, the new backend in Scala 2.12, subtly changed the way that synchronized blocks are emitted. It used `java/lang/Throwable` as an explicitly named exception type, rather than implying the same by omitting this in bytecode. This appears to confuse HotSpot JIT, which reports a error parsing the bytecode into its IR which leaves the enclosing method stuck in interpreted mode. This commit passes a `null` descriptor to restore the old pattern (the same one used by javac.) I've checked that the JIT warnings are gone and that the method can be compiled again.
* Merge pull request #5395 from retronym/pr/5394Jason Zaugg2016-09-151-0/+16
|\ | | | | Avoid omitting constant typed vals in constructors
| * Avoid omitting constant typed vals in constructorsJason Zaugg2016-09-121-0/+16
| | | | | | | | | | | | | | | | | | | | | | | | | | Fix for regression in 2.12.0-RC1 compiling shapeless tests. They were given the same treatment as vals that are members of classes on the definition side without the requisite transformation of references to the val to fold the constant into references. This commit limits the transform to members of classes. Co-Authored-By: Miles Sabin <miles@milessabin.com>
* | Merge pull request #5398 from retronym/ticket/SD-225Jason Zaugg2016-09-154-7/+16
|\ \ | | | | | | SD-225 Use a "lzycompute" method for module initialization
| * | SD-225 Use a "lzycompute" method for module initializationJason Zaugg2016-09-144-7/+16
| |/ | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | The monitors and module instantation were inliuned into the module accessor method in b2e0911. However, this seems to have had a detrimental impact on performance. This might be because the module accessors are now above the "always inline" HotSpot threshold of 35 bytes, or perhaps because they contain monitor-entry/exit and exception handlers. This commit returns to the the 2.11.8 appraoch of factoring the the second check of the doublecheck locking into a method. I've done this by declaring a nested method within the accessor; this will be lifted out to the class level by lambdalift. This represents a slight deviation from the implementation strategy used for lazy accessors, which create a symbol for the slowpath method in the info transform and generate the corresponding DefDef as a class member. I don't believe this deviation is particular worrisome, though. I have bootstrapped the compiler through this commit and found that the drastic regression in compiling the shapeless test suite is solved.
* / SI-9918 object in trait mixed into package objectAdriaan Moors2016-09-102-0/+4
|/
* Merge pull request #5368 from retronym/ticket/SD-208Adriaan Moors2016-09-061-1/+1
|\ | | | | | | | | SD-208 Restore 2.11 names for arrayOps implicits Fix scala/scala-dev#208
| * SD-208 Restore 2.11 names for arrayOps implicitsJason Zaugg2016-08-311-1/+1
| |
| * Disable stack hungry test of deprecated PagedSeqJason Zaugg2016-08-311-1/+2
| |
* | SD-143 allow super calls to methods defined in indirect super classesJason Zaugg2016-09-051-0/+23
| | | | | | | | | | | | | | | | The restriction for super calls to methods defined in indirect super classes introduced in a980fde was over-restrictive. In particular, it ruled out a valid code pattern to select a method from a superclass when an unqualified `super` would resolve to an override defined in a trait (example in the commit as a test).
* | Merge pull request #5369 from lrytz/sd210Lukas Rytz2016-09-029-25/+119
|\ \ | | | | | | Fixes to mixin forwarders
| * | Add a -Xmixin-force-forwarders ChoiceSettingLukas Rytz2016-09-021-4/+4
| | |
| * | Allow per-choice help in ChoiceSettingLukas Rytz2016-09-021-2/+1
| | |
| * | Emit mixin forwarders for JUnit-annotated trait methods by defaultLukas Rytz2016-09-016-15/+25
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | JUnit 4 does not support default methods. For better user experience, this commit makes the compiler generate mixin forwarders for inherited trait methods that carry a JUnit annotation. The -Yjunit-trait-methods-no-forwarders flag disables this behavior. This supersedes the scala-js/scala-2.12-junit-mixin-plugin compiler plugin.
| * | SD-143 error for super calls that cannot be implemented correctlyLukas Rytz2016-09-011-5/+22
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | If a call super[T].m resolves to a method A.m where A is a class, but not the direct superclass of the current class, there is no way to emit an invocation of A.m: `invokespecial A.m` will resolve to B.m where B is the superclass of the current class. This commit adds an error message in this case. Note that this is similar to an existing error message for qualified super calls to a non-direct superclass: class A { def m = 1 } class B extends A { override def m = 2 } class C extends B { override def m = super[A].m } Gives "error: A does not name a parent class of class C". If the user means to call method m in the superclass, he can write an unqualified `super.m`. An similar error message is introduced if A is a Java-defined interface (and m is a default method), and A is not a direct parent of the current class. In this case `invokespecial A.m` is invalid bytecode. The solution is to add A as a direct parent of the current class.
| * | SD-210 don't generate invalid forwarders under -Xgen-mixin-forwardersLukas Rytz2016-09-011-1/+68
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | With -Xgen-mixin-forwarders the compiler eagerly creates mixin forwarders for methods inherited from traits, even if the JVM method resolution would pick the correct default method. When generating a such a forwarder for a Java-defined default method, the mixin forwarder invokes the default method directly using `invokespecial` (for Scala-defined trait methods, the forwarder uses the static `m$` method that is generated for every trait method). An `invokespecial` call is only legal if the named interface is a direct parent of the current class. If this is not the case, we don't generate the mixin forwarder and emit a warning. In the tests there's also an example where a mixin forwarder is required for correctness, but cannot be added because the corresponding `invokespecial` call would be invalid. In this case we emit an error. This is similar to what we already do for other super calls to Java- defined default methods. The difference is that the super call is not written by the user but generated by the mixin forwarder. The solution is the same: add the interface as a direct parent.
| * | Disable stack hungry test of deprecated PagedSeqJason Zaugg2016-09-011-1/+2
| | |
* | | Merge pull request #5294 from adriaanm/fields-laziesAdriaan Moors2016-09-0148-220/+601
|\ \ \ | |/ / |/| | Fields: expand lazy vals during fields, like modules
| * | Cleanups after integrating lazyvals into fields.Adriaan Moors2016-09-011-2/+2
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Mostly refactorings and catching up with doc updates. Some changes to flag handling, removing some redundancy, and making lazy fields and modules a bit more consistent in their flags. They now uniformly carry LAZY or MODULEVAR. Before, LAZY was dropped because mixin had some lazy val logic. No longer.
| * | Specialize erasure of `synchronized` primitive methodAdriaan Moors2016-08-302-16/+4
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | The goal is to avoid emitting unneeded `BoxedUnit` values, which are the result of adapting a `Unit`-typed expression inside a `synchronized(...)` to the erased type of `synchronized`'s argument -- `Object`. The proposed solution gives `synchronized` a polymorphic type (the info of the type param is still erased so that bounds checking works in the erased type system), so that an application `synchronized(println("boo"))` erases to `synchronized[Unit])(println("boo"))`, and no boxing is performed on the `println("boo")` argument, whose expected type is now `Unit` instead of `Object`.
| * | Double-checked locking for local lazy vals.Adriaan Moors2016-08-291-1/+1
| | |
| * | Double-checked locking for modules.Adriaan Moors2016-08-292-10/+18
| | | | | | | | | | | | Inline `mkSynchronizedCheck`, whose abstraction obscured rather than clarified.
| * | Ensure access from subclass to trait lazy valAdriaan Moors2016-08-291-0/+2
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Since we need to refer to a trait lazy val's accessor using a super call in a subclass (when the field and bitmap are added), we must ensure that access is allowed. If the lazy val has an access boundary (e.g., `private[somePkg]`), make sure the `PROTECTED` flag is set, which widens access to `protected[somePkg]`. (As `member.hasAccessBoundary` implies `!member.hasFlag(PRIVATE)`, we don't have to `resetFlag PRIVATE`.)
| * | Fields does bitmaps & synch for lazy vals & modulesAdriaan Moors2016-08-2916-71/+430
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Essentially, we fuse mixin and lazyvals into the fields phase. With fields mixing in trait members into subclasses, we have all info needed to compute bitmaps, and thus we can synthesize the synchronisation logic as well. By doing this before erasure we get better signatures, and before specialized means specialized lazy vals work now. Mixins is now almost reduced to its essence: implementing super accessors and forwarders. It still synthesizes accessors for param accessors and early init trait vals. Concretely, trait lazy vals are mixed into subclasses with the needed synchronization logic in place, as do lazy vals in classes and methods. Similarly, modules are initialized using double checked locking. Since the code to initialize a module is short, we do not emit compute methods for modules (anymore). For simplicity, local lazy vals do not get a compute method either. The strange corner case of constant-typed final lazy vals is resolved in favor of laziness, by no longer assigning a constant type to a lazy val (see widenIfNecessary in namers). If you explicitly ask for something lazy, you get laziness; with the constant-typedness implicit, it yields to the conflicting `lazy` modifier because it is explicit. Co-Authored-By: Lukas Rytz <lukas@lightbend.com> Fixes scala/scala-dev#133 Inspired by dotc, desugar a local `lazy val x = rhs` into ``` val x$lzy = new scala.runtime.LazyInt() def x(): Int = { x$lzy.synchronized { if (!x$lzy.initialized) { x$lzy.initialized = true x$lzy.value = rhs } x$lzy.value } } ``` Note that the 2.11 decoding (into a local variable and a bitmap) also creates boxes for local lazy vals, in fact two for each lazy val: ``` def f = { lazy val x = 0 x } ``` desugars to ``` public int f() { IntRef x$lzy = IntRef.zero(); VolatileByteRef bitmap$0 = VolatileByteRef.create((byte)0); return this.x$1(x$lzy, bitmap$0); } private final int x$lzycompute$1(IntRef x$lzy$1, VolatileByteRef bitmap$0$1) { C c = this; synchronized (c) { if ((byte)(bitmap$0$1.elem & 1) == 0) { x$lzy$1.elem = 0; bitmap$0$1.elem = (byte)(bitmap$0$1.elem | 1); } return x$lzy$1.elem; } } private final int x$1(IntRef x$lzy$1, VolatileByteRef bitmap$0$1) { return (byte)(bitmap$0$1.elem & 1) == 0 ? this.x$lzycompute$1(x$lzy$1, bitmap$0$1) : x$lzy$1.elem; } ``` An additional problem with the above encoding is that the `lzycompute` method synchronizes on `this`. In connection with the new lambda encoding that no longer generates anonymous classes, captured lazy vals no longer synchronize on the lambda object. The new encoding solves this problem (scala/scala-dev#133) by synchronizing on the lazy holder. Currently, we don't exploit the fact that the initialized field is `@volatile`, because it's not clear the performance is needed for local lazy vals (as they are not contended, and as soon as the VM warms up, biased locking should deal with that) Note, be very very careful when moving to double-checked locking, as this needs a different variation than the one we use for class-member lazy vals. A read of a volatile field of a class does not necessarily impart any knowledge about a "subsequent" read of another non-volatile field of the same object. A pair of volatile reads and write can be used to implement a lock, but it's not clear if the complexity is worth an unproven performance gain. (Once the performance gain is proven, let's change the encoding.) - don't explicitly init bitmap in bytecode - must apply method to () explicitly after uncurry
| * | SI-8873 don't propagate primary ctor arg to case class's applyAdriaan Moors2016-08-291-0/+1
| | | | | | | | | | | | Final implementation based on feedback by Jason
| * | Fields phase expands lazy vals like modulesAdriaan Moors2016-08-2930-137/+160
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | They remain ValDefs until then. - remove lazy accessor logic now that we have a single ValDef for lazy vals, with the underlying machinery being hidden until the fields phase leave a `@deprecated def lazyAccessor` for scala-refactoring - don't skolemize in purely synthetic getters, but *do* skolemize in lazy accessor during typers Lazy accessors have arbitrary user code, so have to skolemize. We exempt the purely synthetic accessors (`isSyntheticAccessor`) for strict vals, and lazy accessors emitted by the fields phase to avoid spurious type mismatches due to issues with existentials (That bug is tracked as https://github.com/scala/scala-dev/issues/165) When we're past typer, lazy accessors are synthetic, but before they are user-defined to make this hack less hacky, we could rework our flag usage to allow for requiring both the ACCESSOR and the SYNTHETIC bits to identify synthetic accessors and trigger the exemption. see also https://github.com/scala/scala-dev/issues/165 ok 7 - pos/existentials-harmful.scala ok 8 - pos/t2435.scala ok 9 - pos/existentials.scala previous attempt: skolemize type of val inside the private[this] val because its type is only observed from inside the accessor methods (inside the method scope its existentials are skolemized) - bean accessors have regular method types, not nullary method types - must re-infer type for param accessor some weirdness with scoping of param accessor vals and defs? - tailcalls detect lazy vals, which are defdefs after fields - can inline constant lazy val from trait - don't mix in fields etc for an overridden lazy val - need try-lift in lazy vals: the assign is not seen in uncurry because fields does the transform (see run/t2333.scala) - ensure field members end up final in bytecode - implicit class companion method: annot filter in completer - update check: previous error message was tangled up with unrelated field definitions (`var s` and `val s_scope`), now it behaves consistently whether those are val/vars or defs - analyzer plugin check update seems benign, but no way to know... - error message gen: there is no underlying symbol for a deferred var look for missing getter/setter instead - avoid retypechecking valdefs while duplicating for specialize see pos/spec-private - Scaladoc uniformly looks to field/accessor symbol - test updates to innerClassAttribute by Lukas
* | | sbt build: fix "unchecked" warnings when compiling Java codeSeth Tisue2016-08-302-0/+2
| |/ |/|
* | Merge pull request #5367 from adriaanm/fields-widen-trait-varStefan Zeiger2016-08-291-0/+4
|\ \ | | | | | | Ensure trait var accessor type is widened
| * | Ensure trait var accessor type is widenedAdriaan Moors2016-08-291-0/+4
| |/ | | | | | | | | | | | | | | | | | | If we don't widen, we'll fail to find the setter when typing `x = 42`, because `x` is constant-folded to `0`, as its type is `=> Int(0)`. After widening, `x` is type checked to `x` and its symbol is the getter in the trait, which can then be rewritten to the setter. Regression spotted and test case by szeiger.
* | Merge pull request #5280 from retronym/ticket/8079Adriaan Moors2016-08-297-1/+31
|\ \ | |/ |/| SI-8079 Only expand local aliases during variance checks
| * Address review feedback: comments, renames and extra testJason Zaugg2016-08-292-0/+8
| |
| * SI-8079 Only expand local aliases during variance checksJason Zaugg2016-08-185-1/+23
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | We've been flip-flopping on this one through the years, right now we issue an two errors for the enclosed test. After this commit, variance validation only expands aliases that are `{private,protected}[this]`. The rest need not be expanded, as we have already variance validated the RHS of the alias. It also removes a seemingly incorrect check in `isLocalOnly`. This also means that we can use `@uncheckedVariance` to create variant type aliases for Java interfaces. However, if such a type alias is declared private local, it *will* be expanded. That shouldn't be a problem, other than for the fact that we run through an as-seen-from that strips the `@uV` annotations in the type expansion. This has been recorded in a pending test.
* | Merge pull request #5263 from retronym/review/5041Jason Zaugg2016-08-2911-7/+206
|\ \ | | | | | | SI-5294 SI-6161 Hard graft in asSeenFrom, refinements, and existentials [ci: last-only]
| * | Address review commentsJason Zaugg2016-08-232-7/+9
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | - clarify the intent of tests - Consolidate stripExistentialsAndTypeVars with similar logic in mergePrefixAndArgs - Refactor special cases in maybeRewrap The name isn't great, but I'm struggling to come up with a pithy way to describe the rogue band of types.
| * | Unit test for recent bug fix in LUBsJason Zaugg2016-08-231-0/+11
| | |
| * | SI-5294 Use bounds of abstract prefix in asSeenFromJason Zaugg2016-08-234-0/+88
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | ASF was failing to recognize the correspondence between a prefix if it has an abstract type symbol, even if it is bounded by the currently considered class. Distilling the test cases, this led to incorrect typechecking of the RHS of `G` in: ``` trait T { type A trait HasH { type H[U] <: U } type F[N <: HasH] = N#H[T] type G[N <: HasH] = F[N]#A // RHS was incorrectly reduced to T.this.A } ``` In the fuller examples (included as test cases), this meant that type level functions written as members of `HList` could not be implemented in terms of each other, e.g. defining `Apply[N]` as `Drop[N]#Head` had the wrong semantics. This commit checks checks if the prefix has the candidate class as a base type, rather than checking if its type symbol has this as a base class. The latter formulation discarded information about the instantation of the abstract type. Using the example above: ``` scala> val F = typeOf[T].member(TypeName("F")).info F: $r.intp.global.Type = [N <: T.this.HasH]N#H[T] scala> F.resultType.typeSymbol.baseClasses // old approach res14: List[$r.intp.global.Symbol] = List(class Any) scala> F.resultType.baseClasses // new approach res13: List[$r.intp.global.Symbol] = List(trait T, class Object, class Any) ``` It is worth noting that dotty rejects some of these programs, as it introduces the rule that: > // A type T is a legal prefix in a type selection T#A if > // T is stable or T contains no abstract types except possibly A. > final def isLegalPrefixFor(selector: Name)(implicit ctx: Context) However, typechecking the program above in this comment in dotty yields: <trait> trait T() extends Object { type A <trait> trait HasH() extends Object { type H <: [HK$0] => <: HK$0 } type F = [HK$0] => HK$0#H{HK$0 = T}#Apply type G = [HK$0] => HK$0#H{HK$0 = T}#Apply#A } As the equivalent code [1] in dotc's `asSeenFrom` already looks for a base type of the prefix, rather than looking for a superclass of the prefix's type symbol. [1] https://github.com/lampepfl/dotty/blob/d2c96d02fccef3a82b88ee1ff31253b6ef17f900/src/dotty/tools/dotc/core/TypeOps.scala#L62
| * | Improved refinement type and existential type handlingJason Zaugg2016-08-234-0/+83
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Lazy base type seq elements are encoded as a refined type with an empty scope and a list of type refs over some common type symbol that will be merged when `BaseTypeSeq#apply` is called. The first change in this commit is to mark the creation and consumption of such elements with calls to `[is]IntersectionTypeForBaseTypeSeq`. They are distinguished by using the actual type symbol rather than a refinement class symbol, which in turn simplifies the code in `BaseTypeSeq#typeSymbol`. I have also made `lub` aware of this encoding: it is now able to "see through" to the parents of such refined types and merge them with other base types of the same class symbol (even other refined types representing lazy BTS elements.) To make this fix work, I also had to fix a bug in LUBs of multiple with existential types. Because of the way the recursion was structured in `mergePrefixAndArgs`, the order of list of types being merged changed behaviour: quantified varialbles of existential types were being rewrapped around the resultting type, but only if we hadn't encountered the first regular `TypeRef`. This can be seen with the following before/after shot: ``` // 2.11.8 scala> val ts = typeOf[Set[Any]] :: typeOf[Set[X] forSome { type X <: Y; type Y <: Int}] :: Nil; def merge(ts: List[Type]) = mergePrefixAndArgs(ts, Variance.Contravariant, lubDepth(ts)); val merged1 = merge(ts); val merged2 = merge(ts.reverse); (ts.forall(_ <:< merged1), ts.forall(_ <:< merged2)) ts: List[$r.intp.global.Type] = List(Set[Any], Set[_ <: Int]) merge: (ts: List[$r.intp.global.Type])$r.intp.global.Type merged1: $r.intp.global.Type = scala.collection.immutable.Set[_ >: Int] merged2: $r.intp.global.Type = scala.collection.immutable.Set[_53] forSome { type X <: Int; type _53 >: X } res0: (Boolean, Boolean) = (false,true) // HEAD ... merged1: $r.intp.global.Type = scala.collection.immutable.Set[_10] forSome { type X <: Int; type _10 >: X } merged2: $r.intp.global.Type = scala.collection.immutable.Set[_11] forSome { type X <: Int; type _11 >: X } res0: (Boolean, Boolean) = (true,true) ``` Furthermore, I have fixed the computation of the base type sequences of existential types over refinement types, in order to maintain the invariant that each slot of the base type sequence of a existential has the same type symbol as that of its underlying type. Before, what I've now called a `RefinementTypeRef` was transformed into a `RefinedType` during rewrapping in the existential, which led to it being wrongly considered as a lazy element of the base type sequence. The first change above should also be sufficient to avoid the bug, but I felt it was worth cleaning up `maybeRewrap` as an extra line of defence. Finally, I have added another special case to `BaseTypeSeq#apply` to be able to lazily compute elements that have been wrapped in an existential. The unit test cases in `TypesTest` rely on these changes. A subsequent commit will build on this foundation to make a fix to `asSeenFrom`.
| * | Type#contains should peer into RefinementTypeRef-sJason Zaugg2016-08-192-0/+20
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Usually, `contains` should not look into class symbol infos. For instance, we expect that: ``` scala> trait C { def foo: Int }; typeOf[C].contains(IntClass) defined trait C res1: Boolean = false ``` We do, however, look at the decls of a `RefinedType` in contains: ``` scala> typeOf[{ def foo: Int }].contains(IntClass) res2: Boolean = true ``` Things get a little vague, however, when we consider a type ref to the refinement class symbol of a refined type. ``` scala> TypeRef(NoPrefix, typeOf[{ def foo: Int }].typeSymbol, Nil) res3: $r.intp.global.Type = AnyRef{def foo: Int} scala> .contains(IntClass) res4: Boolean = false ``` These show up in the first element of the base type seq of a refined type, e.g: ``` scala> typeOf[{ def foo: Int }].typeSymbol.tpe_* res5: $r.intp.global.Type = AnyRef{def foo: Int} scala> typeOf[{ def foo: Int }].baseTypeSeq(0).getClass res7: Class[_ <: $r.intp.global.Type] = class scala.reflect.internal.Types$RefinementTypeRef scala> typeOf[{ def foo: Int }].typeSymbol.tpe_*.getClass res6: Class[_ <: $r.intp.global.Type] = class scala.reflect.internal.Types$RefinementTypeRef ``` This commit takes the opinion that a `RefinementTypeRef` should be transparent with respect to `contains`. This paves the way for fixing the base type sequences of existential types over refinement types. The implementation of `ContainsCollector` was already calling `normalize`, which goes from `RefinementTypeRef` to `RefinedType`. This commit maps over the result, which looks in the parents and decls.
| * | Determistically enter classes from directory into package scopeJason Zaugg2016-08-192-7/+2
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | On Linux, the directory listing is not automatically sorted on Mac. This leads to non-determistic ids of Symbols of the classes in a directory, which in turn leads to instability of the ordering of parents within inferred refinement types. Notable, with this patch, we will stably infer: ``` scala> case class C(); case class D(); List(C(), D()).head defined class C defined class D res0: Product with Serializable = C() ``` rather than sometimes getting `Serializable with Product` on Linux. As such, I've removed the workarounds for this instability in two test cases.
* | | Merge pull request #5357 from SethTisue/topic/sd-206Seth Tisue2016-08-271-0/+4
|\ \ \ | | | | | | | | SAM for subtypes of FunctionN
| * | | SAM for subtypes of FunctionNLukas Rytz2016-08-261-0/+4
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | only exclude FunctionN types themselves from SAM, don't exclude their subtypes; we want e.g. trait T extends Function1[String, String] (x => x) : T to compile reference: https://github.com/scala/scala-dev/issues/206
* | | | Merge pull request #5349 from som-snytt/issue/9841-testAdriaan Moors2016-08-241-0/+12
|\ \ \ \ | |/ / / |/| | | SI-9841 Progression test for SO on init
| * | | SI-9841 Progression test for SO on initSom Snytt2016-08-171-0/+12
| |/ / | | | | | | | | | Test as reported in ticket. Works on 2.12.
* | | Switch remaining uses of ant over to sbtStefan Zeiger2016-08-231-6/+6
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | - Modify `tools/scaladoc-diff` to use sbt instead of ant. - Move `stability-test.sh` from `tools` to `scripts`. With the new build process without separate `locker` and `strap` stages, it doesn’t make sense to call this script without first setting up the proper test environment in a CI build. - Replace the use of `build.number` in `bootstrap` with a new `SHA-NIGHTLY` mode for `baseVersionSuffix`. - Make `partest` call sbt instead of ant for initializing the classpath and use the new classpath location (`quick` instead of `pack`).
* | | Merge pull request #5322 from retronym/topic/SD-194Adriaan Moors2016-08-221-10/+10
|\ \ \ | |/ / |/| | SD-194 Tweak module initialization to comply with JVM spec
| * | 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
* | | Merge pull request #5317 from retronym/ticket/SD-192Lukas Rytz2016-08-154-13/+13
|\ \ \ | | | | | | | | SD-192 Change scheme for trait super accessors