Skip to content
Browse files

Fix SI-5853.

This solves two issues.

First, up to now the newly generated symbols for normalized
members were not being added to the declaration list of the
owner during `specialize`. Now they are.

Second, during `extmethods`, the extension methods generated
get an additional curried parameter list for `$this`.
Trouble was, after that, during `uncurry` and before `specialize`,
these curried parameter lists were merged into one list.
Specialization afterwards treats extension methods just
like normal methods and generates new symbols without the
curried parameter list.
The `extensionMethod` now takes this into account by checking
if the first parameter of a potential extension method has
the name `$this`.

Review by @dragos.
Review by @odersky.
  • Loading branch information
axel22 committed Jun 7, 2012
1 parent 6cdb6b0 commit dab1d0361ff74a2e4500255beba65389f44f34cc
@@ -77,11 +77,26 @@ abstract class ExtensionMethods extends Transform with TypingTransformers {

/** This method removes the `$this` argument from the parameter list a method.
* A method may be a `PolyType`, in which case we tear out the `$this` and the class
* type params from its nested `MethodType`.
* It may be a `MethodType`, either with a curried parameter list in which the first argument
* is a `$this` - we just return the rest of the list.
* This means that the corresponding symbol was generated during `extmethods`.
* It may also be a `MethodType` in which the `$this` does not appear in a curried parameter list.
* The curried lists disappear during `uncurry`, and the methods may be duplicated afterwards,
* for instance, during `specialize`.
* In this case, the first argument is `$this` and we just get rid of it.
private def normalize(stpe: Type, clazz: Symbol): Type = stpe match {
case PolyType(tparams, restpe) =>
GenPolyType(tparams dropRight clazz.typeParams.length, normalize(restpe.substSym(tparams takeRight clazz.typeParams.length, clazz.typeParams), clazz))
case MethodType(tparams, restpe) =>
case MethodType(List(thiz), restpe) if == nme.SELF =>
case MethodType(tparams, restpe) =>
MethodType(tparams.drop(1), restpe)
case _ =>
@@ -821,6 +821,7 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers {
debuglog("%s expands to %s in %s".format(sym,, pp(env)))
info(specMember) = NormalizedMember(sym)
overloads(sym) ::= Overload(specMember, env)
@@ -0,0 +1,55 @@

final class C(val x: Int) extends AnyVal {
def ppp[@specialized(Int) T](y: T) = ()

class Foo {
def f = new C(1) ppp 2

/* Original SI-5853 test-case. */

object Bippy {
implicit final class C(val x: Int) extends AnyVal {
def +++[@specialized T](y: T) = ()
def f = 1 +++ 2

/* Few more examples. */

final class C2(val x: Int) extends AnyVal {
def +++[@specialized(Int) T](y: T) = ()

class Foo2 {
def f = new C2(1) +++ 2

object Arrow {
implicit final class ArrowAssoc[A](val __leftOfArrow: A) extends AnyVal {
@inline def ->>[B](y: B): Tuple2[A, B] = Tuple2(__leftOfArrow, y)

def foo = 1 ->> 2

object SpecArrow {
implicit final class ArrowAssoc[A](val __leftOfArrow: A) extends AnyVal {
@inline def ->> [@specialized(Int) B](y: B): Tuple2[A, B] = Tuple2(__leftOfArrow, y)

def foo = 1 ->> 2

0 comments on commit dab1d03

Please sign in to comment.
You can’t perform that action at this time.