scala/scala — pull request #4079 by retronym (2014-10-28 05:32:02+00:00)
Title: SI-8941 Idempotent presentation compilation of implicit classes

When we name an implicit class, `enterImplicitWrapper` is called,
which enters the symbol for the factory method is entered into the
owning scope. The tree defining this factory map is stowed into
`unit.synthetics`, from whence it will be retrieved and incorporated
into the enclosing tree during typechecking (`addDerivedTrees`).
The entry in `unit.synthetics` at that point.

However, in the presentation compiler, we can typecheck a unit
more than once in a single run. For example, if, as happens
in the enclosed test, a call to ask for a type at a given
position interrupts type checking of the entire unit, we
can get into a situation whereby the first type checking
invokation has consumed the entry from `unit.synthetics`,
and the second will crash when it can't find an entry.

Similar problems have been solved in the past by overriding
`enterExistingSym` in the presentation compiler. This method
is called when the namer encounters a tree that already has
a symbol attached. See 0b78a0196 / 148736c3df.

This commit takes a two pronged approach.

First, `enterExistingSym` is extended to handle implicit classes.
Any previous factory method in the owning scope is removed, and
`enterImplicitWrapper` is called to place a new tree for the factory
into `unit.synthetics` and to enter its symbol into the owning scope.

Secondly, the assertions that could be tripped in `addDerivedTrees`
and in `ImplicitClassWrapper#derivedSym` have been converted to
positioned errors.

The first change is sufficient to fix this bug, but the second
is also enough to make the enclosed test pass, and has been retained
as an extra layer of defence.

Review by @lrytz / @dragos