Description
Every usage of TreeTypeMap
is affected, even if run using atGroupEnd
like we do in ExtensionMethods
, so this is a different issue than #1770:
class FF[R] {
def compose(): R = ???
}
class Test(x: Int) extends AnyVal {
def method: Unit = {
class Bla
class Foo extends FF[Bla] {
override def compose() = super[FF].compose()
}
}
}
This fails -Ycheck:tailrec
with:
java.lang.AssertionError: assertion failed:
found: Bla
required: Bla'
where: Bla is a class in method method
Bla' is a class in method method$extension
tree = super[FF].compose()
It's pretty hard to understand what's going on here but I think I've narrowed it down to mapSymbols
, recall that it works in three steps:
- Create new naked symbols for each symbol in
original
- Set the denotation of each of the copies to the original denotation
- Create a new denotation for each of the copy where we set their info using the
TreeTypeMap
, etc.
The issue happens in 3., to create the new infos we map over the old infos (info = ttmap1.mapType(oinfo)
) for each symbol in order, but when we map over the info of one mapped symbol, we may end up looking at another mapped symbol whose denotation is still set to the original denotation, even if we don't end up taking any decision based on that symbol denotation we may end up corrupting some cache (for example, NamedType
cache denotations).
More specifically, in the example above:
class Foo
is in a method that becomes an extension method, so its symbol ends up being transformed byTreeTypeMap
- In
TreeTypeMap#withMappedSyms
we callmapSymbols
with every declaration inFoo
, in the list of declarationscompose
appears beforeFF$R
, this is important. - Inside
mapSymbols
we get to the step 3 explained above, we map the info ofcompose
which is()Foo.this.FF$R
, this is done successfully but note that at this point the denotation of the new symbol forFF$R
is still incorrect, andFoo.this.FF$R
is aNamedType
which means that we cache its denotation. - Still inside
mapSymbols
we correctly set the denotation of the new symbol forFF$R
but it's too late.
Later in TreeChecker
when we look at the type of super[FF].compose()
we get the old cached denotation which points to the old symbol for Bla
, thus the error.