| Commit message (Collapse) | Author | Age | Files | Lines |
|\
| |
| | |
Backport fix for #150 to 2.10.x
|
| |
| |
| |
| |
| |
| | |
And remove unused code.
(cherry picked from commit 7238bc1982cb1d87157c650115a2ae92a58430c9)
|
| |
| |
| |
| |
| |
| |
| | |
This avoids leaving .class files in the working directory
after running the test.
(cherry picked from commit 5bb93b0b7357259eb588437a45063bf43595028a)
|
| |
| |
| |
| |
| |
| |
| |
| | |
By declararing the parameter of `async` as by-name.
Fixes #150 (the bug in the original ticket.)
(cherry picked from commit 4b1dbeef9ec73612867afc5dd9c925faa8cbc30d)
|
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| | |
If we blindly splicing `{..$stats, ..$generatedCode}`, and the last
expression in `$stats` is of type `Nothing`, we'll incur a dead
code warning when typechecking the block.
This commit:
- introduces a helper method to augment user-written stats with
synthetic code
- Emit a try/finally in that code (so we advance the state, even if we
are about to exit the state machine in the async-block global
exception handler
- Hide `Nothing` typed expressions from the dead code analysis
by wrapping them in an `expr: Any`
Fixes #150 (the part reported in the comments, not the original ticket.)
|
| |
| |
| |
| |
| |
| |
| |
| |
| | |
Don't bother adding `{ ...; () }` if we can use the original tree(s) instead,
e.g. if the last tree in `...` conforms to `Unit`.
This makes the debug output of the macro a little easier to read.
(cherry picked from commit de641dc265f34b06e17dfa7c64be00219f72b670)
|
|\ \
| | |
| | | |
bump/0.9.6-2.10
|
|/ /
| |
| | |
Bump to 0.9.6-SNAPSHOT
|
|\ \
| |/
|/| |
Backports for two recently fixed bugs.
|
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| | |
Code like:
val x = if (cond) throw new A else throw new B
Was being transformed to:
val ifRes = ???
if (cond) ifRes = throw new A else ifRes = throw new B
val x = ifRes
by way of the use of `gen.mkZero` which throws `???` if the requested type is `Nothing`
This commit special cases `Nothing` typed expressions in a similar manner to `Unit` type expressions.
The example above is now translated to:
if (cond) throw new A else throw new B
val x = throw new IllegalStateException()
Fixes #120
(cherry picked from commit 80aaf18d5111322baee73dad30eb0a81cdd62314)
|
|/
|
|
|
|
|
|
|
|
|
|
| |
The stack trace and bisection in #119 made me notice that we
are failing to typecheck the cast we generated in the fix for #74.
The ticket doesn't have a reproduction, so I'm submitting this
without a test case.
Fixes #119
(cherry picked from commit a037da192dbea32cffa8c5c8d33e7c56af0c353f)
|
|\
| |
| | |
Update SBT for the warn command, now assumed by sbt-extras
|
| |
| |
| |
| | |
(cherry picked from commit f6a5c93acb7628c4d169b778e386332c6d1bd99b)
|
|\ \
| |/
|/| |
Opt in to container based TravisCI
|
|/ |
|
|\
| |
| | |
Bump version to v0.9.5-SNAPSHOT
|
|/ |
|
|\
| |
| | |
Avoid compiler warning when awaiting Future[Unit]
|
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| | |
During the ANF transform, we were generating a tree of the shape:
{
val temp: Unit = await(futureOfUnit)
temp
()
}
I tried to simplifiy this to avoid creating the temporary value,
but this proved difficult as it would have required changes to
the subsequent state machine transformation.
Even replacing `temp` with `()` made the state machine transform
harder.
So for now, I've just inserted `temp.asInstanceOf[Unit]` to hide
from the compiler warning.
Fixes #74
(cherry picked from commit f3f058991b207a07041672a7e119422d9054788d)
|
|\ \
| | |
| | | |
[backport] Avoid masking real errors with NotImplemented awaiting Future[Nothing]
|
|/ /
| |
| |
| |
| |
| |
| |
| |
| |
| | |
Future[Nothing]
This commit disabled live variable analysis for intermediate values of type Nothing.
Fixes #104
(cherry picked from commit 6353443a0adec384172c38efac3bc96b9d2cbad2)
|
|\ \
| | |
| | | |
Fix compiler crash with value class in result position
|
| |/
| |
| |
| |
| |
| |
| |
| |
| | |
We were leaking untyped trees out of the macro, which crashed
in refchecks.
This commit proactively typechecks the tree returned by `mkZero`.
(cherry picked from commit f4275e22e000541eb619808723b70bd64b9b4873)
|
|/ |
|
|\
| |
| | |
Bump to 0.9.4-SNAPSHOT
|
|/ |
|
|\
| |
| | |
Support tag driven publishing
|
|/
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
I started with:
https://github.com/scala/scala-swing/commit/a6a8e1d77e#diff-3acefdae08499733e855dd23e1af933dR8
And:
- modified the regex that derives the version from the tag to
handle the fact we have the scala binary version appended to
our tags
- Removed unnessary cross building with Scala 2.11 (as this is
on the 2.10.x branch)
- generated a key pair for the async repository
- added passphrase for that key, and sonatype credentials, to
sensitive.sbt
- encrypted the secrets with the travis key.
|
|\
| |
| | |
Make `f(await(completedFuture))` execute `f` synchronously
|
| |
| |
| |
| |
| |
| | |
A worthy optimization, suggested by @danarmak.
Closes #73
|
| | |
|
|/
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Previously, as sequence of state transitions that did not pass through
an asynchrous boundary incurred stack frames. The trivial loop in
the enclosed test case would then overflow the stack.
This commit merges the `resume` and `apply(tr: Try[Any])` methods into
a `apply`. It changes the body of this method to be an infinite loop
with returns at the terminal points in the state machine (or at a
terminal failure.)
To allow merging of these previously separate matches, states that
contain an await are now allocated two state ids: one for the setup
code that calls `onComplete`, and one for the code in the continuation
that records the result and advances the state machine.
Fixes #93
|
|\
| |
| | |
Avoid assigning null to vars of derived value type
|
|/
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
`TreeGen#mkZero` returns `q"null"` for derived value classes.
```
scala> class V(val a: String) extends AnyVal
defined class V
scala> showRaw(gen.mkZero(typeOf[V]))
res0: String = Literal(Constant(null))
```
We use this API in async to generate the initial value for
ANF-lifted temporary variables.
However, this leads to NPEs, as after posterasure, we call the
unbox method on a null reference:
```
% cat sandbox/Macro.scala; scalac-hash v2.10.4 sandbox/Macro.scala; scala-hash v2.10.4 -e 'val x = Macros.myMacro'
import scala.reflect.macros.Context
import scala.language.experimental.macros
object Macros {
def macroImpl(c: Context): c.Expr[C] = {
import c.universe._
val e1 = c.Expr[C](Literal(Constant(null)).setType(typeOf[C]))
reify(e1.splice.asInstanceOf[C @annotation.unchecked.uncheckedVariance])
}
def myMacro: C = macro macroImpl
}
class C(val a: String) extends AnyVal
java.lang.NullPointerException
at Main$$anon$1.<init>(scalacmd4059893593754060829.scala:1)
at Main$.main(scalacmd4059893593754060829.scala:1)
at Main.main(scalacmd4059893593754060829.scala)
```
This commit installs a custom version of `mkZero` that instead
returns `q"new C[$..targs](${mkZero(wrappedType)})`.
Thanks to @ewiner for pinpointing the problem.
|
| |
|
| |
|
|\
| |
| | |
Fix regression around type skolems and if exprs.
|
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| | |
If we start with:
async({
val res = await[S[_$1 with String]](s);
if (true)
await[Int](0)
res
})
Typechecking the application (before macro expansion) yields
(where the trees are printed in the form `expr{tpe}`):
async[S[_$1#5738 with String#137]]({
val res: S[_$1#5490 with String] forSome { type _$1#5490 } =
await[S[_$1#5487 with String]](
s{S[_$1#5487 with String]}
){S[_$1#5487 with String]};
if (true)
await(0)
else
()
res{S[_$1#5738 with String]}
}{S[_$1#5738 with String]}){S[_$1#5738 with String]}
Note that the type of the second last line contains a skolemized
symbol `_$1#5738` of the existential `_$1#5490`. This is created
by this case in `Typer#adapt`:
case et @ ExistentialType(_, _) if ((mode & (EXPRmode | LHSmode)) == EXPRmode) =>
adapt(tree setType et.skolemizeExistential(context.owner, tree), mode, pt, original)
Our ANF rewrites part of this code to:
<synthetic> val await$1: S[_$1#5487 with String] = await[S[_$1#5487 with String]](awaitable$1);
val res: S[_$1#5490 with String] forSome { type _$1 } = await$1;
And later, the state machine transformation splits the last line into
a blank field and an assignment. Typechecking the `Assign` node
led to the an type error.
This commit manually attributes the types to the `Assign` node so
as to avoid these problem.
It also reigns in an overeager rewriting of `If` nodes in the
ANF transform, which was due to a bug in the label detection
logic introduced in 4fc5463538.
Thanks to @gnovark for yet another devilish test case and
analysis of the problem with label detection.
I worked on a more principled fix on:
https://github.com/retronym/async/compare/ticket/79-2?expand=1
in which I try to use `repackExistential` to convert skolemized
types to existentials for use as the types of synthetic vals
introduced by the ANF transform. This ran into a deeper problem
with existential subtyping in the compiler itself though.
|
|\ \
| | |
| | | |
Fix asymptotic performance issues in live variables analysis.
|
| |/
| |
| |
| |
| |
| |
| |
| |
| | |
Fix possibly-exponential runtime for DFS graph searches.
Improve DFA fixpoint algorithm to correctly compute worklist
of only changed nodes for each iteration.
Added test that takes > 2 minutes to compile without these
improvements.
|
|\ \
| |/
|/| |
Avoid NotImplementedError awaiting a Future[Nothing]
|
|/
|
|
|
|
|
| |
`gen.mkZero(NothingTpe)` gives the tree `Predef.???`. Instead, we should leave
the `await` field uninitialized with `ValDef(..., rhs = EmptyTree)`.
Fixes #66
|
| |
|
| |
|
|\
| |
| | |
[backport] Allow lazy vals without await in the initializer
|
| |
| |
| |
| |
| |
| |
| |
| |
| | |
- remove unneeded `setType(NoType)`, which was leftover from my
first attempts to find this bug.
- fix typo in error message
- optimize imports
(cherry picked from commit 5c6ea29966fa80faae13892da50fc68ed1bf9ae7)
|
|/
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
We were incorrectly typechecking the `ClassDef` of the state machine
in the macro in a way that discarded the resulting trees, and only
kept around the symbol.
The led to the the macro engine retypechecking
that node, which somehow led to duplicated lazy val initiaializer
`DefDef`-s in the template, which manifest as a `VerifyError`.
This commit:
- rescues the typechecked `ClassDef` node from the eager
typechecking by the macro
- loosens the restriction on lazy vals in async blocks. They are
still prohibited if they contain an await on the RHS
- Adds a test that shows evalution is indeed lazy.
(cherry picked from commit cc4587b1985519f7049d0feb0783d8e22c10f792)
Conflicts:
src/main/scala/scala/async/internal/AsyncAnalysis.scala
src/main/scala/scala/async/internal/AsyncTransform.scala
|
| |
|
| |
|
| |
|