summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorJames Iry <jamesiry@gmail.com>2013-01-29 16:58:54 -0800
committerJames Iry <jamesiry@gmail.com>2013-01-29 16:58:54 -0800
commit7026376dcc87f531de84c99aa3e52068f5b10874 (patch)
treeeeb9dbcb2553b5771cd337eb53cd5d97aa17aa35 /src
parentc1dd8bbaa4cc688ab05fc325a02e20b91488a583 (diff)
parentcfaa3b5408eb3e6eabe108d3adcb06fdcafe912a (diff)
downloadscala-7026376dcc87f531de84c99aa3e52068f5b10874.tar.gz
scala-7026376dcc87f531de84c99aa3e52068f5b10874.tar.bz2
scala-7026376dcc87f531de84c99aa3e52068f5b10874.zip
Merge pull request #1912 from retronym/ticket/6651
SI-6651 Extension methods types may depend on the typed of the wrapped value
Diffstat (limited to 'src')
-rw-r--r--src/compiler/scala/tools/nsc/transform/ExtensionMethods.scala37
1 files changed, 30 insertions, 7 deletions
diff --git a/src/compiler/scala/tools/nsc/transform/ExtensionMethods.scala b/src/compiler/scala/tools/nsc/transform/ExtensionMethods.scala
index 39e16c3f58..589aa43ac2 100644
--- a/src/compiler/scala/tools/nsc/transform/ExtensionMethods.scala
+++ b/src/compiler/scala/tools/nsc/transform/ExtensionMethods.scala
@@ -75,7 +75,19 @@ abstract class ExtensionMethods extends Transform with TypingTransformers {
val candidates = extensionNames(imeth) map (companionInfo.decl(_)) filter (_.exists)
val matching = candidates filter (alt => normalize(alt.tpe, imeth.owner) matches imeth.tpe)
assert(matching.nonEmpty,
- s"no extension method found for $imeth:${imeth.tpe} among ${candidates.map(c => c.name+":"+c.tpe).toList} / ${extensionNames(imeth).toList}")
+ sm"""|no extension method found for:
+ |
+ | $imeth:${imeth.tpe}
+ |
+ | Candidates:
+ |
+ | ${candidates.map(c => c.name+":"+c.tpe).mkString("\n")}
+ |
+ | Candidates (signatures normalized):
+ |
+ | ${candidates.map(c => c.name+":"+normalize(c.tpe, imeth.owner)).mkString("\n")}
+ |
+ | Eligible Names: ${extensionNames(imeth).mkString(",")}"""")
matching.head
}
@@ -94,11 +106,18 @@ abstract class ExtensionMethods extends Transform with TypingTransformers {
*/
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))
+ // Split the type parameters of the extension method into two groups,
+ // corresponding the to class and method type parameters.
+ val numClassParams = clazz.typeParams.length
+ val methTParams = tparams dropRight numClassParams
+ val classTParams = tparams takeRight numClassParams
+
+ GenPolyType(methTParams,
+ normalize(restpe.substSym(classTParams, clazz.typeParams), clazz))
case MethodType(List(thiz), restpe) if thiz.name == nme.SELF =>
- restpe
- case MethodType(tparams, restpe) =>
- MethodType(tparams.drop(1), restpe)
+ restpe.substituteTypes(thiz :: Nil, clazz.thisType :: Nil)
+ case MethodType(thiz :: params, restpe) =>
+ MethodType(params, restpe)
case _ =>
stpe
}
@@ -128,7 +147,11 @@ abstract class ExtensionMethods extends Transform with TypingTransformers {
MethodType(List(thisParam), restpe)
}
val GenPolyType(tparams, restpe) = origInfo cloneInfo extensionMeth
- GenPolyType(tparams ::: newTypeParams, transform(restpe) substSym (clazz.typeParams, newTypeParams))
+ val selfParamSingletonType = singleType(currentOwner.companionModule.thisType, thisParam)
+ GenPolyType(
+ tparams ::: newTypeParams,
+ transform(restpe) substThisAndSym (clazz, selfParamSingletonType, clazz.typeParams, newTypeParams)
+ )
}
private def allParams(tpe: Type): List[Symbol] = tpe match {
@@ -162,7 +185,7 @@ abstract class ExtensionMethods extends Transform with TypingTransformers {
origMeth.defString,
extensionMeth.defString)) // extensionMeth.defStringSeenAs(origInfo
- def thisParamRef = gen.mkAttributedIdent(extensionMeth.info.params.head setPos extensionMeth.pos)
+ def thisParamRef = gen.mkAttributedStableRef(extensionMeth.info.params.head setPos extensionMeth.pos)
val GenPolyType(extensionTpeParams, extensionMono) = extensionMeth.info
val origTpeParams = (tparams map (_.symbol)) ::: currentOwner.typeParams
val extensionBody = rhs