diff options
author | Aleksandar Prokopec <axel22@gmail.com> | 2012-06-07 19:59:49 +0200 |
---|---|---|
committer | Aleksandar Prokopec <axel22@gmail.com> | 2012-06-07 20:43:26 +0200 |
commit | dab1d0361ff74a2e4500255beba65389f44f34cc (patch) | |
tree | 66a4857ade783e600de355ef8648767cbddf78f8 | |
parent | 6cdb6b0299cb917ac3df9e39aa932bacdc31faf9 (diff) | |
download | scala-dab1d0361ff74a2e4500255beba65389f44f34cc.tar.gz scala-dab1d0361ff74a2e4500255beba65389f44f34cc.tar.bz2 scala-dab1d0361ff74a2e4500255beba65389f44f34cc.zip |
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.
-rw-r--r-- | src/compiler/scala/tools/nsc/transform/ExtensionMethods.scala | 17 | ||||
-rw-r--r-- | src/compiler/scala/tools/nsc/transform/SpecializeTypes.scala | 1 | ||||
-rw-r--r-- | test/files/pos/t5853.scala | 55 |
3 files changed, 72 insertions, 1 deletions
diff --git a/src/compiler/scala/tools/nsc/transform/ExtensionMethods.scala b/src/compiler/scala/tools/nsc/transform/ExtensionMethods.scala index 8556cc9ddc..7e0b87dbe1 100644 --- a/src/compiler/scala/tools/nsc/transform/ExtensionMethods.scala +++ b/src/compiler/scala/tools/nsc/transform/ExtensionMethods.scala @@ -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 } diff --git a/src/compiler/scala/tools/nsc/transform/SpecializeTypes.scala b/src/compiler/scala/tools/nsc/transform/SpecializeTypes.scala index f2e109a5ad..60461a524b 100644 --- a/src/compiler/scala/tools/nsc/transform/SpecializeTypes.scala +++ b/src/compiler/scala/tools/nsc/transform/SpecializeTypes.scala @@ -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 } } diff --git a/test/files/pos/t5853.scala b/test/files/pos/t5853.scala new file mode 100644 index 0000000000..21d80206ab --- /dev/null +++ b/test/files/pos/t5853.scala @@ -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 +} |