scala/async — pull request #80 by retronym (2014-07-15 13:41:31+00:00)
Title: 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:

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.