diff options
author | Jason Zaugg <jzaugg@gmail.com> | 2014-07-01 16:45:33 -0400 |
---|---|---|
committer | Jason Zaugg <jzaugg@gmail.com> | 2014-07-18 16:03:02 +0200 |
commit | 1df849070694756533003c9c331cd04d0c3136e8 (patch) | |
tree | 7b42b9eded651b47739d5bb62ef4f8268cb058f3 /src/main/scala/scala/async/internal/TransformUtils.scala | |
parent | f77d11962a3bf73c813a42a05e842ce710588c3f (diff) | |
download | scala-async-1df849070694756533003c9c331cd04d0c3136e8.tar.gz scala-async-1df849070694756533003c9c331cd04d0c3136e8.tar.bz2 scala-async-1df849070694756533003c9c331cd04d0c3136e8.zip |
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.
Diffstat (limited to 'src/main/scala/scala/async/internal/TransformUtils.scala')
-rw-r--r-- | src/main/scala/scala/async/internal/TransformUtils.scala | 2 |
1 files changed, 1 insertions, 1 deletions
diff --git a/src/main/scala/scala/async/internal/TransformUtils.scala b/src/main/scala/scala/async/internal/TransformUtils.scala index f228e1d..bef52f1 100644 --- a/src/main/scala/scala/async/internal/TransformUtils.scala +++ b/src/main/scala/scala/async/internal/TransformUtils.scala @@ -100,7 +100,7 @@ private[async] trait TransformUtils { case ld: LabelDef => ld.symbol }.toSet t.exists { - case rt: RefTree => !(labelDefs contains rt.symbol) + case rt: RefTree => rt.symbol != null && rt.symbol.isLabel && !(labelDefs contains rt.symbol) case _ => false } } |