summaryrefslogtreecommitdiff
path: root/test/files/run/t8710.scala
Commit message (Collapse)AuthorAgeFilesLines
* SI-8710 Fix crasher for value classes + private + overloadingJason Zaugg2014-07-111-0/+17
The link between methods owned by a value class and the corresponding extension method in the companion is governed in part by a naming convention that depends on how many eponymous decls exist. This is easiest to explain with an example: % cat sandbox/test.scala && \ qscalac -Xprint:extmethods sandbox/test.scala \ | egrep 'class|object|def (foo|bar)|}$' class C(val x: Any) extends AnyVal { def foo(a: Int) = "" def foo(a: String) = "" def bar(a: Byte) } final class C extends scala.AnyVal { def foo(a: Int): String = C.foo$extension0(C.this)(a); def foo(a: String): String = C.foo$extension1(C.this)(a); def bar(a: Byte): Unit = C.bar$extension(C.this)(a); } <synthetic> object C extends AnyRef { final def foo$extension0($this: C)(a: Int): String = ""; final def foo$extension1($this: C)(a: String): String = ""; final def bar$extension($this: C)(a: Byte): Unit = (<empty>.asInstanceOf[Unit]: Unit); } } } Notice how the extension method names for `foo` are suffixed with a counter. This logic is contained in `extensionNames`. However, in the enclosed test cases, when we call `extensionNames` in a late phase of the compiler, in particular during erasure when we rewire `new C(x).foo(args)` to `C.foo$extensionN(x)(args)`, we crash. Why? The private method in the value class has been name mangled by `ExplicitOuter`'s use of `makeNotPrivate`, and we no longer appear to have multiple eponymous methods in play. We could try to fix this by changing `extensionNames` to poke around through the scopes of the value class and its companion in a manner insensitive to expanded names. This might look something like: - info.decl(imeth.name) + newOverloadedSymbol(info.decls.filter(sym => unexpandedName(sym) == unexpandedName(imeth.name)) But in fact we never need to expand the name of a private method in an value class, nor its corresponding companion, as: - calls to private value class members end up as calls to public extension methods - extension methods already have a the `$extension[N]` suffix and need no further mangling. This commit: - Resets `PRIVATE` and `LOCAL` when deriving the extension method - Adds a special case to `ExplicitOuter` to imbue the special knowledge that a call to `SomeValueClass#somePrivateMethod` need not `makeNotPrivate`, as erasure will come along later and rewire that to a (public) extension method.