| Commit message (Collapse) | Author | Age | Files | Lines |
... | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | | |
Cannot subclass such a class. (Well, we could subclass a sealed
class in the same compilation unit. We ignore this for simplicity.)
This is a bit of a sneaky fix for this bug, but our hand
is pretty much forced by other constraints, in this intersection
of overload resolution involving built-in function types and SAMs,
and type inference for higher-order function literals (#5307).
Luckily, in this particular issue, the overloading clash seems
accidental. The `sealed` `<:<` class is not a SAM type as it
cannot be subclassed outside of `Predef`. For simplicity,
we don't consider where the SAM conversion occurs and exclude
all sealed classes from yielding SAM types.
Thanks to Miles for pointing out that `final` was missing in my
first iteration of this fix.
|
|/ / /
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | | |
If a non-transient lazy val is the only user of a private field in
a class, the field is nulled out at the end of the lazy initializer.
This is tested in the existing test `run/lazy-leaks.scala`.
The analysis of which fields could be nulled out was recently moved
from `mixin` to the new `fields` phase. This introduced a regression
as a reference from an inner- or companion-classes had not yet
been processed by `explicitouter` to publicise private fields.
This commit delays the analysis to mixin (after explicit outer has
done its work.)
Navigating from `foo$lzycompute()` to `foo()` to `foo` is a little
dirty now. I'm not sure whether there is a more robust way to
structure things.
|
|\ \ \
| | | |
| | | | |
Emit local module like lazy val
|
| | | |
| | | |
| | | |
| | | |
| | | |
| | | | |
There's still a lot of duplication,
as well as plenty of opportunities
for constant folding / simplification.
|
|/ / /
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | | |
When a class captures an outer value, a field for that value is created
in the class. The class also gets a constructor parameter for the
captured value, the constructor will assign the field.
LambdaLift re-writes accesses to the local value (Ident trees) to the
field. However, if the statement accessing the local value will end up
inside the constructor, the access is re-written to the constructor
parameter instead. This is the case for constructor statements:
class C {
{
println(capturedLocal)
}
}
If C extends DelayedInit, the statement does not end up in C's
constructor, but into a new synthetic method. The access to
`capturedLocal` needs to be re-written to the field instead of the
constructor parameter.
LambdaLift takes the decision (field or constructor parameter) based on
the owner chain of `currentOwner`. For the constructor statement block,
the owner is a local dummy, for which `logicallyEnclosingMember` returns
the constructor symbol.
This commit introduces a special case in LambdaLift for local dummies
of DelayedInit subclasses: instead of the constructor, we use a
temporary symbol representing the synthetic method holding the
initializer statements.
|
| | | |
|
|\ \ \
| | | |
| | | | |
Fixes to mixin forwarders
|
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | | |
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.
|
|\ \ \ \
| |/ / /
|/| | | |
Fields: expand lazy vals during fields, like modules
|
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | | |
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`.
|
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | | |
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
|
| | | | |
|
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | | |
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-8079 Only expand local aliases during variance checks
|
| | | | |
|
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | | |
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.
|
| | | | |
|
| | | | |
|
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | | |
- 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.
|
| | | |
| | | |
| | | |
| | | |
| | | |
| | | | |
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.
|
|\ \ \ \
| | | | |
| | | | | |
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
|
|/ / / /
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | | |
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
|
|\ \ \ \
| | | | |
| | | | | |
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]
|
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | | |
Derive/filter/propagate annotations in info transformer,
don't rely on having type checked the derived trees in order
to see the annotations.
Use synthetics mechanism for bean accessors -- the others
will soon follow.
Propagate inferred tpt from valdef to accessors
by setting type in right spot of synthetic tree
during the info completer.
No need to add trees in derivedTrees, and get rid of
some overfactoring in method synthesis, now that we have
joined symbol and tree creation.
Preserve symbol order because tests are sensitive to it.
Drop warning on potentially discarded annotations,
I don't think this warrants a warning.
Motivated by breaking the scala-js compiler, which relied
on annotations appearing when trees are type checked.
Now that ordering constraint is gone in the new encoding,
we may as well finally fix annotation assignment.
|
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | | |
Remove some old, obsolete & untested hacks from ExplicitOuter.
Added a test for one of them to show this is now fine.
There are a lot of `makeNotPrivate` invocations sprinkled around
the codebase. Lets see if we can centralize the ones dealing
with trait methods that need implementations in the phase that emits them.
For example Fields (accessors for fields/modules) or SuperAccessors.
|
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | | |
There isn't much point to the late* flags in a world where
we're mutating flags left and right in tree and info transformers...
So, lets get rid of the indirection until we can include flags
in a symbol's type history, like we do for its info.
This retires lateDEFERRED (redundant with SYNTHESIZE_IMPL_IN_SUBCLASS).
Since it's introduced so late, it makes little sense to have these
synthetic members go back to DEFERRED. Instead, just set DEFERRED directly.
Also remove unused late* and not* flags.
notPRIVATE subsumes lateFINAL for effective finality (scala/scala-dev#126)
|
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | | |
We do this during uncurry so we can insert the necessary
applications to the empty argument list. Fields is too late.
Refchecks is no longer an info transform.
|
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | | |
Correct caching is impossible because `sym.tpeHK.asSeenFrom(pre, sym.owner)`
may have different results even for reference-identical `sym.tpeHK` and `pre`
(even in the same period). For example, `pre` could be a `ThisType`.
For such a type, `tpThen eq tpNow` does not imply `tpThen` and `tpNow` mean
the same thing, because `tpThen.typeSymbol.info` could have been different
from what it is now, and the cache won't know simply by looking at `pre`.
Somehow this distinction never caused trouble, but when starting to desugar
module definitions during the fields phase, it causes several test failures.
I tried keying the cache on the current period to no avail.
|
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | | |
For now, keep the info transform in refchecks.
Ultimately, refchecks should only check, not transform trees/infos.
Fixes https://github.com/scala/scala-dev/issues/126:
the accessor for a module in a trait is correctly marked non-final
(it's deferred).
|
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | | |
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
|
| |/ / /
| | | |
| | | |
| | | | |
Also deprecate the TraitSetter annotation.
|
|\ \ \ \
| |/ / /
|/| | | |
SI-8829 Defaultly scala -feature -deprecation
|
| |/ /
| | |
| | |
| | |
| | |
| | |
| | |
| | | |
"Re-run with -deprecation" is not always appropriate.
REPL gets to customize the message. The API includes the
setting and its name, because reflect Settings do not
have names. (!)
|
|\ \ \
| | | |
| | | | |
SD-183 Make refinement classes ineligible as SAMs
|
| |/ /
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | | |
Only non-refinement class types need apply, which is the same
restriction that we levy on parent types of a class.
```
scala> class C; class D extends C; type CD = C with D; class E extends CD
<console>:11: error: class type required but C with D found
class C; class D extends C; type CD = C with D; class E extends CD
^
scala> class C; class D extends C; type DC = D with C; class E extends DC
<console>:11: error: class type required but D with C found
class C; class D extends C; type DC = D with C; class E extends DC
^
```
Prior to this change:
```
scala> trait T { def t(a: Any): Any }; trait U; abstract class C extends T
defined trait T
defined trait U
defined class C
````
For indy-based lambdas:
```
scala> val tu: T with U = x => x
tu: T with U = $$Lambda$1812/317644782@3c3c4a71
scala> tu: U
java.lang.ClassCastException: $$Lambda$1812/317644782 cannot be cast to U
... 30 elided
```
For anon class based lambdas:
```
scala> ((x => x): C with U)
<console>:14: error: class type required but C with U found
((x => x): C with U)
^
scala> implicit def anyToCWithU(a: Any): C with U = new C with U { def t(a: Any) = a }
warning: there was one feature warning; re-run with -feature for details
anyToCWithU: (a: Any)C with U
scala> (((x: Any) => x): C with U) // SAM chosen but fails to typecheck the expansion uncurry
<console>:17: error: class type required but C with U found
(((x: Any) => x): C with U) // SAM chosen but fails to typecheck the expansion uncurry
^
```
Fixes https://github.com/scala/scala-dev/issues/183
While it is tempting to special case refinement classes with no decls by
flattening their parents into the parents of the lambda. But there are
some subtle issues at play with lineriazation order, as Martin pointed out
when I brought this up before: http://www.scala-lang.org/old/node/6817.html
|
| | |
| | |
| | |
| | |
| | | |
The constructor of scala.tools.asm.Handle now takes an additional
boolean parameter to denote whether the owner is an interface.
|
| | |
| | |
| | |
| | |
| | | |
Since octal escape is deprecated, use unicode escape
for string representation of constants.
|
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | | |
To quote a triple quote, only quote one quote.
Refactors the code for legibility.
Adds test for other inline cruft like control chars.
|
|/ /
| |
| |
| |
| |
| | |
The boolean test for triples was inadvertently flipped.
Adds test for pretty printed multiline strings
|
| | |
|
| |
| |
| |
| |
| |
| | |
this change is a bit scary because it changes code that's not been
changed in 11 years
https://github.com/scala/scala/commit/7fa7c93#diff-d5789e5ae5061197d782d08324b260dbL214
|
|\ \
| | |
| | | |
SI-9390 Emit local defs that don't capture this as static
|
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | | |
An existing optimization in `Constructors` elides the outer
field in member and local classes, if the class doesn't use
the outer reference. (Member classes also need to be final,
which is a secret handshake to say we're also happy to weaken
prefix matching in the pattern matcher.)
That optimization leaves the constructor signature as is: the
constructor still accepts the outer instance, but does not store
it. For member classes, this means that we can separately compile
code that calls the constructor.
Local classes need not be hampered by this constraint, we could
remove the outer instance from the constructor call too.
Why would we want to do this?
Let's look at the case before and after this commit.
Before:
```
class C extends Object {
def foo(): Function1 = $anonfun();
final <static> <artifact> def $anonfun$foo$1($this: C, x: Object): Object = new <$anon: Object>($this);
def <init>(): C = {
C.super.<init>();
()
}
};
final class anon$1 extends Object {
def <init>($outer: C): <$anon: Object> = {
anon$1.super.<init>();
()
}
}
```
After:
```
class C extends Object {
def foo(): Function1 = $anonfun();
final <static> <artifact> def $anonfun$foo$1(x: Object): Object = new <$anon: Object>(null);
def <init>(): C = {
C.super.<init>();
()
}
};
final class anon$1 extends Object {
def <init>($outer: C): <$anon: Object> = {
anon$1.super.<init>();
()
}
}
```
However, the status quo means that a lambda that
This in turn makes lambdas that refer to such classes serializable
even when the outer class is not itself serialiable.
I have not attempted to extend this to calls to secondary constructors.
|