| Commit message (Collapse) | Author | Age | Files | Lines |
|
|
|
| |
Inline `mkSynchronizedCheck`, whose abstraction obscured rather than clarified.
|
|
|
|
|
|
|
|
|
|
|
| |
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`.)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
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
|
|
|
|
| |
Final implementation based on feedback by Jason
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
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
|
|\
| |
| | |
SI-5294 SI-6161 Hard graft in asSeenFrom, refinements, and existentials [ci: last-only]
|
| |
| |
| |
| |
| |
| |
| |
| |
| |
| | |
- 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.
|
| | |
|
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| | |
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
|
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| | |
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`.
|
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| | |
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.
|
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| | |
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.
|
|\ \
| | |
| | | |
SAM for subtypes of FunctionN
|
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | | |
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
|
|\ \ \
| |/ /
|/| | |
SI-9841 Progression test for SO on init
|
| |/
| |
| |
| | |
Test as reported in ticket. Works on 2.12.
|
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| | |
- 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`).
|
|\ \
| |/
|/| |
SD-194 Tweak module initialization to comply with JVM spec
|
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| | |
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
|
|\ \
| | |
| | | |
SD-192 Change scheme for trait super accessors
|
| |/
| |
| |
| |
| |
| | |
Rather than putting the code of a trait method body into a static method,
leave it in the default method. The static method (needed as the target
of the super calls) now uses `invokespecial` to exactly call that method.
|
|\ \
| | |
| | | |
SI-9847 Nuance pure expr statement warning
|
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | | |
Clarify the current warning, which means that an expression
split over multiple lines may not be parsed as naively expected.
When typing a block, attempt minor nuance. For instance, a
single expression is not in need of parens. Try to avoid
duplicate warnings for expressions that were adapted away
from result position.
|
|\ \ \
| |_|/
|/| | |
SD-182 compiler option -Xgen-mixin-forwarders
|
| | |
| | |
| | |
| | |
| | | |
Introduce a compiler option -Xgen-mixin-forwarders to always generate
mixin forwarder methods.
|
|\ \ \
| | | |
| | | | |
Propagate overloaded function type to expected arg type
|
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | | |
Infer missing parameter types for function literals passed
to higher-order overloaded methods by deriving the
expected argument type from the function types in the
overloaded method type's argument types.
This eases the pain caused by methods becoming overloaded
because SAM types and function types are compatible,
which used to disable parameter type inference because
for overload resolution arguments are typed without
expected type, while typedFunction needs the expected
type to infer missing parameter types for function literals.
It also aligns us with dotty. The special case for
function literals seems reasonable, as it has precedent,
and it just enables the special case in typing function
literals (derive the param types from the expected type).
Since this does change type inference, you can opt out
using the Scala 2.11 source level.
Fix scala/scala-dev#157
|
|\ \ \ \
| | | | |
| | | | | |
Fixes to Java source support in Scaladoc
|
| | | | | |
|
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | | |
- fix initialization NPE in doc headers
- fix assertion errors for java fields
- ignore comments when deciding where to put interface methods
- consider DocDefs when checking for constructors
|
| | | | |
| | | | |
| | | | |
| | | | | |
[Jakob Odersky <jodersky@gmail.com>: remove obsolete comments and fix tests]
|
|\ \ \ \ \
| |/ / / /
|/| | | | |
SD-128 fix override checks for default methods
|
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | | |
The check for inheriting two conflicting members was wrong for default
methods, leading to a missing error message.
We were also not issuing "needs `override' modifier" when overriding a
default method.
Removes two methods:
- `isDeferredOrJavaDefault` had a single use that is removed in this commit.
- `isDeferredNotJavaDefault` is redundant with `isDeferred`, because
no default method has the `DEFERRED` flag:
- For symbols originating in the classfile parser this was the case
from day one: default methods don't receive the `DEFERRED` flag.
Only abstract interface methods do, as they have the `JAVA_ACC_ABSTRACT`
flag in bytecode, which the classfile parser translates to `DEFERRED`.
- For symbols created by the Java source parser, we don't add the
`DEFERRED` to default methods anymore since 373db1e.
Fixes scala/scala-dev#128
|
|\ \ \ \ \
| |/ / / /
|/| | | |
| | | | |
| | | | | |
SD-20 Inlcude static methods in the InlineInfo in mixed compilation
Fixes scala/scala-dev#20
|
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | | |
In mixed compilation, the InlineInfo for a Java-defined class is created
using the class symbol (vs in separate compilation, where the info is
created by looking at the classfile and its methods). The scala compiler
puts static java methods into the companion symbol, and we forgot to
include them in the list of methods in the InlineInfo.
|
|\ \ \ \ \
| |_|/ / /
|/| | | | |
SD-193 Lock down lambda deserialization
|
| | | | |
| | | | |
| | | | |
| | | | |
| | | | | |
- Remove unused references to "addTargetMethods"
- Require that `targetMethodMap` is provided
|
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | | |
The old design allowed a forged `SerializedLambda` to be
deserialized into a lambda that could call any private method
in the host class.
This commit passes through the list of all lambda impl methods
to the bootstrap method and verifies that you are deserializing
one of these.
The new test case shows that a forged lambda can no longer call
the private method, and that the new encoding is okay with a large
number of lambdas in a file.
We already have method handle constants in the constant pool
to support the invokedynamic through LambdaMetafactory, so
the only additional cost will be referring to these in
the boostrap args for `LambdaDeserialize`, 2 bytes per lambda.
I checked this with an example:
https://gist.github.com/retronym/e343d211f7536d06f1fef4b499a0a177
Fixes SD-193
|
|\ \ \ \ \
| | | | | |
| | | | | | |
SI-8434 Make generic Set operations build the same kind of Set
|
| | | | | |
| | | | | |
| | | | | |
| | | | | |
| | | | | |
| | | | | |
| | | | | |
| | | | | |
| | | | | |
| | | | | |
| | | | | |
| | | | | |
| | | | | |
| | | | | |
| | | | | |
| | | | | | |
When building from a `Set` implementation that was statically seen as
a `collection.GenSet` or `collection.Set`, we used to build a default
`Set` implementation determined by `GenSetFactory.setCanBuildFrom`.
This change modifies `setCanBuildFrom` to determine the correct
implementation at runtime by asking the source `Set`’s companion object
for the `Builder`.
Tests are in `NewBuilderTest.mapPreservesCollectionType`, including lots
of disabled tests for which I believe there is no solution under the
current collection library design.
`Map` suffers from the same problem as `Set`. This *can* be fixed in the
same way as for `Set` with some non-trivial changes (see the note in
`NewBuilderTest`), so it is probably best left for Scala 2.13.
|
|\ \ \ \ \ \
| | | | | | |
| | | | | | | |
SI-9019 TraversableLike stringPrefix broken for inner classes
|
| | | | | | |
| | | | | | |
| | | | | | |
| | | | | | |
| | | | | | |
| | | | | | |
| | | | | | | |
This version preserves outer class and object names but discards
any part of the name after a `$` that does not start with an upper-case
letter. When an integer literal occurs after a `$`, the prefix up to
that point is dropped so that classes defined within methods appear as
top-level.
|
|\ \ \ \ \ \ \
| | | | | | | |
| | | | | | | | |
SI-6881 Detect reference equality when comparing streams
|
| |/ / / / / /
| | | | | | |
| | | | | | |
| | | | | | |
| | | | | | |
| | | | | | |
| | | | | | |
| | | | | | |
| | | | | | |
| | | | | | |
| | | | | | | |
`==` already covers this case. We override `equals` in `Stream` to do
the same when `equals` is called directly. This takes care of identical
streams.
To support short-circuiting equality checks on elements prepended to
identical streams we also override `sameElements` in `Cons` to treat
the case where both sides are `Cons` separately.
Tests in StreamTest.test_reference_equality.
|
|\ \ \ \ \ \ \
| | | | | | | |
| | | | | | | | |
SI-9585 hide auto-implicit conversions from scaladoc
|
| | | | | | | |
| | | | | | | |
| | | | | | | |
| | | | | | | |
| | | | | | | |
| | | | | | | |
| | | | | | | |
| | | | | | | |
| | | | | | | |
| | | | | | | |
| | | | | | | |
| | | | | | | |
| | | | | | | |
| | | | | | | |
| | | | | | | |
| | | | | | | |
| | | | | | | |
| | | | | | | |
| | | | | | | |
| | | | | | | |
| | | | | | | |
| | | | | | | |
| | | | | | | |
| | | | | | | |
| | | | | | | |
| | | | | | | |
| | | | | | | |
| | | | | | | |
| | | | | | | |
| | | | | | | |
| | | | | | | |
| | | | | | | |
| | | | | | | |
| | | | | | | |
| | | | | | | |
| | | | | | | |
| | | | | | | |
| | | | | | | |
| | | | | | | |
| | | | | | | | |
This hides implicits conversions (and potential members obtained through
it) that converts a type into itself, because these conversions are
usually non-sensical. They are not completely removed, just placed behind
`-doc-implicits-show-all`, like other implicits deemed probably useless.
---
Consider the scaladoc for the following class:
```
object Box {
implicit def anyToBox[T](t: T): Box[T] = new Box(t)
}
class Box[T](val t: T)
```
When looking for implicits members to add to class `Box`, it finds the
implicit conversion `anyToBox`, and applies it to itself to have an
implicit conversion to Box[Box[T]], which brings a useless implicit
member `t: Box[T]`.
This commit makes scaladoc ignore any conversion from a type to itself
(even if type parameters differ) by default.
Using the (very useful) `tools/scaladoc-diff` script, I found that this
change removes the following conversion from the library doc:
```
Ensuring[A] to Ensuring[Ensuring[A]]
anytostringadd[A] to any2stringadd[anytostringadd[A]]
ArrowAssoc[A] to ArrowAssoc[ArrowAssoc[A]]
=:=[From,To] to =:=[From,To]
SearchImpl[A,Repr] to SearchImpl[A,SearchImpl[A,Repr]]
CollectionsHaveToParArray[C, T] to CollectionsHaveToParArray[CollectionsHaveToParArray[C, T], T]
Ordered[A] to Ordered[Ordered[A]]
StringFormat[A] to StringFormat[StringFormat[A]]
```
|
|\ \ \ \ \ \ \ \
| | | | | | | | |
| | | | | | | | | |
SI-8339 remove deprecated rewrite of withFilter -> filter
|
| | | | | | | | |
| | | | | | | | |
| | | | | | | | |
| | | | | | | | |
| | | | | | | | |
| | | | | | | | |
| | | | | | | | | |
You must implement the `withFilter` method to use
`if`-guards in a `for`-comprehension.
(Drop pos/t7239.scala because it relied on this rewrite.)
|
|\ \ \ \ \ \ \ \ \
| | | | | | | | | |
| | | | | | | | | | |
Introducing: the fields phase [ci: last-only]
|
| | | | | | | | | |
| | | | | | | | | |
| | | | | | | | | |
| | | | | | | | | |
| | | | | | | | | |
| | | | | | | | | |
| | | | | | | | | |
| | | | | | | | | |
| | | | | | | | | |
| | | | | | | | | |
| | | | | | | | | |
| | | | | | | | | |
| | | | | | | | | | |
No longer making trait methods not-protected.
(The backend only does public/private because of the poor
mapping between visibility from Scala to the JVM).
Note that protected trait members will not receive static forwarders
in module classes (when mixed into objects).
Historic note: we used to `makeNotPrivate` during explicitouter,
now we do it later, which means more private methods must be excluded
(e.g., lambdaLIFTED ones).
|