Permalink
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 {
matching.head
}
/** 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 thiz.name == nme.SELF =>
restpe
case MethodType(tparams, restpe) =>
MethodType(tparams.drop(1), restpe)
case _ =>
stpe
}
@@ -821,6 +821,7 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers {
debuglog("%s expands to %s in %s".format(sym, specMember.name.decode, pp(env)))
info(specMember) = NormalizedMember(sym)
overloads(sym) ::= Overload(specMember, env)
owner.info.decls.enter(specMember)
specMember
}
}
View
@@ -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.