| Commit message (Collapse) | Author | Age | Files | Lines |
|
|
|
|
|
|
|
|
| |
We do need lazy to be robust, because initialization sequence might
trigger synced operations in unexpected order, leading to NPE's.
Even if this is optimizable by removing some of the lazies or by
carefully reordering cake layers, there's no guarantee that all this
effort won't break after another reflection refactoring.
|
|
|
|
| |
Fixes this glaring omission of synchronization for a core part of Symbol.info.
|
|
|
|
| |
This is another optimization we discussed with Roland.
|
|
|
|
|
|
|
|
| |
This is one of the changes suggested by Roland in order to reduce contention
caused by reflection GIL.
Locks optimized away here are indirectly used for such fundamental operations
as subtyping tests, so the optimization looks quite important.
|
|
|
|
| |
not anymore
|
|
|
|
|
|
|
|
|
|
|
| |
In the current synchronization scheme multiple threads can enter the
missingHook trying to materialize a package, which hasn't been created.
That's fine, because makeScalaPackage, which creates and enters package
symbols is synchronized and checks whether the creation is necessary
before commencing. Therefore even if makeScalaPackage is called multiple
times in rapid succession, the calls will be serialized and all calls
except the first one won't do anything.
|
|
|
|
|
| |
Called from isVolatile, which is called from isStable, which is a part
of the public reflection API.
|
|
|
|
|
| |
We don't guarantee thread-safety of the front end, but everything else
looks good now.
|
|
|
|
|
|
| |
selfType joins the happy family of flags, annotations and privateWithin,
which automatically trigger initialization, when used within runtime
reflection.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
First of all, GIL should only apply to runtime reflection, because noone
is going to run toolboxes in multiple threads: a) that's impossible, b/c
the compiler isn't thread safe, b) ToolBox api prevents that.
Secondly, the only things in symbols which require synchronization are:
1) info/validTo (completers aren't thread-safe),
2) rawInfo and its dependencies (it shares a mutable field with info)
3) non-trivial caches like in typeAsMemberOfLock
If you think about it, other things like sourceModule or associatedFile
don't need synchronization, because they are either set up when a symbol
is created or cloned or when it's completed. The former is obviously safe,
while the latter is safe as well, because before acquiring init-dependent
state of symbols, the compiler calls `initialize`, which is synchronized.
We can say that symbols can be in four possible states: 1) being created,
2) created, but not yet initialized, 3) initializing, 4) initialized.
Of those only #3 is dangerous and needs protection, which is what this
commit does.
|
|
|
|
|
|
|
| |
On a serious note, I feel really uncomfortable about having to juggle
this slew of locks. Despite that I can't immediately find a deadlock,
I'm 100% sure there is one hiding in the shadows. Hence, I'm abandoning
all runtime reflection locks in favor of a single per-universe one.
|
| |
|
|
|
|
|
|
|
| |
- Include pack/lib/*.jar in the uptodatecheck
- (Hopefully that saves the next guy a few hours)
- Switch the the XML formatter (I couldn't find output from the other one)
and mention the output directory.
|
|
|
|
|
|
|
|
|
|
|
|
| |
The code to do so is curated with the help of a generator. Because this
needs to inspect code post-typer, the code generator is run during partest
as a code-validator. We could concievably do the same with a macro, but
this approach might be a better starting point which macros continue to
stabilize.
Removes Definitions.AnyRefModule and an already deprecated alias, as
these have been throwing exceptions for more than a year since 6bb5975289.
They used to be used by AnyRef specialization.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
At first I just tried to remove syntheticCoreClasses from missingHook
and put them into the initializer of freshly created mirrors in order to
reduce the non-determinism in mutations of the global symbol table.
And then it didn't work, crashing on me claiming that AnyRef is missing.
Apparently we still need AnyRefClass in missingHook, just because it's
impossible to initialize (i.e. unpickle) ScalaPackageClass without it.
And then it still didn't work, whining about multiple overloaded defs
of some synthetic symbols. That was really tricky, but I figured it out
as well by initializing ScalaPackageClass first before forcing any
synthetic symbols (see the details in comments).
And then it worked, but stopped working half a year later when
Jason and I came to revisit this old pull request. The final twist
was pre-initializing ObjectClass, because it's a dependency of AnyRefClass,
which is a critical dependency of ScalaPackageClass (full information
can be found in comments).
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Mentioned methods mutate the global `atPhaseStack` variable, which can
easily lead to imbalances and, ultimately, to the empty stack error.
Luckily for us, there's only one dummy phase, SomePhase, which is used
by runtime reflection, so there is absolutely zero need to invoke atPhase
in non-compiler reflexive universes.
The cleanest solution would be to override `atPhase` for runtime reflection,
but it's @inline final, so I didn't want to pay performance penalties for
something that's used three times in runtime reflection (during unpickling, in
reflection-specific completers and in `Symbol.typeParams/unsafeTypeParams`).
Therefore I added overrideable analogues of `atPhase` and `atPhaseNotLaterThan`
which are called from the aforementioned code shared between the compiler and
runtime reflection. I also had to duplicate the code of `Symbol.XXXtypeParams`
(only in SynchronizedSymbols, not in normal Symbols) again due to those
methods being very performance-sensitive.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Synchronization via decoration would be neat if it actually worked.
Unfortunately, root symbols never got decorated, therefore their children
also never got decorated and all the way down to the very turtles.
This commit fixes this sad issue by turning root symbols from objects
to lazy vals. Yes, this is going to induce a performance penalty, which
will hopefully not be high enough to invalidate this cornerstone of our
synchronization strategy.
Now when root symbols are lazy vals, they can be overridden in the runtime
reflexive universe and decorated with SynchronizedSymbol, which makes their
children sync and sound.
|
|
|
|
|
|
|
| |
Too bad I didn't notice that before. That will free up quite a bit of
memory, removing an extraneous field in every single Symbol, namely the:
private volatile Symbols.Symbol.SymbolKind$ SymbolKind$module
|
|\
| |
| | |
SI-3346 implicit parameters can now guide implicit view inference
|
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| | |
This simple patch makes it possible for implicit views to benefit from
fundep-guided type inference, eliminating a nasty special case in
implicit inference.
Here are the changes that I had to apply to the tests (they exposed
quite a number of interesting questions that I was happy to answer):
1) neg/t5845.scala now works, so I moved it to pos. That easily makes sense,
because the test was just a canary to track previous state of things.
2) neg/divergent_implicit.scala, neg/t5578.scala and neg/t7519.scala
changed their messages to less informative ones, because inapplicable
implicit views now get disqualified early and therefore don't display
their error messages to the user. This is an unfortunate but necessary
byproduct of this change, and one can argue that the behavior is now
completely consistent with implicit vals (that also don't explain why
this or that implicit val got disqualified, but rather display a generic
implicit value not found message).
3) scaladoc/implicits-chaining.scala and scaladoc/implicits-base.scala.
Immediate culling of apriori inapplicable implicit views messes things up
for Scaladoc, because it's interested in potentially applicable views,
having infrastructure to track various constraints (type bounds, requirements
for implicit parameters, etc) that guide applicability of views and then
present it to the user. Therefore, when scaladoc is detected, implicit search
reverts to the old behavior.
4) We still cannot have Jason's workaround to type constructor inference
mentioned in comments to SI-3346, because it's not really about implicit
parameters of implicit views, but about type inference flowing from the
implicit parameter list to a preceding parameter list in order to affect
inference of an implicit view. This is something that's still too ambitious.
|
|\ \
| | |
| | | |
Merge 2.10.x into master
|
| |\ \
| | | |
| | | |
| | | |
| | | |
| | | | |
Conflicts:
build.number
test/files/neg/classmanifests_new_deprecations.check
|
| | |\ \
| | | | |
| | | | | |
Don't issue deprecation warnings for inferred TypeTrees
|
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | | |
Deprecation checks in RefChecks were looking into all TypeTrees
to find references to deprecated type aliases. However, when the
compiler infers a type argument or type of a member it creates
a TypeTree (with a null original) that was also leading to warnings.
I ran into this problem often when upgrading a build from SBT 0.12
to 0.13: a plugin I was using used the deprecated type alias, and I
suffered transitively when I used methods from its API.
This commit disables the checks for inferred TypeTree-s.
|
| | |\ \ \
| | | | | |
| | | | | | |
Bump version to 2.10.4 for nightlies
|
| | |/ / / |
|
|\ \ \ \ \
| | | | | |
| | | | | | |
Test cases for SAM restrictions.
|
| | | | | |
| | | | | |
| | | | | |
| | | | | |
| | | | | |
| | | | | |
| | | | | |
| | | | | |
| | | | | |
| | | | | | |
Only one seems to indicate something new:
((x: Int) => 0): NonClassType
I believe that we shouldn't pursue SAM translation for that case,
and fallthrough to Function1. That would allow for an implicit view
to finish the job.
|
|\ \ \ \ \ \
| |/ / / / /
|/| | | | | |
Fix AsSeenFrom of ThisType from TypeVar prefix
|
| | | | | |
| | | | | |
| | | | | |
| | | | | |
| | | | | |
| | | | | |
| | | | | |
| | | | | |
| | | | | |
| | | | | |
| | | | | |
| | | | | |
| | | | | |
| | | | | |
| | | | | |
| | | | | |
| | | | | |
| | | | | |
| | | | | |
| | | | | |
| | | | | |
| | | | | |
| | | | | |
| | | | | |
| | | | | |
| | | | | |
| | | | | |
| | | | | |
| | | | | |
| | | | | |
| | | | | |
| | | | | | |
Restores behaviour for the AsSeenFrom before the refactoring
in b457b6c477.
This commit uniformly considered that a `TypeVar` prefix should not
`matchesPrefixAndClass`; a condition that formerly was only applied
if the type being viewed was a `TypeRef`. This condition was
originally added in cc9e8eda3364d as a backstop for pos/t2797.scala.
This commit leaves that backstop in place where it was, although it
expresses it more directly by checking if `pre baseType clazz` is
`NoType`, which was the case that cropped up in SI-2797:
scala> type T = bc._1.type forSome { val bc: (AnyRef, AnyRef) }
warning: there were 1 feature warning(s); re-run with -feature for details
defined type alias T
scala> val et = typeOf[T].dealias.asInstanceOf[ExistentialType]
et: $r.intp.global.ExistentialType = bc._1.type forSome { val bc: (AnyRef, AnyRef) }
scala> et.withTypeVars( { x =>
| println(x.prefix.typeSymbol)
| println(x.prefix.typeSymbol.isSubClass(typeOf[Tuple2[_, _]].typeSymbol))
| println(x.prefix.baseType(typeOf[Tuple2[_, _]].typeSymbol))
| true
| } , reflect.internal.Depth(0))
type bc.type
true
<notype>
res98: Boolean = true
|
|\ \ \ \ \ \
| |_|/ / / /
|/| | | | | |
Traverser and Pickler improvements.
|
| | | | | |
| | | | | |
| | | | | |
| | | | | |
| | | | | |
| | | | | |
| | | | | |
| | | | | |
| | | | | |
| | | | | |
| | | | | |
| | | | | |
| | | | | |
| | | | | |
| | | | | |
| | | | | |
| | | | | | |
This commit drops about 700 lines of redundant traversal logic.
There had been ad hoc adjustments to the pickling scheme here and
there, probably in pursuit of tiny performance improvements.
For instance, a Block was pickled expr/stats instead of stats/expr,
a TypeDef was pickled rhs/tparams instead of tparams/rhs.
The benefits derived are invisible compared to the cost of having
several hundred lines of tree traversal code duplicated in half a
dozen or more places.
After making Traverser consistent/complete, it was a straightforward
matter to use it for pickling. It is ALSO now possible to write a
vastly cleaner tree printer than the ones presently in trunk, but I
leave this as an exercise for Dear Reviewer.
|
| | | | | |
| | | | | |
| | | | | |
| | | | | |
| | | | | |
| | | | | |
| | | | | |
| | | | | |
| | | | | |
| | | | | |
| | | | | |
| | | | | |
| | | | | |
| | | | | |
| | | | | |
| | | | | |
| | | | | |
| | | | | |
| | | | | |
| | | | | |
| | | | | |
| | | | | | |
There's a huge amount of tree traversal related duplication
which is hard to eliminate only because trees aren't properly
traversed. The not-quite-tree bits of key trees are ignored
during traversals, making it impossible to write e.g. a
pretty printer without duplicating almost the entire traversal
logic (as indeed is done for printing purposes in more than one
place.) And almost the entire pickler logic is redundant with
Traverser, except since it's all duplicated of course it diverged.
The pickler issue is remedied in the commit to follow.
The not-quite-trees not quite being traversed were Modifiers, Name,
ImportSelector, and Constant. Now every case field of every tree is
traversed, with classes which aren't trees traversed via the following
methods, default implementations as shown:
def traverseName(name: Name): Unit = ()
def traverseConstant(c: Constant): Unit = ()
def traverseImportSelector(sel: ImportSelector): Unit = ()
def traverseModifiers(mods: Modifiers): Unit = traverseAnnotations(mods.annotations)
|
| | | | | |
| | | | | |
| | | | | |
| | | | | |
| | | | | |
| | | | | | |
This enables a measure of "command/query separation", which is
to say: the same method shouldn't go on a side effecting binge
and also return a value.
|
| | | | | | |
|
| | | | | | |
|
|\ \ \ \ \ \
| | | | | | |
| | | | | | | |
[master] assorted fixes for vampire macros
|
| | | | | | |
| | | | | | |
| | | | | | |
| | | | | | |
| | | | | | |
| | | | | | |
| | | | | | |
| | | | | | |
| | | | | | |
| | | | | | |
| | | | | | |
| | | | | | |
| | | | | | | |
As eloquently elaborated and cleverly named by Travis Brown, macros
defined in structural types are useful:
http://meta.plasm.us/posts/2013/07/12/vampire-methods-for-structural-types/.
However, since such macros are on the intersection of a number of language
features, as usual, there are bugs.
This commit fixes an unwanted interaction of macros defined in structural
types with the scala.language.reflectiveCalls guard. Since macro calls
aren't going to be carried to runtime, there's no need to warn about them.
|
|\ \ \ \ \ \ \
| | | | | | | |
| | | | | | | | |
[resubmit] Experimental Single Abstract Method support (sammy meets world)
|
| |\ \ \ \ \ \ \
| | | |/ / / / /
| | |/| | | | |
| | | | | | | |
| | | | | | | | |
Conflicts:
src/compiler/scala/tools/nsc/typechecker/Typers.scala
|
| | | | | | | | |
|
| | | | | | | |
| | | | | | | |
| | | | | | | |
| | | | | | | |
| | | | | | | |
| | | | | | | |
| | | | | | | |
| | | | | | | |
| | | | | | | |
| | | | | | | |
| | | | | | | | |
Inspired by test/files/run/t7398.scala and sammy_poly.
Added some notes to original tests.
Elaborating on that note: we don't yet desugar `f(a)` to `f.sam(a)`,
like we do for regular functions: `f(a)` becomes `f.apply(a)`.
It seems pleasingly symmetrical and is easy to implement,
but not sure it's a good idea...
|
| | | | | | | |
| | | | | | | |
| | | | | | | |
| | | | | | | | |
Addressing review feedback.
|
| | | | | | | |
| | | | | | | |
| | | | | | | |
| | | | | | | |
| | | | | | | |
| | | | | | | |
| | | | | | | |
| | | | | | | |
| | | | | | | |
| | | | | | | |
| | | | | | | |
| | | | | | | |
| | | | | | | |
| | | | | | | | |
Before this change:
scala> trait T { def apply(a: Int): Int }
defined trait T
scala> ((x: Int, y: Int) => 0): T
<console>:9: error: object creation impossible, since method apply in trait T of type (a: Int)Int is not defined
((x: Int, y: Int) => 0): T
^
After the change, these cases report the same errors as they do
*without* -Xexperimental.
|
| | | | | | | |
| | | | | | | |
| | | | | | | |
| | | | | | | |
| | | | | | | |
| | | | | | | |
| | | | | | | |
| | | | | | | |
| | | | | | | |
| | | | | | | | |
Under `-Xexperimental`, `typedFunction` invokes `synthesizeSAMFunction`
when the expected type for the function literal (`pt`) is not the built-in
`FunctionN` type of the expected arity, but `pt` does have a SAM
with the expected number of arguments.
PS: We'll require `import language.sam` instead of `-Xexperimental`,
as soon as the SIP is ready and there are more tests.
|
| | | | | | | |
| | | | | | | |
| | | | | | | |
| | | | | | | |
| | | | | | | |
| | | | | | | |
| | | | | | | |
| | | | | | | |
| | | | | | | |
| | | | | | | |
| | | | | | | |
| | | | | | | |
| | | | | | | |
| | | | | | | |
| | | | | | | |
| | | | | | | |
| | | | | | | |
| | | | | | | |
| | | | | | | |
| | | | | | | |
| | | | | | | |
| | | | | | | |
| | | | | | | |
| | | | | | | |
| | | | | | | |
| | | | | | | |
| | | | | | | |
| | | | | | | |
| | | | | | | |
| | | | | | | |
| | | | | | | |
| | | | | | | |
| | | | | | | |
| | | | | | | |
| | | | | | | |
| | | | | | | |
| | | | | | | |
| | | | | | | |
| | | | | | | | |
`synthesizeSAMFunction` will be used to expand the following tree:
```
{ (p1: T1, ..., pN: TN) => body } : S
```
to:
```
{
def apply$body(p1: T1, ..., pN: TN): T = body
new S { def apply(p1: T1, ..., pN: TN): T = apply$body(p1,..., pN) }
}
```
The expansion assumes `S` (the expected type) defines a single abstract method
(let's call that method `apply` for simplicity).
1. If 'T' is not fully defined, it is inferred by type checking
`def apply$body` without a result type before type checking the block.
The method's inferred result type is used instead of T`.
[See test/files/pos/sammy_poly.scala]
2. To more easily enforce S's members are not in scope in `body`, that tree
goes to the `apply$body` method that's outside the anonymous subclass of S.
(The separate `apply$body` method simplifies the implementation of 1&2.)
3. The following restrictions apply to S:
1. Its primary constructor (if any) must be public, no-args, not overloaded.
2. S must have exactly one abstract member, its SAM
3. SAM must take exactly one argument list
4. SAM must be monomorphic
We may later relax these requirements to allow an implicit argument list,
both on the constructor and the SAM. Could also let the SAM be polymorphic.
|
| | | | | | | |
| | | | | | | |
| | | | | | | |
| | | | | | | |
| | | | | | | | |
When looking for deferred members, it only makes sense
to retry when deferred members aren't excluded.
|
| | |/ / / / /
| |/| | | | | |
|
|\ \ \ \ \ \ \
| | | | | | | |
| | | | | | | | |
SI-7899 Allow by-name inference under -Yinfer-by-name
|
| | |_|/ / / /
| |/| | | | |
| | | | | | |
| | | | | | |
| | | | | | |
| | | | | | |
| | | | | | |
| | | | | | |
| | | | | | |
| | | | | | |
| | | | | | |
| | | | | | |
| | | | | | |
| | | | | | |
| | | | | | |
| | | | | | |
| | | | | | |
| | | | | | | |
As usual, the hole has been exploited in the wild. While you
can't abstract over by-name-ness without running into the
ClassCastException or an un-applied Function0, there are cases
like the enclosed test where you can tiptoe around those
cases.
I've proposed a small change to Scalaz to avoid tripping over
this problem:
https://github.com/scalaz/scalaz/pull/562/files
But this commit I've also added a transitional flag, -Yinfer-by-name,
that they could use to back-publish older versions without code
changes. It is also an insurance policy for other projects that
might be exploiting the same hole.
|