aboutsummaryrefslogtreecommitdiff
path: root/src/dotty/tools/dotc
diff options
context:
space:
mode:
authorGuillaume Martres <smarter@ubuntu.com>2015-04-03 23:20:24 +0200
committerDmitry Petrashko <dmitry.petrashko@gmail.com>2015-05-01 13:27:42 +0200
commit3fca64e2dfd53e376b3a45605100ef6f768b07a4 (patch)
tree6c842827c767bd228ac9dcb8fc4e65df4c1d4a07 /src/dotty/tools/dotc
parent8bd4139db4dd89e83b71a49b39c0747b9f5fc68a (diff)
downloaddotty-3fca64e2dfd53e376b3a45605100ef6f768b07a4.tar.gz
dotty-3fca64e2dfd53e376b3a45605100ef6f768b07a4.tar.bz2
dotty-3fca64e2dfd53e376b3a45605100ef6f768b07a4.zip
Make ExtensionMethods#extensionMethods an object method
This method will be needed to implement VCInline.
Diffstat (limited to 'src/dotty/tools/dotc')
-rw-r--r--src/dotty/tools/dotc/core/Phases.scala2
-rw-r--r--src/dotty/tools/dotc/transform/ExtensionMethods.scala121
-rw-r--r--src/dotty/tools/dotc/transform/FullParameterization.scala21
3 files changed, 76 insertions, 68 deletions
diff --git a/src/dotty/tools/dotc/core/Phases.scala b/src/dotty/tools/dotc/core/Phases.scala
index 96066db5e..406a3457a 100644
--- a/src/dotty/tools/dotc/core/Phases.scala
+++ b/src/dotty/tools/dotc/core/Phases.scala
@@ -232,6 +232,7 @@ object Phases {
private val typerCache = new PhaseCache(classOf[FrontEnd])
private val refChecksCache = new PhaseCache(classOf[RefChecks])
+ private val extensionMethodsCache = new PhaseCache(classOf[ExtensionMethods])
private val erasureCache = new PhaseCache(classOf[Erasure])
private val patmatCache = new PhaseCache(classOf[PatternMatcher])
private val flattenCache = new PhaseCache(classOf[Flatten])
@@ -241,6 +242,7 @@ object Phases {
def typerPhase = typerCache.phase
def refchecksPhase = refChecksCache.phase
+ def extensionMethodsPhase = extensionMethodsCache.phase
def erasurePhase = erasureCache.phase
def patmatPhase = patmatCache.phase
def flattenPhase = flattenCache.phase
diff --git a/src/dotty/tools/dotc/transform/ExtensionMethods.scala b/src/dotty/tools/dotc/transform/ExtensionMethods.scala
index 724f3fc64..b2f402bc5 100644
--- a/src/dotty/tools/dotc/transform/ExtensionMethods.scala
+++ b/src/dotty/tools/dotc/transform/ExtensionMethods.scala
@@ -36,6 +36,7 @@ import SymUtils._
class ExtensionMethods extends MiniPhaseTransform with DenotTransformer with FullParameterization { thisTransformer =>
import tpd._
+ import ExtensionMethods._
/** the following two members override abstract members in Transform */
override def phaseName: String = "extmethods"
@@ -89,65 +90,6 @@ class ExtensionMethods extends MiniPhaseTransform with DenotTransformer with Ful
target.owner.linkedClass == derived.owner) extensionMethod(target)
else NoSymbol
- /** Generate stream of possible names for the extension version of given instance method `imeth`.
- * If the method is not overloaded, this stream consists of just "imeth$extension".
- * If the method is overloaded, the stream has as first element "imeth$extenionX", where X is the
- * index of imeth in the sequence of overloaded alternatives with the same name. This choice will
- * always be picked as the name of the generated extension method.
- * After this first choice, all other possible indices in the range of 0 until the number
- * of overloaded alternatives are returned. The secondary choices are used to find a matching method
- * in `extensionMethod` if the first name has the wrong type. We thereby gain a level of insensitivity
- * of how overloaded types are ordered between phases and picklings.
- */
- private def extensionNames(imeth: Symbol)(implicit ctx: Context): Stream[Name] = {
- val decl = imeth.owner.info.decl(imeth.name)
-
- /** No longer needed for Dotty, as we are more disciplined with scopes now.
- // Bridge generation is done at phase `erasure`, but new scopes are only generated
- // for the phase after that. So bridges are visible in earlier phases.
- //
- // `info.member(imeth.name)` filters these out, but we need to use `decl`
- // to restrict ourselves to members defined in the current class, so we
- // must do the filtering here.
- val declTypeNoBridge = decl.filter(sym => !sym.isBridge).tpe
- */
- decl match {
- case decl: MultiDenotation =>
- val alts = decl.alternatives
- val index = alts indexOf imeth.denot
- assert(index >= 0, alts + " does not contain " + imeth)
- def altName(index: Int) = (imeth.name + "$extension" + index).toTermName
- altName(index) #:: ((0 until alts.length).toStream filter (index != _) map altName)
- case decl =>
- assert(decl.exists, imeth.name + " not found in " + imeth.owner + "'s decls: " + imeth.owner.info.decls)
- Stream((imeth.name + "$extension").toTermName)
- }
- }
-
- /** Return the extension method that corresponds to given instance method `meth`. */
- def extensionMethod(imeth: Symbol)(implicit ctx: Context): TermSymbol =
- ctx.atPhase(thisTransformer.next) { implicit ctx =>
- // FIXME use toStatic instead?
- val companionInfo = imeth.owner.companionModule.info
- val candidates = extensionNames(imeth) map (companionInfo.decl(_).symbol) filter (_.exists)
- val matching = candidates filter (c => memberSignature(c.info) == imeth.signature)
- assert(matching.nonEmpty,
- sm"""|no extension method found for:
- |
- | $imeth:${imeth.info.show} with signature ${imeth.signature}
- |
- | Candidates:
- |
- | ${candidates.map(c => c.name + ":" + c.info.show).mkString("\n")}
- |
- | Candidates (signatures normalized):
- |
- | ${candidates.map(c => c.name + ":" + c.info.signature + ":" + memberSignature(c.info)).mkString("\n")}
- |
- | Eligible Names: ${extensionNames(imeth).mkString(",")}""")
- matching.head.asTerm
- }
-
private def createExtensionMethod(imeth: Symbol, staticClass: Symbol)(implicit ctx: Context): TermSymbol = {
assert(ctx.phase == thisTransformer.next)
val extensionName = extensionNames(imeth).head.toTermName
@@ -209,3 +151,64 @@ class ExtensionMethods extends MiniPhaseTransform with DenotTransformer with Ful
} else tree
}
}
+
+object ExtensionMethods {
+ /** Generate stream of possible names for the extension version of given instance method `imeth`.
+ * If the method is not overloaded, this stream consists of just "imeth$extension".
+ * If the method is overloaded, the stream has as first element "imeth$extenionX", where X is the
+ * index of imeth in the sequence of overloaded alternatives with the same name. This choice will
+ * always be picked as the name of the generated extension method.
+ * After this first choice, all other possible indices in the range of 0 until the number
+ * of overloaded alternatives are returned. The secondary choices are used to find a matching method
+ * in `extensionMethod` if the first name has the wrong type. We thereby gain a level of insensitivity
+ * of how overloaded types are ordered between phases and picklings.
+ */
+ private def extensionNames(imeth: Symbol)(implicit ctx: Context): Stream[Name] = {
+ val decl = imeth.owner.info.decl(imeth.name)
+
+ /** No longer needed for Dotty, as we are more disciplined with scopes now.
+ // Bridge generation is done at phase `erasure`, but new scopes are only generated
+ // for the phase after that. So bridges are visible in earlier phases.
+ //
+ // `info.member(imeth.name)` filters these out, but we need to use `decl`
+ // to restrict ourselves to members defined in the current class, so we
+ // must do the filtering here.
+ val declTypeNoBridge = decl.filter(sym => !sym.isBridge).tpe
+ */
+ decl match {
+ case decl: MultiDenotation =>
+ val alts = decl.alternatives
+ val index = alts indexOf imeth.denot
+ assert(index >= 0, alts + " does not contain " + imeth)
+ def altName(index: Int) = (imeth.name + "$extension" + index).toTermName
+ altName(index) #:: ((0 until alts.length).toStream filter (index != _) map altName)
+ case decl =>
+ assert(decl.exists, imeth.name + " not found in " + imeth.owner + "'s decls: " + imeth.owner.info.decls)
+ Stream((imeth.name + "$extension").toTermName)
+ }
+ }
+
+ /** Return the extension method that corresponds to given instance method `meth`. */
+ def extensionMethod(imeth: Symbol)(implicit ctx: Context): TermSymbol =
+ ctx.atPhase(ctx.extensionMethodsPhase.next) { implicit ctx =>
+ // FIXME use toStatic instead?
+ val companionInfo = imeth.owner.companionModule.info
+ val candidates = extensionNames(imeth) map (companionInfo.decl(_).symbol) filter (_.exists)
+ val matching = candidates filter (c => FullParameterization.memberSignature(c.info) == imeth.signature)
+ assert(matching.nonEmpty,
+ sm"""|no extension method found for:
+ |
+ | $imeth:${imeth.info.show} with signature ${imeth.signature}
+ |
+ | Candidates:
+ |
+ | ${candidates.map(c => c.name + ":" + c.info.show).mkString("\n")}
+ |
+ | Candidates (signatures normalized):
+ |
+ | ${candidates.map(c => c.name + ":" + c.info.signature + ":" + FullParameterization.memberSignature(c.info)).mkString("\n")}
+ |
+ | Eligible Names: ${extensionNames(imeth).mkString(",")}""")
+ matching.head.asTerm
+ }
+}
diff --git a/src/dotty/tools/dotc/transform/FullParameterization.scala b/src/dotty/tools/dotc/transform/FullParameterization.scala
index f46942fb3..d402c2e7f 100644
--- a/src/dotty/tools/dotc/transform/FullParameterization.scala
+++ b/src/dotty/tools/dotc/transform/FullParameterization.scala
@@ -52,6 +52,7 @@ import ast.Trees._
trait FullParameterization {
import tpd._
+ import FullParameterization._
/** If references to original symbol `referenced` from within fully parameterized method
* `derived` should be rewired to some fully parameterized method, the rewiring target symbol,
@@ -124,15 +125,6 @@ trait FullParameterization {
}
}
- /** Assuming `info` is a result of a `fullyParameterizedType` call, the signature of the
- * original method type `X` such that `info = fullyParameterizedType(X, ...)`.
- */
- def memberSignature(info: Type)(implicit ctx: Context): Signature = info match {
- case info: PolyType => memberSignature(info.resultType)
- case info @ MethodType(nme.SELF :: Nil, _) => info.resultType.ensureMethodic.signature
- case _ => Signature.NotAMethod
- }
-
/** The type parameters (skolems) of the method definition `originalDef`,
* followed by the class parameters of its enclosing class.
*/
@@ -230,3 +222,14 @@ trait FullParameterization {
.appliedToArgss(originalDef.vparamss.nestedMap(vparam => ref(vparam.symbol)))
.withPos(originalDef.rhs.pos)
}
+
+object FullParameterization {
+ /** Assuming `info` is a result of a `fullyParameterizedType` call, the signature of the
+ * original method type `X` such that `info = fullyParameterizedType(X, ...)`.
+ */
+ def memberSignature(info: Type)(implicit ctx: Context): Signature = info match {
+ case info: PolyType => memberSignature(info.resultType)
+ case info @ MethodType(nme.SELF :: Nil, _) => info.resultType.ensureMethodic.signature
+ case _ => Signature.NotAMethod
+ }
+}